1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# stackcount Count events and their stack traces. 4*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 5*387f9dfdSAndroid Build Coastguard Worker# 6*387f9dfdSAndroid Build Coastguard Worker# USAGE: stackcount.py [-h] [-p PID] [-c CPU] [-i INTERVAL] [-D DURATION] [-T] 7*387f9dfdSAndroid Build Coastguard Worker# [-r] [-s] [-P] [-K] [-U] [-v] [-d] [-f] [--debug] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# The pattern is a string with optional '*' wildcards, similar to file 10*387f9dfdSAndroid Build Coastguard Worker# globbing. If you'd prefer to use regular expressions, use the -r option. 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Netflix, Inc. 13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 14*387f9dfdSAndroid Build Coastguard Worker# 15*387f9dfdSAndroid Build Coastguard Worker# 12-Jan-2016 Brendan Gregg Created this. 16*387f9dfdSAndroid Build Coastguard Worker# 09-Jul-2016 Sasha Goldshtein Generalized for uprobes and tracepoints. 17*387f9dfdSAndroid Build Coastguard Worker 18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 19*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT 20*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep, strftime 21*387f9dfdSAndroid Build Coastguard Workerimport argparse 22*387f9dfdSAndroid Build Coastguard Workerimport re 23*387f9dfdSAndroid Build Coastguard Workerimport signal 24*387f9dfdSAndroid Build Coastguard Workerimport sys 25*387f9dfdSAndroid Build Coastguard Workerimport traceback 26*387f9dfdSAndroid Build Coastguard Worker 27*387f9dfdSAndroid Build Coastguard Workerdebug = False 28*387f9dfdSAndroid Build Coastguard Worker 29*387f9dfdSAndroid Build Coastguard Workerclass Probe(object): 30*387f9dfdSAndroid Build Coastguard Worker def __init__(self, pattern, kernel_stack, user_stack, use_regex=False, 31*387f9dfdSAndroid Build Coastguard Worker pid=None, per_pid=False, cpu=None): 32*387f9dfdSAndroid Build Coastguard Worker """Init a new probe. 33*387f9dfdSAndroid Build Coastguard Worker 34*387f9dfdSAndroid Build Coastguard Worker Init the probe from the pattern provided by the user. The supported 35*387f9dfdSAndroid Build Coastguard Worker patterns mimic the 'trace' and 'argdist' tools, but are simpler because 36*387f9dfdSAndroid Build Coastguard Worker we don't have to distinguish between probes and retprobes. 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker func -- probe a kernel function 39*387f9dfdSAndroid Build Coastguard Worker lib:func -- probe a user-space function in the library 'lib' 40*387f9dfdSAndroid Build Coastguard Worker p::func -- same thing as 'func' 41*387f9dfdSAndroid Build Coastguard Worker p:lib:func -- same thing as 'lib:func' 42*387f9dfdSAndroid Build Coastguard Worker t:cat:event -- probe a kernel tracepoint 43*387f9dfdSAndroid Build Coastguard Worker u:lib:probe -- probe a USDT tracepoint 44*387f9dfdSAndroid Build Coastguard Worker """ 45*387f9dfdSAndroid Build Coastguard Worker self.kernel_stack = kernel_stack 46*387f9dfdSAndroid Build Coastguard Worker self.user_stack = user_stack 47*387f9dfdSAndroid Build Coastguard Worker parts = pattern.split(':') 48*387f9dfdSAndroid Build Coastguard Worker if len(parts) == 1: 49*387f9dfdSAndroid Build Coastguard Worker parts = ["p", "", parts[0]] 50*387f9dfdSAndroid Build Coastguard Worker elif len(parts) == 2: 51*387f9dfdSAndroid Build Coastguard Worker parts = ["p", parts[0], parts[1]] 52*387f9dfdSAndroid Build Coastguard Worker elif len(parts) == 3: 53*387f9dfdSAndroid Build Coastguard Worker if parts[0] == "t": 54*387f9dfdSAndroid Build Coastguard Worker parts = ["t", "", "%s:%s" % tuple(parts[1:])] 55*387f9dfdSAndroid Build Coastguard Worker if parts[0] not in ["p", "t", "u"]: 56*387f9dfdSAndroid Build Coastguard Worker raise Exception("Type must be 'p', 't', or 'u', but got %s" % 57*387f9dfdSAndroid Build Coastguard Worker parts[0]) 58*387f9dfdSAndroid Build Coastguard Worker else: 59*387f9dfdSAndroid Build Coastguard Worker raise Exception("Too many ':'-separated components in pattern %s" % 60*387f9dfdSAndroid Build Coastguard Worker pattern) 61*387f9dfdSAndroid Build Coastguard Worker 62*387f9dfdSAndroid Build Coastguard Worker (self.type, self.library, self.pattern) = parts 63*387f9dfdSAndroid Build Coastguard Worker if not use_regex: 64*387f9dfdSAndroid Build Coastguard Worker self.pattern = self.pattern.replace('*', '.*') 65*387f9dfdSAndroid Build Coastguard Worker self.pattern = '^' + self.pattern + '$' 66*387f9dfdSAndroid Build Coastguard Worker 67*387f9dfdSAndroid Build Coastguard Worker if (self.type == "p" and self.library) or self.type == "u": 68*387f9dfdSAndroid Build Coastguard Worker libpath = BPF.find_library(self.library) 69*387f9dfdSAndroid Build Coastguard Worker if libpath is None: 70*387f9dfdSAndroid Build Coastguard Worker # This might be an executable (e.g. 'bash') 71*387f9dfdSAndroid Build Coastguard Worker libpath = BPF.find_exe(self.library) 72*387f9dfdSAndroid Build Coastguard Worker if libpath is None or len(libpath) == 0: 73*387f9dfdSAndroid Build Coastguard Worker raise Exception("unable to find library %s" % self.library) 74*387f9dfdSAndroid Build Coastguard Worker self.library = libpath 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker self.pid = pid 77*387f9dfdSAndroid Build Coastguard Worker self.per_pid = per_pid 78*387f9dfdSAndroid Build Coastguard Worker self.cpu = cpu 79*387f9dfdSAndroid Build Coastguard Worker self.matched = 0 80*387f9dfdSAndroid Build Coastguard Worker 81*387f9dfdSAndroid Build Coastguard Worker def is_kernel_probe(self): 82*387f9dfdSAndroid Build Coastguard Worker return self.type == "t" or (self.type == "p" and self.library == "") 83*387f9dfdSAndroid Build Coastguard Worker 84*387f9dfdSAndroid Build Coastguard Worker def attach(self): 85*387f9dfdSAndroid Build Coastguard Worker if self.type == "p": 86*387f9dfdSAndroid Build Coastguard Worker if self.library: 87*387f9dfdSAndroid Build Coastguard Worker self.bpf.attach_uprobe(name=self.library, 88*387f9dfdSAndroid Build Coastguard Worker sym_re=self.pattern, 89*387f9dfdSAndroid Build Coastguard Worker fn_name="trace_count", 90*387f9dfdSAndroid Build Coastguard Worker pid=self.pid or -1) 91*387f9dfdSAndroid Build Coastguard Worker self.matched = self.bpf.num_open_uprobes() 92*387f9dfdSAndroid Build Coastguard Worker else: 93*387f9dfdSAndroid Build Coastguard Worker self.bpf.attach_kprobe(event_re=self.pattern, 94*387f9dfdSAndroid Build Coastguard Worker fn_name="trace_count") 95*387f9dfdSAndroid Build Coastguard Worker self.matched = self.bpf.num_open_kprobes() 96*387f9dfdSAndroid Build Coastguard Worker elif self.type == "t": 97*387f9dfdSAndroid Build Coastguard Worker self.bpf.attach_tracepoint(tp_re=self.pattern, 98*387f9dfdSAndroid Build Coastguard Worker fn_name="trace_count") 99*387f9dfdSAndroid Build Coastguard Worker self.matched = self.bpf.num_open_tracepoints() 100*387f9dfdSAndroid Build Coastguard Worker elif self.type == "u": 101*387f9dfdSAndroid Build Coastguard Worker pass # Nothing to do -- attach already happened in `load` 102*387f9dfdSAndroid Build Coastguard Worker 103*387f9dfdSAndroid Build Coastguard Worker if self.matched == 0: 104*387f9dfdSAndroid Build Coastguard Worker raise Exception("No functions matched by pattern %s" % 105*387f9dfdSAndroid Build Coastguard Worker self.pattern) 106*387f9dfdSAndroid Build Coastguard Worker 107*387f9dfdSAndroid Build Coastguard Worker def load(self): 108*387f9dfdSAndroid Build Coastguard Worker ctx_name = "ctx" 109*387f9dfdSAndroid Build Coastguard Worker stack_trace = "" 110*387f9dfdSAndroid Build Coastguard Worker if self.user_stack: 111*387f9dfdSAndroid Build Coastguard Worker stack_trace += """ 112*387f9dfdSAndroid Build Coastguard Worker key.user_stack_id = stack_traces.get_stackid( 113*387f9dfdSAndroid Build Coastguard Worker %s, BPF_F_USER_STACK 114*387f9dfdSAndroid Build Coastguard Worker );""" % (ctx_name) 115*387f9dfdSAndroid Build Coastguard Worker else: 116*387f9dfdSAndroid Build Coastguard Worker stack_trace += "key.user_stack_id = -1;" 117*387f9dfdSAndroid Build Coastguard Worker if self.kernel_stack: 118*387f9dfdSAndroid Build Coastguard Worker stack_trace += """ 119*387f9dfdSAndroid Build Coastguard Worker key.kernel_stack_id = stack_traces.get_stackid( 120*387f9dfdSAndroid Build Coastguard Worker %s, 0 121*387f9dfdSAndroid Build Coastguard Worker );""" % (ctx_name) 122*387f9dfdSAndroid Build Coastguard Worker else: 123*387f9dfdSAndroid Build Coastguard Worker stack_trace += "key.kernel_stack_id = -1;" 124*387f9dfdSAndroid Build Coastguard Worker 125*387f9dfdSAndroid Build Coastguard Worker trace_count_text = """ 126*387f9dfdSAndroid Build Coastguard Workerint trace_count(void *ctx) { 127*387f9dfdSAndroid Build Coastguard Worker FILTER 128*387f9dfdSAndroid Build Coastguard Worker struct key_t key = {}; 129*387f9dfdSAndroid Build Coastguard Worker key.tgid = GET_TGID; 130*387f9dfdSAndroid Build Coastguard Worker STORE_COMM 131*387f9dfdSAndroid Build Coastguard Worker %s 132*387f9dfdSAndroid Build Coastguard Worker counts.atomic_increment(key); 133*387f9dfdSAndroid Build Coastguard Worker return 0; 134*387f9dfdSAndroid Build Coastguard Worker} 135*387f9dfdSAndroid Build Coastguard Worker """ 136*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text % (stack_trace) 137*387f9dfdSAndroid Build Coastguard Worker 138*387f9dfdSAndroid Build Coastguard Worker bpf_text = """#include <uapi/linux/ptrace.h> 139*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 140*387f9dfdSAndroid Build Coastguard Worker 141*387f9dfdSAndroid Build Coastguard Workerstruct key_t { 142*387f9dfdSAndroid Build Coastguard Worker // no pid (thread ID) so that we do not needlessly split this key 143*387f9dfdSAndroid Build Coastguard Worker u32 tgid; 144*387f9dfdSAndroid Build Coastguard Worker int kernel_stack_id; 145*387f9dfdSAndroid Build Coastguard Worker int user_stack_id; 146*387f9dfdSAndroid Build Coastguard Worker char name[TASK_COMM_LEN]; 147*387f9dfdSAndroid Build Coastguard Worker}; 148*387f9dfdSAndroid Build Coastguard Worker 149*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct key_t); 150*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, 1024); 151*387f9dfdSAndroid Build Coastguard Worker """ 152*387f9dfdSAndroid Build Coastguard Worker 153*387f9dfdSAndroid Build Coastguard Worker filter_text = [] 154*387f9dfdSAndroid Build Coastguard Worker # We really mean the tgid from the kernel's perspective, which is in 155*387f9dfdSAndroid Build Coastguard Worker # the top 32 bits of bpf_get_current_pid_tgid(). 156*387f9dfdSAndroid Build Coastguard Worker if self.is_kernel_probe() and self.pid: 157*387f9dfdSAndroid Build Coastguard Worker filter_text.append('u32 pid; pid = bpf_get_current_pid_tgid() >> 32; ' + 158*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %d) { return 0; }' % self.pid) 159*387f9dfdSAndroid Build Coastguard Worker 160*387f9dfdSAndroid Build Coastguard Worker if self.is_kernel_probe() and self.cpu: 161*387f9dfdSAndroid Build Coastguard Worker filter_text.append('struct task_struct *task; task = (struct task_struct*)bpf_get_current_task(); ' + 162*387f9dfdSAndroid Build Coastguard Worker 'if (task->cpu != %d) { return 0; }' % self.cpu) 163*387f9dfdSAndroid Build Coastguard Worker 164*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text.replace('FILTER', '\n '.join(filter_text)) 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Worker # Do per-pid statistics iff -P is provided 167*387f9dfdSAndroid Build Coastguard Worker if self.per_pid: 168*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text.replace('GET_TGID', 169*387f9dfdSAndroid Build Coastguard Worker 'bpf_get_current_pid_tgid() >> 32') 170*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text.replace('STORE_COMM', 171*387f9dfdSAndroid Build Coastguard Worker 'bpf_get_current_comm(&key.name, sizeof(key.name));') 172*387f9dfdSAndroid Build Coastguard Worker else: 173*387f9dfdSAndroid Build Coastguard Worker # skip splitting on PID so these aggregate 174*387f9dfdSAndroid Build Coastguard Worker # together, and don't store the process name. 175*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text.replace( 176*387f9dfdSAndroid Build Coastguard Worker 'GET_TGID', '0xffffffff') 177*387f9dfdSAndroid Build Coastguard Worker trace_count_text = trace_count_text.replace('STORE_COMM', '') 178*387f9dfdSAndroid Build Coastguard Worker 179*387f9dfdSAndroid Build Coastguard Worker self.usdt = None 180*387f9dfdSAndroid Build Coastguard Worker if self.type == "u": 181*387f9dfdSAndroid Build Coastguard Worker self.usdt = USDT(path=self.library, pid=self.pid) 182*387f9dfdSAndroid Build Coastguard Worker for probe in self.usdt.enumerate_probes(): 183*387f9dfdSAndroid Build Coastguard Worker if not self.pid and (probe.bin_path != self.library): 184*387f9dfdSAndroid Build Coastguard Worker continue 185*387f9dfdSAndroid Build Coastguard Worker if re.match(self.pattern, probe.name): 186*387f9dfdSAndroid Build Coastguard Worker # This hack is required because the bpf_usdt_readarg 187*387f9dfdSAndroid Build Coastguard Worker # functions generated need different function names for 188*387f9dfdSAndroid Build Coastguard Worker # each attached probe. If we just stick to trace_count, 189*387f9dfdSAndroid Build Coastguard Worker # we'd get multiple bpf_usdt_readarg helpers with the same 190*387f9dfdSAndroid Build Coastguard Worker # name when enabling more than one USDT probe. 191*387f9dfdSAndroid Build Coastguard Worker new_func = "trace_count_%d" % self.matched 192*387f9dfdSAndroid Build Coastguard Worker bpf_text += trace_count_text.replace( 193*387f9dfdSAndroid Build Coastguard Worker "trace_count", new_func) 194*387f9dfdSAndroid Build Coastguard Worker self.usdt.enable_probe(probe.name, new_func) 195*387f9dfdSAndroid Build Coastguard Worker self.matched += 1 196*387f9dfdSAndroid Build Coastguard Worker if debug: 197*387f9dfdSAndroid Build Coastguard Worker print(self.usdt.get_text()) 198*387f9dfdSAndroid Build Coastguard Worker else: 199*387f9dfdSAndroid Build Coastguard Worker bpf_text += trace_count_text 200*387f9dfdSAndroid Build Coastguard Worker 201*387f9dfdSAndroid Build Coastguard Worker if debug: 202*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 203*387f9dfdSAndroid Build Coastguard Worker self.bpf = BPF(text=bpf_text, 204*387f9dfdSAndroid Build Coastguard Worker usdt_contexts=[self.usdt] if self.usdt else []) 205*387f9dfdSAndroid Build Coastguard Worker 206*387f9dfdSAndroid Build Coastguard Workerclass Tool(object): 207*387f9dfdSAndroid Build Coastguard Worker def __init__(self): 208*387f9dfdSAndroid Build Coastguard Worker examples = """examples: 209*387f9dfdSAndroid Build Coastguard Worker ./stackcount submit_bio # count kernel stack traces for submit_bio 210*387f9dfdSAndroid Build Coastguard Worker ./stackcount -d ip_output # include a user/kernel stack delimiter 211*387f9dfdSAndroid Build Coastguard Worker ./stackcount -s ip_output # show symbol offsets 212*387f9dfdSAndroid Build Coastguard Worker ./stackcount -sv ip_output # show offsets and raw addresses (verbose) 213*387f9dfdSAndroid Build Coastguard Worker ./stackcount 'tcp_send*' # count stacks for funcs matching tcp_send* 214*387f9dfdSAndroid Build Coastguard Worker ./stackcount -r '^tcp_send.*' # same as above, using regular expressions 215*387f9dfdSAndroid Build Coastguard Worker ./stackcount -Ti 5 ip_output # output every 5 seconds, with timestamps 216*387f9dfdSAndroid Build Coastguard Worker ./stackcount -p 185 ip_output # count ip_output stacks for PID 185 only 217*387f9dfdSAndroid Build Coastguard Worker ./stackcount -c 1 put_prev_entity # count put_prev_entity stacks for CPU 1 only 218*387f9dfdSAndroid Build Coastguard Worker ./stackcount -p 185 c:malloc # count stacks for malloc in PID 185 219*387f9dfdSAndroid Build Coastguard Worker ./stackcount t:sched:sched_fork # count stacks for sched_fork tracepoint 220*387f9dfdSAndroid Build Coastguard Worker ./stackcount -p 185 u:node:* # count stacks for all USDT probes in node 221*387f9dfdSAndroid Build Coastguard Worker ./stackcount -K t:sched:sched_switch # kernel stacks only 222*387f9dfdSAndroid Build Coastguard Worker ./stackcount -U t:sched:sched_switch # user stacks only 223*387f9dfdSAndroid Build Coastguard Worker """ 224*387f9dfdSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 225*387f9dfdSAndroid Build Coastguard Worker description="Count events and their stack traces", 226*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 227*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 228*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-p", "--pid", type=int, 229*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 230*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-c", "--cpu", type=int, 231*387f9dfdSAndroid Build Coastguard Worker help="trace this CPU only") 232*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-i", "--interval", 233*387f9dfdSAndroid Build Coastguard Worker help="summary interval, seconds") 234*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-D", "--duration", 235*387f9dfdSAndroid Build Coastguard Worker help="total duration of trace, seconds") 236*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-T", "--timestamp", action="store_true", 237*387f9dfdSAndroid Build Coastguard Worker help="include timestamp on output") 238*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-r", "--regexp", action="store_true", 239*387f9dfdSAndroid Build Coastguard Worker help="use regular expressions. Default is \"*\" wildcards only.") 240*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-s", "--offset", action="store_true", 241*387f9dfdSAndroid Build Coastguard Worker help="show address offsets") 242*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-P", "--perpid", action="store_true", 243*387f9dfdSAndroid Build Coastguard Worker help="display stacks separately for each process") 244*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-K", "--kernel-stacks-only", 245*387f9dfdSAndroid Build Coastguard Worker action="store_true", help="kernel stack only", default=False) 246*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-U", "--user-stacks-only", 247*387f9dfdSAndroid Build Coastguard Worker action="store_true", help="user stack only", default=False) 248*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-v", "--verbose", action="store_true", 249*387f9dfdSAndroid Build Coastguard Worker help="show raw addresses") 250*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-d", "--delimited", action="store_true", 251*387f9dfdSAndroid Build Coastguard Worker help="insert delimiter between kernel/user stacks") 252*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-f", "--folded", action="store_true", 253*387f9dfdSAndroid Build Coastguard Worker help="output folded format") 254*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--debug", action="store_true", 255*387f9dfdSAndroid Build Coastguard Worker help="print BPF program before starting (for debugging purposes)") 256*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("pattern", 257*387f9dfdSAndroid Build Coastguard Worker help="search expression for events") 258*387f9dfdSAndroid Build Coastguard Worker self.args = parser.parse_args() 259*387f9dfdSAndroid Build Coastguard Worker global debug 260*387f9dfdSAndroid Build Coastguard Worker debug = self.args.debug 261*387f9dfdSAndroid Build Coastguard Worker 262*387f9dfdSAndroid Build Coastguard Worker if self.args.duration and not self.args.interval: 263*387f9dfdSAndroid Build Coastguard Worker self.args.interval = self.args.duration 264*387f9dfdSAndroid Build Coastguard Worker if not self.args.interval: 265*387f9dfdSAndroid Build Coastguard Worker self.args.interval = 99999999 266*387f9dfdSAndroid Build Coastguard Worker 267*387f9dfdSAndroid Build Coastguard Worker if self.args.kernel_stacks_only and self.args.user_stacks_only: 268*387f9dfdSAndroid Build Coastguard Worker print("ERROR: -K and -U are mutually exclusive. If you want " + 269*387f9dfdSAndroid Build Coastguard Worker "both stacks, that is the default.") 270*387f9dfdSAndroid Build Coastguard Worker exit() 271*387f9dfdSAndroid Build Coastguard Worker if not self.args.kernel_stacks_only and not self.args.user_stacks_only: 272*387f9dfdSAndroid Build Coastguard Worker self.kernel_stack = True 273*387f9dfdSAndroid Build Coastguard Worker self.user_stack = True 274*387f9dfdSAndroid Build Coastguard Worker else: 275*387f9dfdSAndroid Build Coastguard Worker self.kernel_stack = self.args.kernel_stacks_only 276*387f9dfdSAndroid Build Coastguard Worker self.user_stack = self.args.user_stacks_only 277*387f9dfdSAndroid Build Coastguard Worker 278*387f9dfdSAndroid Build Coastguard Worker # For tracing single processes in isolation, explicitly set perpid 279*387f9dfdSAndroid Build Coastguard Worker # to True, if not already set. This is required to generate the correct 280*387f9dfdSAndroid Build Coastguard Worker # BPF program that can store pid in the tgid field of the key_t object. 281*387f9dfdSAndroid Build Coastguard Worker if self.args.pid is not None and self.args.pid > 0: 282*387f9dfdSAndroid Build Coastguard Worker self.args.perpid = True 283*387f9dfdSAndroid Build Coastguard Worker 284*387f9dfdSAndroid Build Coastguard Worker self.probe = Probe(self.args.pattern, 285*387f9dfdSAndroid Build Coastguard Worker self.kernel_stack, self.user_stack, 286*387f9dfdSAndroid Build Coastguard Worker self.args.regexp, self.args.pid, self.args.perpid, self.args.cpu) 287*387f9dfdSAndroid Build Coastguard Worker self.need_delimiter = self.args.delimited and not ( 288*387f9dfdSAndroid Build Coastguard Worker self.args.kernel_stacks_only or self.args.user_stacks_only) 289*387f9dfdSAndroid Build Coastguard Worker 290*387f9dfdSAndroid Build Coastguard Worker def _print_kframe(self, addr): 291*387f9dfdSAndroid Build Coastguard Worker print(" ", end="") 292*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose: 293*387f9dfdSAndroid Build Coastguard Worker print("%-16x " % addr, end="") 294*387f9dfdSAndroid Build Coastguard Worker if self.args.offset: 295*387f9dfdSAndroid Build Coastguard Worker print("%s" % self.probe.bpf.ksym(addr, show_offset=True).decode()) 296*387f9dfdSAndroid Build Coastguard Worker else: 297*387f9dfdSAndroid Build Coastguard Worker print("%s" % self.probe.bpf.ksym(addr).decode()) 298*387f9dfdSAndroid Build Coastguard Worker 299*387f9dfdSAndroid Build Coastguard Worker def _print_uframe(self, addr, pid): 300*387f9dfdSAndroid Build Coastguard Worker print(" ", end="") 301*387f9dfdSAndroid Build Coastguard Worker if self.args.verbose: 302*387f9dfdSAndroid Build Coastguard Worker print("%-16x " % addr, end="") 303*387f9dfdSAndroid Build Coastguard Worker if self.args.offset: 304*387f9dfdSAndroid Build Coastguard Worker print("%s" % self.probe.bpf.sym(addr, pid, show_offset=True).decode()) 305*387f9dfdSAndroid Build Coastguard Worker else: 306*387f9dfdSAndroid Build Coastguard Worker print("%s" % self.probe.bpf.sym(addr, pid).decode()) 307*387f9dfdSAndroid Build Coastguard Worker 308*387f9dfdSAndroid Build Coastguard Worker @staticmethod 309*387f9dfdSAndroid Build Coastguard Worker def _signal_ignore(signal, frame): 310*387f9dfdSAndroid Build Coastguard Worker print() 311*387f9dfdSAndroid Build Coastguard Worker 312*387f9dfdSAndroid Build Coastguard Worker def _print_comm(self, comm, pid): 313*387f9dfdSAndroid Build Coastguard Worker print(" %s [%d]" % (comm, pid)) 314*387f9dfdSAndroid Build Coastguard Worker 315*387f9dfdSAndroid Build Coastguard Worker def run(self): 316*387f9dfdSAndroid Build Coastguard Worker self.probe.load() 317*387f9dfdSAndroid Build Coastguard Worker self.probe.attach() 318*387f9dfdSAndroid Build Coastguard Worker if not self.args.folded: 319*387f9dfdSAndroid Build Coastguard Worker print("Tracing %d functions for \"%s\"... Hit Ctrl-C to end." % 320*387f9dfdSAndroid Build Coastguard Worker (self.probe.matched, self.args.pattern)) 321*387f9dfdSAndroid Build Coastguard Worker b = self.probe.bpf 322*387f9dfdSAndroid Build Coastguard Worker exiting = 0 if self.args.interval else 1 323*387f9dfdSAndroid Build Coastguard Worker seconds = 0 324*387f9dfdSAndroid Build Coastguard Worker while True: 325*387f9dfdSAndroid Build Coastguard Worker try: 326*387f9dfdSAndroid Build Coastguard Worker sleep(int(self.args.interval)) 327*387f9dfdSAndroid Build Coastguard Worker seconds += int(self.args.interval) 328*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 329*387f9dfdSAndroid Build Coastguard Worker exiting = 1 330*387f9dfdSAndroid Build Coastguard Worker # as cleanup can take many seconds, trap Ctrl-C: 331*387f9dfdSAndroid Build Coastguard Worker signal.signal(signal.SIGINT, Tool._signal_ignore) 332*387f9dfdSAndroid Build Coastguard Worker if self.args.duration and seconds >= int(self.args.duration): 333*387f9dfdSAndroid Build Coastguard Worker exiting = 1 334*387f9dfdSAndroid Build Coastguard Worker 335*387f9dfdSAndroid Build Coastguard Worker if not self.args.folded: 336*387f9dfdSAndroid Build Coastguard Worker print() 337*387f9dfdSAndroid Build Coastguard Worker if self.args.timestamp: 338*387f9dfdSAndroid Build Coastguard Worker print("%-8s\n" % strftime("%H:%M:%S"), end="") 339*387f9dfdSAndroid Build Coastguard Worker 340*387f9dfdSAndroid Build Coastguard Worker counts = self.probe.bpf["counts"] 341*387f9dfdSAndroid Build Coastguard Worker stack_traces = self.probe.bpf["stack_traces"] 342*387f9dfdSAndroid Build Coastguard Worker self.comm_cache = {} 343*387f9dfdSAndroid Build Coastguard Worker for k, v in sorted(counts.items(), 344*387f9dfdSAndroid Build Coastguard Worker key=lambda counts: counts[1].value): 345*387f9dfdSAndroid Build Coastguard Worker user_stack = [] if k.user_stack_id < 0 else \ 346*387f9dfdSAndroid Build Coastguard Worker stack_traces.walk(k.user_stack_id) 347*387f9dfdSAndroid Build Coastguard Worker kernel_stack = [] if k.kernel_stack_id < 0 else \ 348*387f9dfdSAndroid Build Coastguard Worker stack_traces.walk(k.kernel_stack_id) 349*387f9dfdSAndroid Build Coastguard Worker 350*387f9dfdSAndroid Build Coastguard Worker if self.args.folded: 351*387f9dfdSAndroid Build Coastguard Worker # print folded stack output 352*387f9dfdSAndroid Build Coastguard Worker user_stack = list(user_stack) 353*387f9dfdSAndroid Build Coastguard Worker kernel_stack = list(kernel_stack) 354*387f9dfdSAndroid Build Coastguard Worker line = [k.name.decode('utf-8', 'replace')] + \ 355*387f9dfdSAndroid Build Coastguard Worker [b.sym(addr, k.tgid).decode('utf-8', 'replace') for addr in 356*387f9dfdSAndroid Build Coastguard Worker reversed(user_stack)] + \ 357*387f9dfdSAndroid Build Coastguard Worker (self.need_delimiter and ["-"] or []) + \ 358*387f9dfdSAndroid Build Coastguard Worker [b.ksym(addr).decode('utf-8', 'replace') for addr in reversed(kernel_stack)] 359*387f9dfdSAndroid Build Coastguard Worker print("%s %d" % (";".join(line), v.value)) 360*387f9dfdSAndroid Build Coastguard Worker else: 361*387f9dfdSAndroid Build Coastguard Worker # print multi-line stack output 362*387f9dfdSAndroid Build Coastguard Worker for addr in kernel_stack: 363*387f9dfdSAndroid Build Coastguard Worker self._print_kframe(addr) 364*387f9dfdSAndroid Build Coastguard Worker if self.need_delimiter: 365*387f9dfdSAndroid Build Coastguard Worker print(" --") 366*387f9dfdSAndroid Build Coastguard Worker for addr in user_stack: 367*387f9dfdSAndroid Build Coastguard Worker self._print_uframe(addr, k.tgid) 368*387f9dfdSAndroid Build Coastguard Worker if not self.args.pid and k.tgid != 0xffffffff: 369*387f9dfdSAndroid Build Coastguard Worker self._print_comm(k.name, k.tgid) 370*387f9dfdSAndroid Build Coastguard Worker print(" %d\n" % v.value) 371*387f9dfdSAndroid Build Coastguard Worker counts.clear() 372*387f9dfdSAndroid Build Coastguard Worker 373*387f9dfdSAndroid Build Coastguard Worker if exiting: 374*387f9dfdSAndroid Build Coastguard Worker if not self.args.folded: 375*387f9dfdSAndroid Build Coastguard Worker print("Detaching...") 376*387f9dfdSAndroid Build Coastguard Worker exit() 377*387f9dfdSAndroid Build Coastguard Worker 378*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 379*387f9dfdSAndroid Build Coastguard Worker try: 380*387f9dfdSAndroid Build Coastguard Worker Tool().run() 381*387f9dfdSAndroid Build Coastguard Worker except Exception: 382*387f9dfdSAndroid Build Coastguard Worker if debug: 383*387f9dfdSAndroid Build Coastguard Worker traceback.print_exc() 384*387f9dfdSAndroid Build Coastguard Worker elif sys.exc_info()[0] is not SystemExit: 385*387f9dfdSAndroid Build Coastguard Worker print(sys.exc_info()[1]) 386