perf scripts: Add python scripts for CoreSight traces
authortor-jeremiassen <tor@ti.com>
Wed, 17 Feb 2016 16:58:21 +0000 (10:58 -0600)
committerMathieu Poirier <mathieu.poirier@linaro.org>
Mon, 20 Jun 2016 17:16:06 +0000 (11:16 -0600)
Example scripts for CoreSight trace processing with perf script.

Signed-off-by: Tor Jeremiassen <tor@ti.com>
tools/perf/scripts/python/cs-trace-disasm.py [new file with mode: 0644]
tools/perf/scripts/python/cs-trace-ranges.py [new file with mode: 0644]

diff --git a/tools/perf/scripts/python/cs-trace-disasm.py b/tools/perf/scripts/python/cs-trace-disasm.py
new file mode 100644 (file)
index 0000000..175ae4b
--- /dev/null
@@ -0,0 +1,122 @@
+# perf script event handlers, generated by perf script -g python
+# Licensed under the terms of the GNU GPL License version 2
+
+# The common_* event handler fields are the most useful fields common to
+# all events.  They don't necessarily correspond to the 'common_*' fields
+# in the format files.  Those fields not available as handler params can
+# be retrieved using Python functions of the form common_*(context).
+# See the perf-trace-python Documentation for the list of available functions.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+                '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from subprocess import *
+from Core import *
+import re;
+
+from optparse import OptionParser
+
+#
+# Add options to specify vmlinux file and the objdump executable
+#
+parser = OptionParser()
+parser.add_option("-k", "--vmlinux", dest="vmlinux_name",
+                  help="path to vmlinux file")
+parser.add_option("-d", "--objdump", dest="objdump_name",
+                  help="name of objdump executable (in path)")
+(options, args) = parser.parse_args()
+
+if (options.objdump_name == None):
+        sys.exit("No objdump executable specified - use -d or --objdump option")
+
+# initialize global dicts and regular expression
+
+build_ids = dict();
+mmaps = dict();
+disasm_cache = dict();
+disasm_re = re.compile("^\s*([0-9a-fA-F]+):")
+
+cache_size = 16*1024
+
+def trace_begin():
+        cmd_output = check_output(["perf", "buildid-list"]).split('\n');
+        bid_re = re.compile("([a-fA-f0-9]+)[ \t]([^ \n]+)")
+        for line in cmd_output:
+                m = bid_re.search(line)
+                if (m != None) :
+                        build_ids[m.group(2)] =  \
+                        os.environ['PERF_BUILDID_DIR'] +  \
+                        m.group(2) + "/" + m.group(1);
+
+        if ((options.vmlinux_name != None) and ("[kernel.kallsyms]" in build_ids)):
+                build_ids['[kernel.kallsyms]'] = options.vmlinux_name;
+        else:
+                del build_ids['[kernel.kallsyms]']
+
+        mmap_re = re.compile("PERF_RECORD_MMAP2 -?[0-9]+/[0-9]+: \[(0x[0-9a-fA-F]+).*:\s.*\s(.*.so)")
+        cmd_output= check_output("perf script --show-mmap-events | fgrep PERF_RECORD_MMAP2",shell=True).split('\n')
+        for line in cmd_output:
+                m = mmap_re.search(line)
+                if (m != None) :
+                        mmaps[m.group(2)] = int(m.group(1),0)
+
+
+
+def trace_end():
+        pass
+
+def process_event(t):
+        global cache_size
+        global options 
+
+        sample = t['sample']
+        dso = t['dso']
+
+        # don't let the cache get too big, but don't bother with a fancy replacement policy
+        # just clear it when it hits max size
+
+        if (len(disasm_cache) > cache_size):
+                disasm_cache.clear();
+
+        addr_range = format(sample['ip'],"x")  + ":" + format(sample['addr'],"x");
+
+        try:
+                disasm_output = disasm_cache[addr_range];
+        except:
+                try:
+                        fname = build_ids[dso];
+                except KeyError:
+                        if (dso == '[kernel.kallsyms]'):
+                                return;
+                        fname = dso;
+
+                if (dso in mmaps):
+                        offset = mmaps[dso];
+                        disasm = [options.objdump_name,"-d","-z", "--adjust-vma="+format(offset,"#x"),"--start-address="+format(sample['ip'],"#x"),"--stop-address="+format(sample['addr'],"#x"), fname]
+                else:
+                        offset = 0
+                        disasm = [options.objdump_name,"-d","-z", "--start-address="+format(sample['ip'],"#x"),"--stop-address="+format(sample['addr'],"#x"),fname] 
+                disasm_output = check_output(disasm).split('\n')
+                disasm_cache[addr_range] = disasm_output;
+
+        for line in disasm_output:
+                m = disasm_re.search(line)
+                if (m != None) :
+                        try:
+                                print "\t",line
+                        except:
+                                exit(1);
+                else:
+                        continue;
+
+def trace_unhandled(event_name, context, event_fields_dict):
+               print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
+
+def print_header(event_name, cpu, secs, nsecs, pid, comm):
+        print "print_header"
+       print "%-20s %5u %05u.%09u %8u %-20s " % \
+       (event_name, cpu, secs, nsecs, pid, comm),
diff --git a/tools/perf/scripts/python/cs-trace-ranges.py b/tools/perf/scripts/python/cs-trace-ranges.py
new file mode 100644 (file)
index 0000000..c8edacb
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Copyright(C) 2016 Linaro Limited. All rights reserved.
+# Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+                '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+
+def trace_begin():
+        pass;
+
+def trace_end():
+        pass
+
+def process_event(t):
+
+        sample = t['sample']
+
+        print "range:",format(sample['ip'],"x"),"-",format(sample['addr'],"x")
+
+def trace_unhandled(event_name, context, event_fields_dict):
+               print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
+
+def print_header(event_name, cpu, secs, nsecs, pid, comm):
+        print "print_header"
+       print "%-20s %5u %05u.%09u %8u %-20s " % \
+       (event_name, cpu, secs, nsecs, pid, comm),