xref: /aosp_15_r20/external/bcc/examples/tracing/stack_buildid_example.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# An example usage of stack_build_id
4*387f9dfdSAndroid Build Coastguard Worker# Most of the code here is borrowed from tools/profile.py
5*387f9dfdSAndroid Build Coastguard Worker#
6*387f9dfdSAndroid Build Coastguard Worker# Steps for using this code
7*387f9dfdSAndroid Build Coastguard Worker# 1) Start ping program in one terminal eg invocation: ping google.com -i0.001
8*387f9dfdSAndroid Build Coastguard Worker# 2) Change the path of libc specified in b.add_module() below
9*387f9dfdSAndroid Build Coastguard Worker# 3) Invoke the script as 'python stack_buildid_example.py'
10*387f9dfdSAndroid Build Coastguard Worker# 4) o/p of the tool is as shown below
11*387f9dfdSAndroid Build Coastguard Worker#  python example/tracing/stack_buildid_example.py
12*387f9dfdSAndroid Build Coastguard Worker#    sendto
13*387f9dfdSAndroid Build Coastguard Worker#    -                ping (5232)
14*387f9dfdSAndroid Build Coastguard Worker#        2
15*387f9dfdSAndroid Build Coastguard Worker#
16*387f9dfdSAndroid Build Coastguard Worker# REQUIRES: Linux 4.17+ (BPF_BUILD_ID support)
17*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
18*387f9dfdSAndroid Build Coastguard Worker# 03-Jan-2019  Vijay Nag
19*387f9dfdSAndroid Build Coastguard Worker
20*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
21*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF, PerfType, PerfSWConfig
22*387f9dfdSAndroid Build Coastguard Workerfrom sys import stderr
23*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep
24*387f9dfdSAndroid Build Coastguard Workerimport argparse
25*387f9dfdSAndroid Build Coastguard Workerimport signal
26*387f9dfdSAndroid Build Coastguard Workerimport os
27*387f9dfdSAndroid Build Coastguard Workerimport subprocess
28*387f9dfdSAndroid Build Coastguard Workerimport errno
29*387f9dfdSAndroid Build Coastguard Workerimport multiprocessing
30*387f9dfdSAndroid Build Coastguard Workerimport ctypes as ct
31*387f9dfdSAndroid Build Coastguard Worker
32*387f9dfdSAndroid Build Coastguard Workerdef Get_libc_path():
33*387f9dfdSAndroid Build Coastguard Worker  # A small helper function that returns full path
34*387f9dfdSAndroid Build Coastguard Worker  # of libc in the system
35*387f9dfdSAndroid Build Coastguard Worker  cmd = 'cat /proc/self/maps | grep libc | awk \'{print $6}\' | uniq'
36*387f9dfdSAndroid Build Coastguard Worker  output = subprocess.check_output(cmd, shell=True)
37*387f9dfdSAndroid Build Coastguard Worker  if not isinstance(output, str):
38*387f9dfdSAndroid Build Coastguard Worker    output = output.decode()
39*387f9dfdSAndroid Build Coastguard Worker  return output.split('\n')[0]
40*387f9dfdSAndroid Build Coastguard Worker
41*387f9dfdSAndroid Build Coastguard Workerbpf_text = """
42*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
43*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/bpf_perf_event.h>
44*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h>
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Workerstruct key_t {
47*387f9dfdSAndroid Build Coastguard Worker    u32 pid;
48*387f9dfdSAndroid Build Coastguard Worker    int user_stack_id;
49*387f9dfdSAndroid Build Coastguard Worker    char name[TASK_COMM_LEN];
50*387f9dfdSAndroid Build Coastguard Worker};
51*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(counts, struct key_t);
52*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE_BUILDID(stack_traces, 128);
53*387f9dfdSAndroid Build Coastguard Worker
54*387f9dfdSAndroid Build Coastguard Workerint do_perf_event(struct bpf_perf_event_data *ctx) {
55*387f9dfdSAndroid Build Coastguard Worker    u32 pid = bpf_get_current_pid_tgid() >> 32;
56*387f9dfdSAndroid Build Coastguard Worker
57*387f9dfdSAndroid Build Coastguard Worker    // create map key
58*387f9dfdSAndroid Build Coastguard Worker    struct key_t key = {.pid = pid};
59*387f9dfdSAndroid Build Coastguard Worker    bpf_get_current_comm(&key.name, sizeof(key.name));
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker    key.user_stack_id = stack_traces.get_stackid(&ctx->regs, BPF_F_USER_STACK);
62*387f9dfdSAndroid Build Coastguard Worker
63*387f9dfdSAndroid Build Coastguard Worker    if (key.user_stack_id >= 0) {
64*387f9dfdSAndroid Build Coastguard Worker      counts.increment(key);
65*387f9dfdSAndroid Build Coastguard Worker    }
66*387f9dfdSAndroid Build Coastguard Worker    return 0;
67*387f9dfdSAndroid Build Coastguard Worker}
68*387f9dfdSAndroid Build Coastguard Worker"""
69*387f9dfdSAndroid Build Coastguard Worker
70*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text)
71*387f9dfdSAndroid Build Coastguard Workerb.attach_perf_event(ev_type=PerfType.SOFTWARE,
72*387f9dfdSAndroid Build Coastguard Worker    ev_config=PerfSWConfig.CPU_CLOCK, fn_name="do_perf_event",
73*387f9dfdSAndroid Build Coastguard Worker    sample_period=0, sample_freq=49, cpu=0)
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker# Add the list of libraries/executables to the build sym cache for sym resolution
76*387f9dfdSAndroid Build Coastguard Worker# Change the libc path if it is different on a different machine.
77*387f9dfdSAndroid Build Coastguard Worker# libc.so and ping are added here so that any symbols pertaining to
78*387f9dfdSAndroid Build Coastguard Worker# libc or ping are resolved. More executables/libraries can be added here.
79*387f9dfdSAndroid Build Coastguard Workerb.add_module(Get_libc_path())
80*387f9dfdSAndroid Build Coastguard Workerb.add_module("/usr/sbin/sshd")
81*387f9dfdSAndroid Build Coastguard Workerb.add_module("/bin/ping")
82*387f9dfdSAndroid Build Coastguard Workercounts = b.get_table("counts")
83*387f9dfdSAndroid Build Coastguard Workerstack_traces = b.get_table("stack_traces")
84*387f9dfdSAndroid Build Coastguard Workerduration = 2
85*387f9dfdSAndroid Build Coastguard Worker
86*387f9dfdSAndroid Build Coastguard Workerdef signal_handler(signal, frame):
87*387f9dfdSAndroid Build Coastguard Worker  print()
88*387f9dfdSAndroid Build Coastguard Worker
89*387f9dfdSAndroid Build Coastguard Workertry:
90*387f9dfdSAndroid Build Coastguard Worker    sleep(duration)
91*387f9dfdSAndroid Build Coastguard Workerexcept KeyboardInterrupt:
92*387f9dfdSAndroid Build Coastguard Worker    # as cleanup can take some time, trap Ctrl-C:
93*387f9dfdSAndroid Build Coastguard Worker    signal.signal(signal.SIGINT, signal.SIG_IGN)
94*387f9dfdSAndroid Build Coastguard Worker
95*387f9dfdSAndroid Build Coastguard Workeruser_stack=[]
96*387f9dfdSAndroid Build Coastguard Workerfor k,v in sorted(counts.items(), key=lambda counts: counts[1].value):
97*387f9dfdSAndroid Build Coastguard Worker  user_stack = [] if k.user_stack_id < 0 else \
98*387f9dfdSAndroid Build Coastguard Worker      stack_traces.walk(k.user_stack_id)
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker  user_stack=list(user_stack)
101*387f9dfdSAndroid Build Coastguard Worker  for addr in user_stack:
102*387f9dfdSAndroid Build Coastguard Worker    print("    %s" % b.sym(addr, k.pid).decode('utf-8', 'replace'))
103*387f9dfdSAndroid Build Coastguard Worker  print("    %-16s %s (%d)" % ("-", k.name.decode('utf-8', 'replace'), k.pid))
104*387f9dfdSAndroid Build Coastguard Worker  print("        %d\n" % v.value)
105*387f9dfdSAndroid Build Coastguard Worker
106