xref: /aosp_15_r20/external/bcc/examples/tracing/mallocstacks.py (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python
2*387f9dfdSAndroid Build Coastguard Worker#
3*387f9dfdSAndroid Build Coastguard Worker# mallocstacks  Trace malloc() calls in a process and print the full
4*387f9dfdSAndroid Build Coastguard Worker#               stack trace for all callsites.
5*387f9dfdSAndroid Build Coastguard Worker#               For Linux, uses BCC, eBPF. Embedded C.
6*387f9dfdSAndroid Build Coastguard Worker#
7*387f9dfdSAndroid Build Coastguard Worker# This script is a basic example of the new Linux 4.6+ BPF_STACK_TRACE
8*387f9dfdSAndroid Build Coastguard Worker# table API.
9*387f9dfdSAndroid Build Coastguard Worker#
10*387f9dfdSAndroid Build Coastguard Worker# Copyright 2016 GitHub, Inc.
11*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License")
12*387f9dfdSAndroid Build Coastguard Worker
13*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function
14*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF
15*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import printb
16*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep
17*387f9dfdSAndroid Build Coastguard Workerimport sys
18*387f9dfdSAndroid Build Coastguard Worker
19*387f9dfdSAndroid Build Coastguard Workerif len(sys.argv) < 2:
20*387f9dfdSAndroid Build Coastguard Worker    print("USAGE: mallocstacks PID [NUM_STACKS=1024]")
21*387f9dfdSAndroid Build Coastguard Worker    exit()
22*387f9dfdSAndroid Build Coastguard Workerpid = int(sys.argv[1])
23*387f9dfdSAndroid Build Coastguard Workerif len(sys.argv) == 3:
24*387f9dfdSAndroid Build Coastguard Worker    try:
25*387f9dfdSAndroid Build Coastguard Worker        assert int(sys.argv[2]) > 0, ""
26*387f9dfdSAndroid Build Coastguard Worker    except (ValueError, AssertionError) as e:
27*387f9dfdSAndroid Build Coastguard Worker        print("USAGE: mallocstacks PID [NUM_STACKS=1024]")
28*387f9dfdSAndroid Build Coastguard Worker        print("NUM_STACKS must be a non-zero, positive integer")
29*387f9dfdSAndroid Build Coastguard Worker        exit()
30*387f9dfdSAndroid Build Coastguard Worker    stacks = sys.argv[2]
31*387f9dfdSAndroid Build Coastguard Workerelse:
32*387f9dfdSAndroid Build Coastguard Worker    stacks = "1024"
33*387f9dfdSAndroid Build Coastguard Worker
34*387f9dfdSAndroid Build Coastguard Worker# load BPF program
35*387f9dfdSAndroid Build Coastguard Workerb = BPF(text="""
36*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h>
37*387f9dfdSAndroid Build Coastguard Worker
38*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(calls, int);
39*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, """ + stacks + """);
40*387f9dfdSAndroid Build Coastguard Worker
41*387f9dfdSAndroid Build Coastguard Workerint alloc_enter(struct pt_regs *ctx, size_t size) {
42*387f9dfdSAndroid Build Coastguard Worker    int key = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);
43*387f9dfdSAndroid Build Coastguard Worker    if (key < 0)
44*387f9dfdSAndroid Build Coastguard Worker        return 0;
45*387f9dfdSAndroid Build Coastguard Worker
46*387f9dfdSAndroid Build Coastguard Worker    // could also use `calls.increment(key, size);`
47*387f9dfdSAndroid Build Coastguard Worker    u64 zero = 0, *val;
48*387f9dfdSAndroid Build Coastguard Worker    val = calls.lookup_or_try_init(&key, &zero);
49*387f9dfdSAndroid Build Coastguard Worker    if (val) {
50*387f9dfdSAndroid Build Coastguard Worker      (*val) += size;
51*387f9dfdSAndroid Build Coastguard Worker    }
52*387f9dfdSAndroid Build Coastguard Worker    return 0;
53*387f9dfdSAndroid Build Coastguard Worker};
54*387f9dfdSAndroid Build Coastguard Worker""")
55*387f9dfdSAndroid Build Coastguard Worker
56*387f9dfdSAndroid Build Coastguard Workerb.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid)
57*387f9dfdSAndroid Build Coastguard Workerprint("Attaching to malloc in pid %d, Ctrl+C to quit." % pid)
58*387f9dfdSAndroid Build Coastguard Worker
59*387f9dfdSAndroid Build Coastguard Worker# sleep until Ctrl-C
60*387f9dfdSAndroid Build Coastguard Workertry:
61*387f9dfdSAndroid Build Coastguard Worker    sleep(99999999)
62*387f9dfdSAndroid Build Coastguard Workerexcept KeyboardInterrupt:
63*387f9dfdSAndroid Build Coastguard Worker    pass
64*387f9dfdSAndroid Build Coastguard Worker
65*387f9dfdSAndroid Build Coastguard Workercalls = b.get_table("calls")
66*387f9dfdSAndroid Build Coastguard Workerstack_traces = b.get_table("stack_traces")
67*387f9dfdSAndroid Build Coastguard Worker
68*387f9dfdSAndroid Build Coastguard Workerfor k, v in reversed(sorted(calls.items(), key=lambda c: c[1].value)):
69*387f9dfdSAndroid Build Coastguard Worker    print("%d bytes allocated at:" % v.value)
70*387f9dfdSAndroid Build Coastguard Worker    if k.value > 0 :
71*387f9dfdSAndroid Build Coastguard Worker        for addr in stack_traces.walk(k.value):
72*387f9dfdSAndroid Build Coastguard Worker            printb(b"\t%s" % b.sym(addr, pid, show_offset=True))
73