# 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),