aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/scripts/python/cs-trace-disasm.py
blob: 429d0d2d7a23e7f99dd74ac1e59468847b48de2b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 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();

        cpu = format(sample['cpu'], "d");
        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;

        print "FILE: %s\tCPU: %s" % (dso, cpu);
        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),