1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# profile Profile CPU usage by sampling stack traces at a timed interval. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, BPF, perf_events. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# This is an efficient profiler, as stack traces are frequency counted in 8*387f9dfdSAndroid Build Coastguard Worker# kernel context, rather than passing every stack to user space for frequency 9*387f9dfdSAndroid Build Coastguard Worker# counting there. Only the unique stacks and counts are passed to user space 10*387f9dfdSAndroid Build Coastguard Worker# at the end of the profile, greatly reducing the kernel<->user transfer. 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# This uses perf_event_open to setup a timer which is instrumented by BPF, 13*387f9dfdSAndroid Build Coastguard Worker# and for efficiency it does not initialize the perf ring buffer, so the 14*387f9dfdSAndroid Build Coastguard Worker# redundant perf samples are not collected. 15*387f9dfdSAndroid Build Coastguard Worker# 16*387f9dfdSAndroid Build Coastguard Worker# Kernel stacks are post-process in user-land to skip the interrupt framework 17*387f9dfdSAndroid Build Coastguard Worker# frames. You can improve efficiency a little by specifying the exact number 18*387f9dfdSAndroid Build Coastguard Worker# of frames to skip with -s, provided you know what that is. If you get -s 19*387f9dfdSAndroid Build Coastguard Worker# wrong, note that the first line is the IP, and then the (skipped) stack. 20*387f9dfdSAndroid Build Coastguard Worker# 21*387f9dfdSAndroid Build Coastguard Worker# Note: if another perf-based sampling session is active, the output may become 22*387f9dfdSAndroid Build Coastguard Worker# polluted with their events. On older kernels, the output may also become 23*387f9dfdSAndroid Build Coastguard Worker# polluted with tracing sessions (when the kprobe is used instead of the 24*387f9dfdSAndroid Build Coastguard Worker# tracepoint). If this becomes a problem, logic can be added to filter events. 25*387f9dfdSAndroid Build Coastguard Worker# 26*387f9dfdSAndroid Build Coastguard Worker# REQUIRES: Linux 4.6+ (BPF_MAP_TYPE_STACK_TRACE support), and the 27*387f9dfdSAndroid Build Coastguard Worker# perf_misc_flags() function symbol to exist. The latter may or may not 28*387f9dfdSAndroid Build Coastguard Worker# exist depending on your kernel build. Linux 4.9 provides a proper solution 29*387f9dfdSAndroid Build Coastguard Worker# to this (this tool will be updated). 30*387f9dfdSAndroid Build Coastguard Worker# 31*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 32*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 33*387f9dfdSAndroid Build Coastguard Worker# 34*387f9dfdSAndroid Build Coastguard Worker# THANKS: Sasha Goldshtein, Andrew Birchall, and Evgeny Vereshchagin, who wrote 35*387f9dfdSAndroid Build Coastguard Worker# much of the code here, borrowed from tracepoint.py and offcputime.py. 36*387f9dfdSAndroid Build Coastguard Worker# 37*387f9dfdSAndroid Build Coastguard Worker# 15-Jul-2016 Brendan Gregg Created this. 38*387f9dfdSAndroid Build Coastguard Worker 39*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 40*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, Perf 41*387f9dfdSAndroid Build Coastguard Workerfrom sys import stderr 42*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep 43*387f9dfdSAndroid Build Coastguard Workerimport argparse 44*387f9dfdSAndroid Build Coastguard Workerimport signal 45*387f9dfdSAndroid Build Coastguard Workerimport os 46*387f9dfdSAndroid Build Coastguard Workerimport errno 47*387f9dfdSAndroid Build Coastguard Workerimport multiprocessing 48*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard Worker# 51*387f9dfdSAndroid Build Coastguard Worker# Process Arguments 52*387f9dfdSAndroid Build Coastguard Worker# 53*387f9dfdSAndroid Build Coastguard Worker 54*387f9dfdSAndroid Build Coastguard Worker# arg validation 55*387f9dfdSAndroid Build Coastguard Workerdef positive_int(val): 56*387f9dfdSAndroid Build Coastguard Worker try: 57*387f9dfdSAndroid Build Coastguard Worker ival = int(val) 58*387f9dfdSAndroid Build Coastguard Worker except ValueError: 59*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("must be an integer") 60*387f9dfdSAndroid Build Coastguard Worker 61*387f9dfdSAndroid Build Coastguard Worker if ival < 0: 62*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("must be positive") 63*387f9dfdSAndroid Build Coastguard Worker return ival 64*387f9dfdSAndroid Build Coastguard Worker 65*387f9dfdSAndroid Build Coastguard Workerdef positive_nonzero_int(val): 66*387f9dfdSAndroid Build Coastguard Worker ival = positive_int(val) 67*387f9dfdSAndroid Build Coastguard Worker if ival == 0: 68*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("must be nonzero") 69*387f9dfdSAndroid Build Coastguard Worker return ival 70*387f9dfdSAndroid Build Coastguard Worker 71*387f9dfdSAndroid Build Coastguard Worker# arguments 72*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 73*387f9dfdSAndroid Build Coastguard Worker ./profile # profile stack traces at 49 Hertz until Ctrl-C 74*387f9dfdSAndroid Build Coastguard Worker ./profile -F 99 # profile stack traces at 99 Hertz 75*387f9dfdSAndroid Build Coastguard Worker ./profile 5 # profile at 49 Hertz for 5 seconds only 76*387f9dfdSAndroid Build Coastguard Worker ./profile -f 5 # output in folded format for flame graphs 77*387f9dfdSAndroid Build Coastguard Worker ./profile -p 185 # only profile threads for PID 185 78*387f9dfdSAndroid Build Coastguard Worker ./profile -U # only show user space stacks (no kernel) 79*387f9dfdSAndroid Build Coastguard Worker ./profile -K # only show kernel space stacks (no user) 80*387f9dfdSAndroid Build Coastguard Worker ./profile -S 11 # always skip 11 frames of kernel stack 81*387f9dfdSAndroid Build Coastguard Worker""" 82*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 83*387f9dfdSAndroid Build Coastguard Worker description="Profile CPU stack traces at a timed interval", 84*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 85*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 86*387f9dfdSAndroid Build Coastguard Workerthread_group = parser.add_mutually_exclusive_group() 87*387f9dfdSAndroid Build Coastguard Workerthread_group.add_argument("-p", "--pid", type=positive_int, 88*387f9dfdSAndroid Build Coastguard Worker help="profile this PID only") 89*387f9dfdSAndroid Build Coastguard Worker# TODO: add options for user/kernel threads only 90*387f9dfdSAndroid Build Coastguard Workerstack_group = parser.add_mutually_exclusive_group() 91*387f9dfdSAndroid Build Coastguard Workerstack_group.add_argument("-U", "--user-stacks-only", action="store_true", 92*387f9dfdSAndroid Build Coastguard Worker help="show stacks from user space only (no kernel space stacks)") 93*387f9dfdSAndroid Build Coastguard Workerstack_group.add_argument("-K", "--kernel-stacks-only", action="store_true", 94*387f9dfdSAndroid Build Coastguard Worker help="show stacks from kernel space only (no user space stacks)") 95*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-F", "--frequency", type=positive_int, default=49, 96*387f9dfdSAndroid Build Coastguard Worker help="sample frequency, Hertz (default 49)") 97*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--delimited", action="store_true", 98*387f9dfdSAndroid Build Coastguard Worker help="insert delimiter between kernel/user stacks") 99*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-a", "--annotations", action="store_true", 100*387f9dfdSAndroid Build Coastguard Worker help="add _[k] annotations to kernel frames") 101*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-f", "--folded", action="store_true", 102*387f9dfdSAndroid Build Coastguard Worker help="output folded format, one line per stack (for flame graphs)") 103*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--stack-storage-size", default=2048, 104*387f9dfdSAndroid Build Coastguard Worker type=positive_nonzero_int, 105*387f9dfdSAndroid Build Coastguard Worker help="the number of unique stack traces that can be stored and " 106*387f9dfdSAndroid Build Coastguard Worker "displayed (default 2048)") 107*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-S", "--kernel-skip", type=positive_int, default=0, 108*387f9dfdSAndroid Build Coastguard Worker help="skip this many kernel frames (default 3)") 109*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("duration", nargs="?", default=99999999, 110*387f9dfdSAndroid Build Coastguard Worker type=positive_nonzero_int, 111*387f9dfdSAndroid Build Coastguard Worker help="duration of trace, in seconds") 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Worker# option logic 114*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 115*387f9dfdSAndroid Build Coastguard Workerskip = args.kernel_skip 116*387f9dfdSAndroid Build Coastguard Workerpid = int(args.pid) if args.pid is not None else -1 117*387f9dfdSAndroid Build Coastguard Workerduration = int(args.duration) 118*387f9dfdSAndroid Build Coastguard Workerdebug = 0 119*387f9dfdSAndroid Build Coastguard Workerneed_delimiter = args.delimited and not (args.kernel_stacks_only or 120*387f9dfdSAndroid Build Coastguard Worker args.user_stacks_only) 121*387f9dfdSAndroid Build Coastguard Worker# TODO: add stack depth, and interval 122*387f9dfdSAndroid Build Coastguard Worker 123*387f9dfdSAndroid Build Coastguard Worker# 124*387f9dfdSAndroid Build Coastguard Worker# Setup BPF 125*387f9dfdSAndroid Build Coastguard Worker# 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker# define BPF program 128*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 129*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 130*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 131*387f9dfdSAndroid Build Coastguard Worker 132*387f9dfdSAndroid Build Coastguard Workerstruct key_t { 133*387f9dfdSAndroid Build Coastguard Worker u32 pid; 134*387f9dfdSAndroid Build Coastguard Worker u64 kernel_ip; 135*387f9dfdSAndroid Build Coastguard Worker u64 kernel_ret_ip; 136*387f9dfdSAndroid Build Coastguard Worker int user_stack_id; 137*387f9dfdSAndroid Build Coastguard Worker int kernel_stack_id; 138*387f9dfdSAndroid Build Coastguard Worker char name[TASK_COMM_LEN]; 139*387f9dfdSAndroid Build Coastguard Worker}; 140*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct key_t); 141*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start, u32); 142*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, STACK_STORAGE_SIZE); 143*387f9dfdSAndroid Build Coastguard Worker 144*387f9dfdSAndroid Build Coastguard Worker// This code gets a bit complex. Probably not suitable for casual hacking. 145*387f9dfdSAndroid Build Coastguard Worker 146*387f9dfdSAndroid Build Coastguard WorkerPERF_TRACE_EVENT { 147*387f9dfdSAndroid Build Coastguard Worker u32 pid = bpf_get_current_pid_tgid(); 148*387f9dfdSAndroid Build Coastguard Worker if (!(THREAD_FILTER)) 149*387f9dfdSAndroid Build Coastguard Worker return 0; 150*387f9dfdSAndroid Build Coastguard Worker 151*387f9dfdSAndroid Build Coastguard Worker // create map key 152*387f9dfdSAndroid Build Coastguard Worker u64 zero = 0, *val; 153*387f9dfdSAndroid Build Coastguard Worker struct key_t key = {.pid = pid}; 154*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&key.name, sizeof(key.name)); 155*387f9dfdSAndroid Build Coastguard Worker 156*387f9dfdSAndroid Build Coastguard Worker // get stacks 157*387f9dfdSAndroid Build Coastguard Worker key.user_stack_id = USER_STACK_GET; 158*387f9dfdSAndroid Build Coastguard Worker key.kernel_stack_id = KERNEL_STACK_GET; 159*387f9dfdSAndroid Build Coastguard Worker 160*387f9dfdSAndroid Build Coastguard Worker if (key.kernel_stack_id >= 0) { 161*387f9dfdSAndroid Build Coastguard Worker // populate extras to fix the kernel stack 162*387f9dfdSAndroid Build Coastguard Worker struct pt_regs regs = {}; 163*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(®s, sizeof(regs), (void *)REGS_LOCATION); 164*387f9dfdSAndroid Build Coastguard Worker u64 ip = PT_REGS_IP(®s); 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Worker // if ip isn't sane, leave key ips as zero for later checking 167*387f9dfdSAndroid Build Coastguard Worker#ifdef CONFIG_RANDOMIZE_MEMORY 168*387f9dfdSAndroid Build Coastguard Worker if (ip > __PAGE_OFFSET_BASE) { 169*387f9dfdSAndroid Build Coastguard Worker#else 170*387f9dfdSAndroid Build Coastguard Worker if (ip > PAGE_OFFSET) { 171*387f9dfdSAndroid Build Coastguard Worker#endif 172*387f9dfdSAndroid Build Coastguard Worker key.kernel_ip = ip; 173*387f9dfdSAndroid Build Coastguard Worker if (DO_KERNEL_RIP) { 174*387f9dfdSAndroid Build Coastguard Worker /* 175*387f9dfdSAndroid Build Coastguard Worker * User didn't specify a skip value (-s), so we will figure 176*387f9dfdSAndroid Build Coastguard Worker * out how many interrupt framework frames to skip by recording 177*387f9dfdSAndroid Build Coastguard Worker * the kernel rip, then later scanning for it on the stack. 178*387f9dfdSAndroid Build Coastguard Worker * This is likely x86_64 specific; can use -s as a workaround 179*387f9dfdSAndroid Build Coastguard Worker * until this supports your architecture. 180*387f9dfdSAndroid Build Coastguard Worker */ 181*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(&key.kernel_ret_ip, sizeof(key.kernel_ret_ip), 182*387f9dfdSAndroid Build Coastguard Worker (void *)(regs.bp + 8)); 183*387f9dfdSAndroid Build Coastguard Worker } 184*387f9dfdSAndroid Build Coastguard Worker } 185*387f9dfdSAndroid Build Coastguard Worker } 186*387f9dfdSAndroid Build Coastguard Worker 187*387f9dfdSAndroid Build Coastguard Worker val = counts.lookup_or_init(&key, &zero); 188*387f9dfdSAndroid Build Coastguard Worker if (val) { 189*387f9dfdSAndroid Build Coastguard Worker (*val)++; 190*387f9dfdSAndroid Build Coastguard Worker } 191*387f9dfdSAndroid Build Coastguard Worker return 0; 192*387f9dfdSAndroid Build Coastguard Worker} 193*387f9dfdSAndroid Build Coastguard Worker""" 194*387f9dfdSAndroid Build Coastguard Worker 195*387f9dfdSAndroid Build Coastguard Worker# set thread filter 196*387f9dfdSAndroid Build Coastguard Workerthread_context = "" 197*387f9dfdSAndroid Build Coastguard Workerperf_filter = "-a" 198*387f9dfdSAndroid Build Coastguard Workerif args.pid is not None: 199*387f9dfdSAndroid Build Coastguard Worker thread_context = "PID %s" % args.pid 200*387f9dfdSAndroid Build Coastguard Worker thread_filter = 'pid == %s' % args.pid 201*387f9dfdSAndroid Build Coastguard Worker perf_filter = '-p %s' % args.pid 202*387f9dfdSAndroid Build Coastguard Workerelse: 203*387f9dfdSAndroid Build Coastguard Worker thread_context = "all threads" 204*387f9dfdSAndroid Build Coastguard Worker thread_filter = '1' 205*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('THREAD_FILTER', thread_filter) 206*387f9dfdSAndroid Build Coastguard Worker 207*387f9dfdSAndroid Build Coastguard Worker# set stack storage size 208*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('STACK_STORAGE_SIZE', str(args.stack_storage_size)) 209*387f9dfdSAndroid Build Coastguard Worker 210*387f9dfdSAndroid Build Coastguard Worker# handle stack args 211*387f9dfdSAndroid Build Coastguard Workerkernel_stack_get = "stack_traces.get_stackid(args, " \ 212*387f9dfdSAndroid Build Coastguard Worker "%d)" % skip 213*387f9dfdSAndroid Build Coastguard Workeruser_stack_get = \ 214*387f9dfdSAndroid Build Coastguard Worker "stack_traces.get_stackid(args, BPF_F_USER_STACK)" 215*387f9dfdSAndroid Build Coastguard Workerstack_context = "" 216*387f9dfdSAndroid Build Coastguard Workerif args.user_stacks_only: 217*387f9dfdSAndroid Build Coastguard Worker stack_context = "user" 218*387f9dfdSAndroid Build Coastguard Worker kernel_stack_get = "-1" 219*387f9dfdSAndroid Build Coastguard Workerelif args.kernel_stacks_only: 220*387f9dfdSAndroid Build Coastguard Worker stack_context = "kernel" 221*387f9dfdSAndroid Build Coastguard Worker user_stack_get = "-1" 222*387f9dfdSAndroid Build Coastguard Workerelse: 223*387f9dfdSAndroid Build Coastguard Worker stack_context = "user + kernel" 224*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('USER_STACK_GET', user_stack_get) 225*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('KERNEL_STACK_GET', kernel_stack_get) 226*387f9dfdSAndroid Build Coastguard Workerif skip: 227*387f9dfdSAndroid Build Coastguard Worker # don't record the rip, as we won't use it 228*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('DO_KERNEL_RIP', '0') 229*387f9dfdSAndroid Build Coastguard Workerelse: 230*387f9dfdSAndroid Build Coastguard Worker # rip is used to skip interrupt infrastructure frames 231*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('DO_KERNEL_RIP', '1') 232*387f9dfdSAndroid Build Coastguard Worker 233*387f9dfdSAndroid Build Coastguard Worker# header 234*387f9dfdSAndroid Build Coastguard Workerif not args.folded: 235*387f9dfdSAndroid Build Coastguard Worker print("Sampling at %d Hertz of %s by %s stack" % 236*387f9dfdSAndroid Build Coastguard Worker (args.frequency, thread_context, stack_context), end="") 237*387f9dfdSAndroid Build Coastguard Worker if duration < 99999999: 238*387f9dfdSAndroid Build Coastguard Worker print(" for %d secs." % duration) 239*387f9dfdSAndroid Build Coastguard Worker else: 240*387f9dfdSAndroid Build Coastguard Worker print("... Hit Ctrl-C to end.") 241*387f9dfdSAndroid Build Coastguard Worker 242*387f9dfdSAndroid Build Coastguard Worker# kprobe perf_misc_flags() 243*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('PERF_TRACE_EVENT', 244*387f9dfdSAndroid Build Coastguard Worker 'int kprobe__perf_misc_flags(struct pt_regs *args)') 245*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('REGS_LOCATION', 'PT_REGS_PARM1(args)') 246*387f9dfdSAndroid Build Coastguard Workerif debug: 247*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 248*387f9dfdSAndroid Build Coastguard Worker 249*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 250*387f9dfdSAndroid Build Coastguard Workertry: 251*387f9dfdSAndroid Build Coastguard Worker b = BPF(text=bpf_text) 252*387f9dfdSAndroid Build Coastguard Workerexcept: 253*387f9dfdSAndroid Build Coastguard Worker print("BPF initialization failed. perf_misc_flags() may be inlined in " + 254*387f9dfdSAndroid Build Coastguard Worker "your kernel build.\nThis tool will be updated in the future to " + 255*387f9dfdSAndroid Build Coastguard Worker "support Linux 4.9, which has reliable profiling support. Exiting.") 256*387f9dfdSAndroid Build Coastguard Worker exit() 257*387f9dfdSAndroid Build Coastguard Worker 258*387f9dfdSAndroid Build Coastguard Worker# signal handler 259*387f9dfdSAndroid Build Coastguard Workerdef signal_ignore(signal, frame): 260*387f9dfdSAndroid Build Coastguard Worker print() 261*387f9dfdSAndroid Build Coastguard Worker 262*387f9dfdSAndroid Build Coastguard Worker# 263*387f9dfdSAndroid Build Coastguard Worker# Setup perf_events 264*387f9dfdSAndroid Build Coastguard Worker# 265*387f9dfdSAndroid Build Coastguard Worker 266*387f9dfdSAndroid Build Coastguard Worker# use perf_events to sample 267*387f9dfdSAndroid Build Coastguard Workertry: 268*387f9dfdSAndroid Build Coastguard Worker Perf.perf_event_open(0, pid=-1, ptype=Perf.PERF_TYPE_SOFTWARE, 269*387f9dfdSAndroid Build Coastguard Worker freq=args.frequency) 270*387f9dfdSAndroid Build Coastguard Workerexcept: 271*387f9dfdSAndroid Build Coastguard Worker print("ERROR: initializing perf_events for sampling.\n" 272*387f9dfdSAndroid Build Coastguard Worker "To debug this, try running the following command:\n" 273*387f9dfdSAndroid Build Coastguard Worker " perf record -F 49 -e cpu-clock %s -- sleep 1\n" 274*387f9dfdSAndroid Build Coastguard Worker "If that also doesn't work, fix it first." % perf_filter, file=stderr) 275*387f9dfdSAndroid Build Coastguard Worker exit(0) 276*387f9dfdSAndroid Build Coastguard Worker 277*387f9dfdSAndroid Build Coastguard Worker# 278*387f9dfdSAndroid Build Coastguard Worker# Output Report 279*387f9dfdSAndroid Build Coastguard Worker# 280*387f9dfdSAndroid Build Coastguard Worker 281*387f9dfdSAndroid Build Coastguard Worker# collect samples 282*387f9dfdSAndroid Build Coastguard Workertry: 283*387f9dfdSAndroid Build Coastguard Worker sleep(duration) 284*387f9dfdSAndroid Build Coastguard Workerexcept KeyboardInterrupt: 285*387f9dfdSAndroid Build Coastguard Worker # as cleanup can take some time, trap Ctrl-C: 286*387f9dfdSAndroid Build Coastguard Worker signal.signal(signal.SIGINT, signal_ignore) 287*387f9dfdSAndroid Build Coastguard Worker 288*387f9dfdSAndroid Build Coastguard Workerif not args.folded: 289*387f9dfdSAndroid Build Coastguard Worker print() 290*387f9dfdSAndroid Build Coastguard Worker 291*387f9dfdSAndroid Build Coastguard Workerdef aksym(addr): 292*387f9dfdSAndroid Build Coastguard Worker if args.annotations: 293*387f9dfdSAndroid Build Coastguard Worker return b.ksym(addr) + "_[k]" 294*387f9dfdSAndroid Build Coastguard Worker else: 295*387f9dfdSAndroid Build Coastguard Worker return b.ksym(addr) 296*387f9dfdSAndroid Build Coastguard Worker 297*387f9dfdSAndroid Build Coastguard Worker# output stacks 298*387f9dfdSAndroid Build Coastguard Workermissing_stacks = 0 299*387f9dfdSAndroid Build Coastguard Workerhas_enomem = False 300*387f9dfdSAndroid Build Coastguard Workercounts = b.get_table("counts") 301*387f9dfdSAndroid Build Coastguard Workerstack_traces = b.get_table("stack_traces") 302*387f9dfdSAndroid Build Coastguard Workerfor k, v in sorted(counts.items(), key=lambda counts: counts[1].value): 303*387f9dfdSAndroid Build Coastguard Worker # handle get_stackid errors 304*387f9dfdSAndroid Build Coastguard Worker if (not args.user_stacks_only and k.kernel_stack_id < 0 and 305*387f9dfdSAndroid Build Coastguard Worker k.kernel_stack_id != -errno.EFAULT) or \ 306*387f9dfdSAndroid Build Coastguard Worker (not args.kernel_stacks_only and k.user_stack_id < 0 and 307*387f9dfdSAndroid Build Coastguard Worker k.user_stack_id != -errno.EFAULT): 308*387f9dfdSAndroid Build Coastguard Worker missing_stacks += 1 309*387f9dfdSAndroid Build Coastguard Worker # check for an ENOMEM error 310*387f9dfdSAndroid Build Coastguard Worker if k.kernel_stack_id == -errno.ENOMEM or \ 311*387f9dfdSAndroid Build Coastguard Worker k.user_stack_id == -errno.ENOMEM: 312*387f9dfdSAndroid Build Coastguard Worker has_enomem = True 313*387f9dfdSAndroid Build Coastguard Worker 314*387f9dfdSAndroid Build Coastguard Worker user_stack = [] if k.user_stack_id < 0 else \ 315*387f9dfdSAndroid Build Coastguard Worker stack_traces.walk(k.user_stack_id) 316*387f9dfdSAndroid Build Coastguard Worker kernel_tmp = [] if k.kernel_stack_id < 0 else \ 317*387f9dfdSAndroid Build Coastguard Worker stack_traces.walk(k.kernel_stack_id) 318*387f9dfdSAndroid Build Coastguard Worker 319*387f9dfdSAndroid Build Coastguard Worker # fix kernel stack 320*387f9dfdSAndroid Build Coastguard Worker kernel_stack = [] 321*387f9dfdSAndroid Build Coastguard Worker if k.kernel_stack_id >= 0: 322*387f9dfdSAndroid Build Coastguard Worker if skip: 323*387f9dfdSAndroid Build Coastguard Worker # fixed skip 324*387f9dfdSAndroid Build Coastguard Worker for addr in kernel_tmp: 325*387f9dfdSAndroid Build Coastguard Worker kernel_stack.append(addr) 326*387f9dfdSAndroid Build Coastguard Worker kernel_stack = kernel_stack[skip:] 327*387f9dfdSAndroid Build Coastguard Worker else: 328*387f9dfdSAndroid Build Coastguard Worker # skip the interrupt framework stack by searching for our RIP 329*387f9dfdSAndroid Build Coastguard Worker skipping = 1 330*387f9dfdSAndroid Build Coastguard Worker for addr in kernel_tmp: 331*387f9dfdSAndroid Build Coastguard Worker if k.kernel_ret_ip == addr: 332*387f9dfdSAndroid Build Coastguard Worker skipping = 0 333*387f9dfdSAndroid Build Coastguard Worker if not skipping: 334*387f9dfdSAndroid Build Coastguard Worker kernel_stack.append(addr) 335*387f9dfdSAndroid Build Coastguard Worker if k.kernel_ip: 336*387f9dfdSAndroid Build Coastguard Worker kernel_stack.insert(0, k.kernel_ip) 337*387f9dfdSAndroid Build Coastguard Worker 338*387f9dfdSAndroid Build Coastguard Worker do_delimiter = need_delimiter and kernel_stack 339*387f9dfdSAndroid Build Coastguard Worker 340*387f9dfdSAndroid Build Coastguard Worker if args.folded: 341*387f9dfdSAndroid Build Coastguard Worker # print folded stack output 342*387f9dfdSAndroid Build Coastguard Worker user_stack = list(user_stack) 343*387f9dfdSAndroid Build Coastguard Worker kernel_stack = list(kernel_stack) 344*387f9dfdSAndroid Build Coastguard Worker line = [k.name.decode('utf-8', 'replace')] + \ 345*387f9dfdSAndroid Build Coastguard Worker [b.sym(addr, k.pid) for addr in reversed(user_stack)] + \ 346*387f9dfdSAndroid Build Coastguard Worker (do_delimiter and ["-"] or []) + \ 347*387f9dfdSAndroid Build Coastguard Worker [aksym(addr) for addr in reversed(kernel_stack)] 348*387f9dfdSAndroid Build Coastguard Worker print("%s %d" % (";".join(line), v.value)) 349*387f9dfdSAndroid Build Coastguard Worker else: 350*387f9dfdSAndroid Build Coastguard Worker # print default multi-line stack output. 351*387f9dfdSAndroid Build Coastguard Worker for addr in kernel_stack: 352*387f9dfdSAndroid Build Coastguard Worker print(" %s" % aksym(addr)) 353*387f9dfdSAndroid Build Coastguard Worker if do_delimiter: 354*387f9dfdSAndroid Build Coastguard Worker print(" --") 355*387f9dfdSAndroid Build Coastguard Worker for addr in user_stack: 356*387f9dfdSAndroid Build Coastguard Worker print(" %s" % b.sym(addr, k.pid)) 357*387f9dfdSAndroid Build Coastguard Worker print(" %-16s %s (%d)" % ("-", k.name, k.pid)) 358*387f9dfdSAndroid Build Coastguard Worker print(" %d\n" % v.value) 359*387f9dfdSAndroid Build Coastguard Worker 360*387f9dfdSAndroid Build Coastguard Worker# check missing 361*387f9dfdSAndroid Build Coastguard Workerif missing_stacks > 0: 362*387f9dfdSAndroid Build Coastguard Worker enomem_str = "" if not has_enomem else \ 363*387f9dfdSAndroid Build Coastguard Worker " Consider increasing --stack-storage-size." 364*387f9dfdSAndroid Build Coastguard Worker print("WARNING: %d stack traces could not be displayed.%s" % 365*387f9dfdSAndroid Build Coastguard Worker (missing_stacks, enomem_str), 366*387f9dfdSAndroid Build Coastguard Worker file=stderr) 367