mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
This patch adds the required mechanic to quickly lookup the CPU number
associated with a traceID. That way the CPU that executed the code
conveyed by a decoded packet can be identified, without having to
do unecessary translations.
Using this new functionality the "cs-trace-disasm.py" script is
enhanced to output the file and CPU number the code has been
executed on:
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
7fab57fd80: 910003e0 mov x0, sp
7fab57fd84: 94000d53 bl 7fab5832d0 <free@plt+0x3790>
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
7fab5832d0: d11203ff sub sp, sp, #0x480
FILE: /lib/aarch64-linux-gnu/ld-2.21.so CPU: 3
7fab5832d4: a9ba7bfd stp x29, x30, [sp,#-96]!
7fab5832d8: 910003fd mov x29, sp
7fab5832dc: a90363f7 stp x23, x24, [sp,#48]
7fab5832e0: 9101e3b7 add x23, x29, #0x78
7fab5832e4: a90573fb stp x27, x28, [sp,#80]
7fab5832e8: a90153f3 stp x19, x20, [sp,#16]
7fab5832ec: aa0003fb mov x27, x0
7fab5832f0: 910a82e1 add x1, x23, #0x2a0
7fab5832f4: a9025bf5 stp x21, x22, [sp,#32]
7fab5832f8: a9046bf9 stp x25, x26, [sp,#64]
7fab5832fc: 910102e0 add x0, x23, #0x40
7fab583300: f800841f str xzr, [x0],#8
7fab583304: eb01001f cmp x0, x1
7fab583308: 54ffffc1 b.ne 7fab583300 <free@plt+0x37c0>
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
125 lines
4.5 KiB
Python
125 lines
4.5 KiB
Python
# 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),
|