xref: /aosp_15_r20/external/bcc/tools/lib/ucalls.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
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# ucalls  Summarize method calls in high-level languages and/or system calls.
5*387f9dfdSAndroid Build Coastguard Worker#         For Linux, uses BCC, eBPF.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# USAGE: ucalls [-l {java,perl,php,python,ruby,tcl}] [-h] [-T TOP] [-L] [-S] [-v] [-m]
8*387f9dfdSAndroid Build Coastguard Worker#        pid [interval]
9*387f9dfdSAndroid Build Coastguard Worker#
10*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 Sasha Goldshtein
11*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
12*387f9dfdSAndroid Build Coastguard Worker#
13*387f9dfdSAndroid Build Coastguard Worker# 19-Oct-2016   Sasha Goldshtein   Created this.
14*387f9dfdSAndroid Build Coastguard Worker
15*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
16*387f9dfdSAndroid Build Coastguard Workerimport argparse
17*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep
18*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, USDT, utils
19*387f9dfdSAndroid Build Coastguard Workerfrom bcc.syscall import syscall_name
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Workerlanguages = ["java", "perl", "php", "python", "ruby", "tcl"]
22*387f9dfdSAndroid Build Coastguard Worker
23*387f9dfdSAndroid Build Coastguard Workerexamples = """examples:
24*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l java 185        # trace Java calls and print statistics on ^C
25*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l python 2020 1   # trace Python calls and print every second
26*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l java 185 -S     # trace Java calls and syscalls
27*387f9dfdSAndroid Build Coastguard Worker    ./ucalls 6712 -S            # trace only syscall counts
28*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l ruby 1344 -T 10 # trace top 10 Ruby method calls
29*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l ruby 1344 -L    # trace Ruby calls including latency
30*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l php 443 -LS     # trace PHP calls and syscalls with latency
31*387f9dfdSAndroid Build Coastguard Worker    ./ucalls -l python 2020 -mL # trace Python calls including latency in ms
32*387f9dfdSAndroid Build Coastguard Worker"""
33*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser(
34*387f9dfdSAndroid Build Coastguard Worker    description="Summarize method calls in high-level languages.",
35*387f9dfdSAndroid Build Coastguard Worker    formatter_class=argparse.RawDescriptionHelpFormatter,
36*387f9dfdSAndroid Build Coastguard Worker    epilog=examples)
37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("pid", type=int, help="process id to attach to")
38*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("interval", type=int, nargs='?',
39*387f9dfdSAndroid Build Coastguard Worker    help="print every specified number of seconds")
40*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-l", "--language", choices=languages + ["none"],
41*387f9dfdSAndroid Build Coastguard Worker    help="language to trace (if none, trace syscalls only)")
42*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--top", type=int,
43*387f9dfdSAndroid Build Coastguard Worker    help="number of most frequent/slow calls to print")
44*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-L", "--latency", action="store_true",
45*387f9dfdSAndroid Build Coastguard Worker    help="record method latency from enter to exit (except recursive calls)")
46*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-S", "--syscalls", action="store_true",
47*387f9dfdSAndroid Build Coastguard Worker    help="record syscall latency (adds overhead)")
48*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-v", "--verbose", action="store_true",
49*387f9dfdSAndroid Build Coastguard Worker    help="verbose mode: print the BPF program (for debugging purposes)")
50*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-m", "--milliseconds", action="store_true",
51*387f9dfdSAndroid Build Coastguard Worker    help="report times in milliseconds (default is microseconds)")
52*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true",
53*387f9dfdSAndroid Build Coastguard Worker    help=argparse.SUPPRESS)
54*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args()
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard Workerlanguage = args.language
57*387f9dfdSAndroid Build Coastguard Workerif not language:
58*387f9dfdSAndroid Build Coastguard Worker    language = utils.detect_language(languages, args.pid)
59*387f9dfdSAndroid Build Coastguard Worker
60*387f9dfdSAndroid Build Coastguard Worker# We assume that the entry and return probes have the same arguments. This is
61*387f9dfdSAndroid Build Coastguard Worker# the case for Java, Python, Ruby, and PHP. If there's a language where it's
62*387f9dfdSAndroid Build Coastguard Worker# not the case, we will need to build a custom correlator from entry to exit.
63*387f9dfdSAndroid Build Coastguard Workerextra_message = ""
64*387f9dfdSAndroid Build Coastguard Workerif language == "java":
65*387f9dfdSAndroid Build Coastguard Worker    # TODO for JVM entries, we actually have the real length of the class
66*387f9dfdSAndroid Build Coastguard Worker    #      and method strings in arg3 and arg5 respectively, so we can insert
67*387f9dfdSAndroid Build Coastguard Worker    #      the null terminator in its proper position.
68*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "method__entry"
69*387f9dfdSAndroid Build Coastguard Worker    return_probe = "method__return"
70*387f9dfdSAndroid Build Coastguard Worker    read_class = "bpf_usdt_readarg(2, ctx, &clazz);"
71*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(4, ctx, &method);"
72*387f9dfdSAndroid Build Coastguard Worker    extra_message = ("If you do not see any results, make sure you ran java"
73*387f9dfdSAndroid Build Coastguard Worker                     " with option -XX:+ExtendedDTraceProbes")
74*387f9dfdSAndroid Build Coastguard Workerelif language == "perl":
75*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "sub__entry"
76*387f9dfdSAndroid Build Coastguard Worker    return_probe = "sub__return"
77*387f9dfdSAndroid Build Coastguard Worker    read_class = "bpf_usdt_readarg(2, ctx, &clazz);"    # filename really
78*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(1, ctx, &method);"
79*387f9dfdSAndroid Build Coastguard Workerelif language == "php":
80*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "function__entry"
81*387f9dfdSAndroid Build Coastguard Worker    return_probe = "function__return"
82*387f9dfdSAndroid Build Coastguard Worker    read_class = "bpf_usdt_readarg(4, ctx, &clazz);"
83*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(1, ctx, &method);"
84*387f9dfdSAndroid Build Coastguard Worker    extra_message = ("If you do not see any results, make sure the environment"
85*387f9dfdSAndroid Build Coastguard Worker                     " variable USE_ZEND_DTRACE is set to 1")
86*387f9dfdSAndroid Build Coastguard Workerelif language == "python":
87*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "function__entry"
88*387f9dfdSAndroid Build Coastguard Worker    return_probe = "function__return"
89*387f9dfdSAndroid Build Coastguard Worker    read_class = "bpf_usdt_readarg(1, ctx, &clazz);"    # filename really
90*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(2, ctx, &method);"
91*387f9dfdSAndroid Build Coastguard Workerelif language == "ruby":
92*387f9dfdSAndroid Build Coastguard Worker    # TODO Also probe cmethod__entry and cmethod__return with same arguments
93*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "method__entry"
94*387f9dfdSAndroid Build Coastguard Worker    return_probe = "method__return"
95*387f9dfdSAndroid Build Coastguard Worker    read_class = "bpf_usdt_readarg(1, ctx, &clazz);"
96*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(2, ctx, &method);"
97*387f9dfdSAndroid Build Coastguard Workerelif language == "tcl":
98*387f9dfdSAndroid Build Coastguard Worker    # TODO Also consider probe cmd__entry and cmd__return with same arguments
99*387f9dfdSAndroid Build Coastguard Worker    entry_probe = "proc__entry"
100*387f9dfdSAndroid Build Coastguard Worker    return_probe = "proc__return"
101*387f9dfdSAndroid Build Coastguard Worker    read_class = ""  # no class/file info available
102*387f9dfdSAndroid Build Coastguard Worker    read_method = "bpf_usdt_readarg(1, ctx, &method);"
103*387f9dfdSAndroid Build Coastguard Workerelif not language or language == "none":
104*387f9dfdSAndroid Build Coastguard Worker    if not args.syscalls:
105*387f9dfdSAndroid Build Coastguard Worker        print("Nothing to do; use -S to trace syscalls.")
106*387f9dfdSAndroid Build Coastguard Worker        exit(1)
107*387f9dfdSAndroid Build Coastguard Worker    entry_probe, return_probe, read_class, read_method = ("", "", "", "")
108*387f9dfdSAndroid Build Coastguard Worker    if language:
109*387f9dfdSAndroid Build Coastguard Worker        language = None
110*387f9dfdSAndroid Build Coastguard Worker
111*387f9dfdSAndroid Build Coastguard Workerprogram = """
112*387f9dfdSAndroid Build Coastguard Worker#include <linux/ptrace.h>
113*387f9dfdSAndroid Build Coastguard Worker
114*387f9dfdSAndroid Build Coastguard Worker#define MAX_STRING_LENGTH 80
115*387f9dfdSAndroid Build Coastguard WorkerDEFINE_NOLANG
116*387f9dfdSAndroid Build Coastguard WorkerDEFINE_LATENCY
117*387f9dfdSAndroid Build Coastguard WorkerDEFINE_SYSCALLS
118*387f9dfdSAndroid Build Coastguard Worker
119*387f9dfdSAndroid Build Coastguard Workerstruct method_t {
120*387f9dfdSAndroid Build Coastguard Worker    char clazz[MAX_STRING_LENGTH];
121*387f9dfdSAndroid Build Coastguard Worker    char method[MAX_STRING_LENGTH];
122*387f9dfdSAndroid Build Coastguard Worker};
123*387f9dfdSAndroid Build Coastguard Workerstruct entry_t {
124*387f9dfdSAndroid Build Coastguard Worker    u64 pid;
125*387f9dfdSAndroid Build Coastguard Worker    struct method_t method;
126*387f9dfdSAndroid Build Coastguard Worker};
127*387f9dfdSAndroid Build Coastguard Workerstruct info_t {
128*387f9dfdSAndroid Build Coastguard Worker    u64 num_calls;
129*387f9dfdSAndroid Build Coastguard Worker    u64 total_ns;
130*387f9dfdSAndroid Build Coastguard Worker};
131*387f9dfdSAndroid Build Coastguard Workerstruct syscall_entry_t {
132*387f9dfdSAndroid Build Coastguard Worker    u64 timestamp;
133*387f9dfdSAndroid Build Coastguard Worker    u64 id;
134*387f9dfdSAndroid Build Coastguard Worker};
135*387f9dfdSAndroid Build Coastguard Worker
136*387f9dfdSAndroid Build Coastguard Worker#ifndef LATENCY
137*387f9dfdSAndroid Build Coastguard Worker  BPF_HASH(counts, struct method_t, u64);            // number of calls
138*387f9dfdSAndroid Build Coastguard Worker  #ifdef SYSCALLS
139*387f9dfdSAndroid Build Coastguard Worker    BPF_HASH(syscounts, u64, u64);                   // number of calls per IP
140*387f9dfdSAndroid Build Coastguard Worker  #endif  // SYSCALLS
141*387f9dfdSAndroid Build Coastguard Worker#else
142*387f9dfdSAndroid Build Coastguard Worker  BPF_HASH(times, struct method_t, struct info_t);
143*387f9dfdSAndroid Build Coastguard Worker  BPF_HASH(entry, struct entry_t, u64);              // timestamp at entry
144*387f9dfdSAndroid Build Coastguard Worker  #ifdef SYSCALLS
145*387f9dfdSAndroid Build Coastguard Worker    BPF_HASH(systimes, u64, struct info_t);          // latency per IP
146*387f9dfdSAndroid Build Coastguard Worker    BPF_HASH(sysentry, u64, struct syscall_entry_t); // ts + IP at entry
147*387f9dfdSAndroid Build Coastguard Worker  #endif  // SYSCALLS
148*387f9dfdSAndroid Build Coastguard Worker#endif
149*387f9dfdSAndroid Build Coastguard Worker
150*387f9dfdSAndroid Build Coastguard Worker#ifndef NOLANG
151*387f9dfdSAndroid Build Coastguard Workerint trace_entry(struct pt_regs *ctx) {
152*387f9dfdSAndroid Build Coastguard Worker    u64 clazz = 0, method = 0, val = 0;
153*387f9dfdSAndroid Build Coastguard Worker    u64 *valp;
154*387f9dfdSAndroid Build Coastguard Worker    struct entry_t data = {0};
155*387f9dfdSAndroid Build Coastguard Worker#ifdef LATENCY
156*387f9dfdSAndroid Build Coastguard Worker    u64 timestamp = bpf_ktime_get_ns();
157*387f9dfdSAndroid Build Coastguard Worker    data.pid = bpf_get_current_pid_tgid();
158*387f9dfdSAndroid Build Coastguard Worker#endif
159*387f9dfdSAndroid Build Coastguard Worker    READ_CLASS
160*387f9dfdSAndroid Build Coastguard Worker    READ_METHOD
161*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&data.method.clazz, sizeof(data.method.clazz),
162*387f9dfdSAndroid Build Coastguard Worker                   (void *)clazz);
163*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&data.method.method, sizeof(data.method.method),
164*387f9dfdSAndroid Build Coastguard Worker                   (void *)method);
165*387f9dfdSAndroid Build Coastguard Worker#ifndef LATENCY
166*387f9dfdSAndroid Build Coastguard Worker    valp = counts.lookup_or_try_init(&data.method, &val);
167*387f9dfdSAndroid Build Coastguard Worker    if (valp) {
168*387f9dfdSAndroid Build Coastguard Worker        ++(*valp);
169*387f9dfdSAndroid Build Coastguard Worker    }
170*387f9dfdSAndroid Build Coastguard Worker#endif
171*387f9dfdSAndroid Build Coastguard Worker#ifdef LATENCY
172*387f9dfdSAndroid Build Coastguard Worker    entry.update(&data, &timestamp);
173*387f9dfdSAndroid Build Coastguard Worker#endif
174*387f9dfdSAndroid Build Coastguard Worker    return 0;
175*387f9dfdSAndroid Build Coastguard Worker}
176*387f9dfdSAndroid Build Coastguard Worker
177*387f9dfdSAndroid Build Coastguard Worker#ifdef LATENCY
178*387f9dfdSAndroid Build Coastguard Workerint trace_return(struct pt_regs *ctx) {
179*387f9dfdSAndroid Build Coastguard Worker    u64 *entry_timestamp, clazz = 0, method = 0;
180*387f9dfdSAndroid Build Coastguard Worker    struct info_t *info, zero = {};
181*387f9dfdSAndroid Build Coastguard Worker    struct entry_t data = {};
182*387f9dfdSAndroid Build Coastguard Worker    data.pid = bpf_get_current_pid_tgid();
183*387f9dfdSAndroid Build Coastguard Worker    READ_CLASS
184*387f9dfdSAndroid Build Coastguard Worker    READ_METHOD
185*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&data.method.clazz, sizeof(data.method.clazz),
186*387f9dfdSAndroid Build Coastguard Worker                   (void *)clazz);
187*387f9dfdSAndroid Build Coastguard Worker    bpf_probe_read_user(&data.method.method, sizeof(data.method.method),
188*387f9dfdSAndroid Build Coastguard Worker                   (void *)method);
189*387f9dfdSAndroid Build Coastguard Worker    entry_timestamp = entry.lookup(&data);
190*387f9dfdSAndroid Build Coastguard Worker    if (!entry_timestamp) {
191*387f9dfdSAndroid Build Coastguard Worker        return 0;   // missed the entry event
192*387f9dfdSAndroid Build Coastguard Worker    }
193*387f9dfdSAndroid Build Coastguard Worker    info = times.lookup_or_try_init(&data.method, &zero);
194*387f9dfdSAndroid Build Coastguard Worker    if (info) {
195*387f9dfdSAndroid Build Coastguard Worker        info->num_calls += 1;
196*387f9dfdSAndroid Build Coastguard Worker        info->total_ns += bpf_ktime_get_ns() - *entry_timestamp;
197*387f9dfdSAndroid Build Coastguard Worker    }
198*387f9dfdSAndroid Build Coastguard Worker    entry.delete(&data);
199*387f9dfdSAndroid Build Coastguard Worker    return 0;
200*387f9dfdSAndroid Build Coastguard Worker}
201*387f9dfdSAndroid Build Coastguard Worker#endif  // LATENCY
202*387f9dfdSAndroid Build Coastguard Worker#endif  // NOLANG
203*387f9dfdSAndroid Build Coastguard Worker
204*387f9dfdSAndroid Build Coastguard Worker#ifdef SYSCALLS
205*387f9dfdSAndroid Build Coastguard WorkerTRACEPOINT_PROBE(raw_syscalls, sys_enter) {
206*387f9dfdSAndroid Build Coastguard Worker    u64 pid = bpf_get_current_pid_tgid();
207*387f9dfdSAndroid Build Coastguard Worker    u64 *valp, id = args->id, val = 0;
208*387f9dfdSAndroid Build Coastguard Worker    PID_FILTER
209*387f9dfdSAndroid Build Coastguard Worker#ifdef LATENCY
210*387f9dfdSAndroid Build Coastguard Worker    struct syscall_entry_t data = {};
211*387f9dfdSAndroid Build Coastguard Worker    data.timestamp = bpf_ktime_get_ns();
212*387f9dfdSAndroid Build Coastguard Worker    data.id = id;
213*387f9dfdSAndroid Build Coastguard Worker    sysentry.update(&pid, &data);
214*387f9dfdSAndroid Build Coastguard Worker#endif
215*387f9dfdSAndroid Build Coastguard Worker#ifndef LATENCY
216*387f9dfdSAndroid Build Coastguard Worker    valp = syscounts.lookup_or_try_init(&id, &val);
217*387f9dfdSAndroid Build Coastguard Worker    if (valp) {
218*387f9dfdSAndroid Build Coastguard Worker        ++(*valp);
219*387f9dfdSAndroid Build Coastguard Worker    }
220*387f9dfdSAndroid Build Coastguard Worker#endif
221*387f9dfdSAndroid Build Coastguard Worker    return 0;
222*387f9dfdSAndroid Build Coastguard Worker}
223*387f9dfdSAndroid Build Coastguard Worker
224*387f9dfdSAndroid Build Coastguard Worker#ifdef LATENCY
225*387f9dfdSAndroid Build Coastguard WorkerTRACEPOINT_PROBE(raw_syscalls, sys_exit) {
226*387f9dfdSAndroid Build Coastguard Worker    struct syscall_entry_t *e;
227*387f9dfdSAndroid Build Coastguard Worker    struct info_t *info, zero = {};
228*387f9dfdSAndroid Build Coastguard Worker    u64 pid = bpf_get_current_pid_tgid(), id;
229*387f9dfdSAndroid Build Coastguard Worker    PID_FILTER
230*387f9dfdSAndroid Build Coastguard Worker    e = sysentry.lookup(&pid);
231*387f9dfdSAndroid Build Coastguard Worker    if (!e) {
232*387f9dfdSAndroid Build Coastguard Worker        return 0;   // missed the entry event
233*387f9dfdSAndroid Build Coastguard Worker    }
234*387f9dfdSAndroid Build Coastguard Worker    id = e->id;
235*387f9dfdSAndroid Build Coastguard Worker    info = systimes.lookup_or_try_init(&id, &zero);
236*387f9dfdSAndroid Build Coastguard Worker    if (info) {
237*387f9dfdSAndroid Build Coastguard Worker        info->num_calls += 1;
238*387f9dfdSAndroid Build Coastguard Worker        info->total_ns += bpf_ktime_get_ns() - e->timestamp;
239*387f9dfdSAndroid Build Coastguard Worker    }
240*387f9dfdSAndroid Build Coastguard Worker    sysentry.delete(&pid);
241*387f9dfdSAndroid Build Coastguard Worker    return 0;
242*387f9dfdSAndroid Build Coastguard Worker}
243*387f9dfdSAndroid Build Coastguard Worker#endif  // LATENCY
244*387f9dfdSAndroid Build Coastguard Worker#endif  // SYSCALLS
245*387f9dfdSAndroid Build Coastguard Worker""".replace("READ_CLASS", read_class) \
246*387f9dfdSAndroid Build Coastguard Worker   .replace("READ_METHOD", read_method) \
247*387f9dfdSAndroid Build Coastguard Worker   .replace("PID_FILTER", "if ((pid >> 32) != %d) { return 0; }" % args.pid) \
248*387f9dfdSAndroid Build Coastguard Worker   .replace("DEFINE_NOLANG", "#define NOLANG" if not language else "") \
249*387f9dfdSAndroid Build Coastguard Worker   .replace("DEFINE_LATENCY", "#define LATENCY" if args.latency else "") \
250*387f9dfdSAndroid Build Coastguard Worker   .replace("DEFINE_SYSCALLS", "#define SYSCALLS" if args.syscalls else "")
251*387f9dfdSAndroid Build Coastguard Worker
252*387f9dfdSAndroid Build Coastguard Workerif language:
253*387f9dfdSAndroid Build Coastguard Worker    usdt = USDT(pid=args.pid)
254*387f9dfdSAndroid Build Coastguard Worker    usdt.enable_probe_or_bail(entry_probe, "trace_entry")
255*387f9dfdSAndroid Build Coastguard Worker    if args.latency:
256*387f9dfdSAndroid Build Coastguard Worker        usdt.enable_probe_or_bail(return_probe, "trace_return")
257*387f9dfdSAndroid Build Coastguard Workerelse:
258*387f9dfdSAndroid Build Coastguard Worker    usdt = None
259*387f9dfdSAndroid Build Coastguard Worker
260*387f9dfdSAndroid Build Coastguard Workerif args.ebpf or args.verbose:
261*387f9dfdSAndroid Build Coastguard Worker    if args.verbose and usdt:
262*387f9dfdSAndroid Build Coastguard Worker        print(usdt.get_text())
263*387f9dfdSAndroid Build Coastguard Worker    print(program)
264*387f9dfdSAndroid Build Coastguard Worker    if args.ebpf:
265*387f9dfdSAndroid Build Coastguard Worker        exit()
266*387f9dfdSAndroid Build Coastguard Worker
267*387f9dfdSAndroid Build Coastguard Workerbpf = BPF(text=program, usdt_contexts=[usdt] if usdt else [])
268*387f9dfdSAndroid Build Coastguard Workerif args.syscalls:
269*387f9dfdSAndroid Build Coastguard Worker    print("Attached kernel tracepoints for syscall tracing.")
270*387f9dfdSAndroid Build Coastguard Worker
271*387f9dfdSAndroid Build Coastguard Workerdef get_data():
272*387f9dfdSAndroid Build Coastguard Worker    # Will be empty when no language was specified for tracing
273*387f9dfdSAndroid Build Coastguard Worker    if args.latency:
274*387f9dfdSAndroid Build Coastguard Worker        data = list(map(lambda kv: (kv[0].clazz.decode('utf-8', 'replace') \
275*387f9dfdSAndroid Build Coastguard Worker                                    + "." + \
276*387f9dfdSAndroid Build Coastguard Worker                                    kv[0].method.decode('utf-8', 'replace'),
277*387f9dfdSAndroid Build Coastguard Worker                                   (kv[1].num_calls, kv[1].total_ns)),
278*387f9dfdSAndroid Build Coastguard Worker                   bpf["times"].items()))
279*387f9dfdSAndroid Build Coastguard Worker    else:
280*387f9dfdSAndroid Build Coastguard Worker        data = list(map(lambda kv: (kv[0].clazz.decode('utf-8', 'replace') \
281*387f9dfdSAndroid Build Coastguard Worker                                    + "." + \
282*387f9dfdSAndroid Build Coastguard Worker                                    kv[0].method.decode('utf-8', 'replace'),
283*387f9dfdSAndroid Build Coastguard Worker                                   (kv[1].value, 0)),
284*387f9dfdSAndroid Build Coastguard Worker                   bpf["counts"].items()))
285*387f9dfdSAndroid Build Coastguard Worker
286*387f9dfdSAndroid Build Coastguard Worker    if args.syscalls:
287*387f9dfdSAndroid Build Coastguard Worker        if args.latency:
288*387f9dfdSAndroid Build Coastguard Worker            syscalls = map(lambda kv: (syscall_name(kv[0].value).decode('utf-8', 'replace'),
289*387f9dfdSAndroid Build Coastguard Worker                                       (kv[1].num_calls, kv[1].total_ns)),
290*387f9dfdSAndroid Build Coastguard Worker                           bpf["systimes"].items())
291*387f9dfdSAndroid Build Coastguard Worker            data.extend(syscalls)
292*387f9dfdSAndroid Build Coastguard Worker        else:
293*387f9dfdSAndroid Build Coastguard Worker            syscalls = map(lambda kv: (syscall_name(kv[0].value).decode('utf-8', 'replace'),
294*387f9dfdSAndroid Build Coastguard Worker                                       (kv[1].value, 0)),
295*387f9dfdSAndroid Build Coastguard Worker                           bpf["syscounts"].items())
296*387f9dfdSAndroid Build Coastguard Worker            data.extend(syscalls)
297*387f9dfdSAndroid Build Coastguard Worker
298*387f9dfdSAndroid Build Coastguard Worker    return sorted(data, key=lambda kv: kv[1][1 if args.latency else 0])
299*387f9dfdSAndroid Build Coastguard Worker
300*387f9dfdSAndroid Build Coastguard Workerdef clear_data():
301*387f9dfdSAndroid Build Coastguard Worker    if args.latency:
302*387f9dfdSAndroid Build Coastguard Worker        bpf["times"].clear()
303*387f9dfdSAndroid Build Coastguard Worker    else:
304*387f9dfdSAndroid Build Coastguard Worker        bpf["counts"].clear()
305*387f9dfdSAndroid Build Coastguard Worker
306*387f9dfdSAndroid Build Coastguard Worker    if args.syscalls:
307*387f9dfdSAndroid Build Coastguard Worker        if args.latency:
308*387f9dfdSAndroid Build Coastguard Worker            bpf["systimes"].clear()
309*387f9dfdSAndroid Build Coastguard Worker        else:
310*387f9dfdSAndroid Build Coastguard Worker            bpf["syscounts"].clear()
311*387f9dfdSAndroid Build Coastguard Worker
312*387f9dfdSAndroid Build Coastguard Workerexit_signaled = False
313*387f9dfdSAndroid Build Coastguard Workerprint("Tracing calls in process %d (language: %s)... Ctrl-C to quit." %
314*387f9dfdSAndroid Build Coastguard Worker      (args.pid, language or "none"))
315*387f9dfdSAndroid Build Coastguard Workerif extra_message:
316*387f9dfdSAndroid Build Coastguard Worker    print(extra_message)
317*387f9dfdSAndroid Build Coastguard Workerwhile True:
318*387f9dfdSAndroid Build Coastguard Worker    try:
319*387f9dfdSAndroid Build Coastguard Worker        sleep(args.interval or 99999999)
320*387f9dfdSAndroid Build Coastguard Worker    except KeyboardInterrupt:
321*387f9dfdSAndroid Build Coastguard Worker        exit_signaled = True
322*387f9dfdSAndroid Build Coastguard Worker    print()
323*387f9dfdSAndroid Build Coastguard Worker    data = get_data()   # [(function, (num calls, latency in ns))]
324*387f9dfdSAndroid Build Coastguard Worker    if args.latency:
325*387f9dfdSAndroid Build Coastguard Worker        time_col = "TIME (ms)" if args.milliseconds else "TIME (us)"
326*387f9dfdSAndroid Build Coastguard Worker        print("%-50s %8s %8s" % ("METHOD", "# CALLS", time_col))
327*387f9dfdSAndroid Build Coastguard Worker    else:
328*387f9dfdSAndroid Build Coastguard Worker        print("%-50s %8s" % ("METHOD", "# CALLS"))
329*387f9dfdSAndroid Build Coastguard Worker    if args.top:
330*387f9dfdSAndroid Build Coastguard Worker        data = data[-args.top:]
331*387f9dfdSAndroid Build Coastguard Worker    for key, value in data:
332*387f9dfdSAndroid Build Coastguard Worker        if args.latency:
333*387f9dfdSAndroid Build Coastguard Worker            time = value[1] / 1000000.0 if args.milliseconds else \
334*387f9dfdSAndroid Build Coastguard Worker                   value[1] / 1000.0
335*387f9dfdSAndroid Build Coastguard Worker            print("%-50s %8d %6.2f" % (key, value[0], time))
336*387f9dfdSAndroid Build Coastguard Worker        else:
337*387f9dfdSAndroid Build Coastguard Worker            print("%-50s %8d" % (key, value[0]))
338*387f9dfdSAndroid Build Coastguard Worker    if args.interval and not exit_signaled:
339*387f9dfdSAndroid Build Coastguard Worker        clear_data()
340*387f9dfdSAndroid Build Coastguard Worker    else:
341*387f9dfdSAndroid Build Coastguard Worker        if args.syscalls:
342*387f9dfdSAndroid Build Coastguard Worker            print("Detaching kernel probes, please wait...")
343*387f9dfdSAndroid Build Coastguard Worker        exit()
344