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