blob: 0def220f33027e3c6d2d96c8504f8f6b21dc23a4 [file] [log] [blame]
Vicent Marti88899062016-03-25 23:22:57 +01001#!/usr/bin/python
2#
3# mallocstacks Trace malloc() calls in a process and print the full
4# stack trace for all callsites.
5# For Linux, uses BCC, eBPF. Embedded C.
6#
7# This script is a basic example of the new Linux 4.6+ BPF_STACK_TRACE
8# table API.
9#
10# Copyright 2016 GitHub, Inc.
11# Licensed under the Apache License, Version 2.0 (the "License")
12
13from __future__ import print_function
Sasha Goldshtein98f5d4e2017-02-08 20:54:56 -050014from bcc import BPF
Vicent Marti88899062016-03-25 23:22:57 +010015from time import sleep
16import sys
17
18if len(sys.argv) < 2:
19 print("USAGE: mallocstacks PID")
20 exit()
21pid = int(sys.argv[1])
22
23# load BPF program
24b = BPF(text="""
25#include <uapi/linux/ptrace.h>
26
27BPF_HASH(calls, int);
Song Liu67ae6052018-02-01 14:59:24 -080028BPF_STACK_TRACE(stack_traces, 1024);
Vicent Marti88899062016-03-25 23:22:57 +010029
30int alloc_enter(struct pt_regs *ctx, size_t size) {
31 int key = stack_traces.get_stackid(ctx,
32 BPF_F_USER_STACK|BPF_F_REUSE_STACKID);
33 if (key < 0)
34 return 0;
35
36 u64 zero = 0, *val;
37 val = calls.lookup_or_init(&key, &zero);
38 (*val) += size;
39 return 0;
40};
41""")
42
43b.attach_uprobe(name="c", sym="malloc", fn_name="alloc_enter", pid=pid)
44print("Attaching to malloc in pid %d, Ctrl+C to quit." % pid)
45
Vicent Marti88899062016-03-25 23:22:57 +010046# sleep until Ctrl-C
47try:
48 sleep(99999999)
49except KeyboardInterrupt:
50 pass
51
52calls = b.get_table("calls")
53stack_traces = b.get_table("stack_traces")
54
55for k, v in reversed(sorted(calls.items(), key=lambda c: c[1].value)):
56 print("%d bytes allocated at:" % v.value)
57 for addr in stack_traces.walk(k.value):
Sasha Goldshtein01553852017-02-09 03:58:09 -050058 print("\t%s" % b.sym(addr, pid, show_offset=True))