xref: /aosp_15_r20/external/bcc/tools/stackcount.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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