memleak: Migrate to new symbols resolution API
Remove usyms.py dependency and replace with new symbols API.
diff --git a/tools/memleak.py b/tools/memleak.py
index e9856ea..e5034cf 100755
--- a/tools/memleak.py
+++ b/tools/memleak.py
@@ -11,31 +11,13 @@
# Licensed under the Apache License, Version 2.0 (the "License")
# Copyright (C) 2016 Sasha Goldshtein.
-from bcc import BPF, ProcessSymbols
+from bcc import BPF
from time import sleep
from datetime import datetime
import argparse
import subprocess
import os
-class KStackDecoder(object):
- def refresh(self):
- pass
-
- def __call__(self, addr):
- return "%s [kernel] (%x)" % (BPF.ksym(addr), addr)
-
-class UStackDecoder(object):
- def __init__(self, pid):
- self.pid = pid
- self.proc_sym = ProcessSymbols(pid)
-
- def refresh(self):
- self.proc_sym.refresh_code_ranges()
-
- def __call__(self, addr):
- return "%s (%x)" % (self.proc_sym.decode_addr(addr), addr)
-
class Allocation(object):
def __init__(self, stack, size):
self.stack = stack
@@ -240,8 +222,6 @@
bpf_program.attach_kretprobe(event="__kmalloc", fn_name="alloc_exit")
bpf_program.attach_kprobe(event="kfree", fn_name="free_enter")
-decoder = KStackDecoder() if kernel_trace else UStackDecoder(pid)
-
def print_outstanding():
print("[%s] Top %d stacks with outstanding allocations:" %
(datetime.now().strftime("%H:%M:%S"), top_stacks))
@@ -256,8 +236,12 @@
if info.stack_id in alloc_info:
alloc_info[info.stack_id].update(info.size)
else:
- stack = list(stack_traces.walk(info.stack_id, decoder))
- alloc_info[info.stack_id] = Allocation(stack,
+ stack = list(stack_traces.walk(info.stack_id))
+ combined = []
+ for addr in stack:
+ combined.append(bpf_program.sym(addr, pid,
+ show_module=True, show_address=True))
+ alloc_info[info.stack_id] = Allocation(combined,
info.size)
if args.show_allocs:
print("\taddr = %x size = %s" %
@@ -277,7 +261,6 @@
sleep(interval)
except KeyboardInterrupt:
exit()
- decoder.refresh()
print_outstanding()
count_so_far += 1
if num_prints is not None and count_so_far >= num_prints:
diff --git a/tools/memleak_example.txt b/tools/memleak_example.txt
index 5b6f8d4..accc74f 100644
--- a/tools/memleak_example.txt
+++ b/tools/memleak_example.txt
@@ -10,13 +10,13 @@
Attaching to malloc and free in pid 5193, Ctrl+C to quit.
[11:16:33] Top 2 stacks with outstanding allocations:
80 bytes in 5 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fd460ac2790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
[11:16:34] Top 2 stacks with outstanding allocations:
160 bytes in 10 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fd460ac2790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
Each entry printed is a set of allocations that originate from the same call
@@ -40,8 +40,8 @@
addr = 948d30 size = 16
addr = 948cf0 size = 16
64 bytes in 4 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fd460ac2790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
[11:16:34] Top 2 stacks with outstanding allocations:
addr = 948d50 size = 16
@@ -55,8 +55,8 @@
addr = 948d70 size = 16
addr = 948df0 size = 16
160 bytes in 10 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fd460ac2790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
When using the -p switch, memleak traces the allocations of a particular
@@ -67,35 +67,35 @@
Attaching to kmalloc and kfree, Ctrl+C to quit.
...
248 bytes in 4 allocations from stack
- bpf_prog_load [kernel] (ffffffff8118c471)
- sys_bpf [kernel] (ffffffff8118c8b5)
+ bpf_prog_load [kernel]
+ sys_bpf [kernel]
328 bytes in 1 allocations from stack
- perf_mmap [kernel] (ffffffff811990fd)
- mmap_region [kernel] (ffffffff811df5d4)
- do_mmap [kernel] (ffffffff811dfb83)
- vm_mmap_pgoff [kernel] (ffffffff811c494f)
- sys_mmap_pgoff [kernel] (ffffffff811ddf02)
- sys_mmap [kernel] (ffffffff8101b0ab)
+ perf_mmap [kernel]
+ mmap_region [kernel]
+ do_mmap [kernel]
+ vm_mmap_pgoff [kernel]
+ sys_mmap_pgoff [kernel]
+ sys_mmap [kernel]
464 bytes in 1 allocations from stack
- traceprobe_command [kernel] (ffffffff81187cf2)
- traceprobe_probes_write [kernel] (ffffffff81187d86)
- probes_write [kernel] (ffffffff81181580)
- __vfs_write [kernel] (ffffffff812237b7)
- vfs_write [kernel] (ffffffff81223ec6)
- sys_write [kernel] (ffffffff81224b85)
- entry_SYSCALL_64_fastpath [kernel] (ffffffff8178182e)
+ traceprobe_command [kernel]
+ traceprobe_probes_write [kernel]
+ probes_write [kernel]
+ __vfs_write [kernel]
+ vfs_write [kernel]
+ sys_write [kernel]
+ entry_SYSCALL_64_fastpath [kernel]
8192 bytes in 1 allocations from stack
- alloc_and_copy_ftrace_hash.constprop.59 [kernel] (ffffffff8115d17e)
- ftrace_set_hash [kernel] (ffffffff8115e767)
- ftrace_set_filter_ip [kernel] (ffffffff8115e9a8)
- arm_kprobe [kernel] (ffffffff81148600)
- enable_kprobe [kernel] (ffffffff811486f6)
- kprobe_register [kernel] (ffffffff81182399)
- perf_trace_init [kernel] (ffffffff8117c4e0)
- perf_tp_event_init [kernel] (ffffffff81192479)
+ alloc_and_copy_ftrace_hash.constprop.59 [kernel]
+ ftrace_set_hash [kernel]
+ ftrace_set_filter_ip [kernel]
+ arm_kprobe [kernel]
+ enable_kprobe [kernel]
+ kprobe_register [kernel]
+ perf_trace_init [kernel]
+ perf_tp_event_init [kernel]
Here you can see that arming the kprobe to which our eBPF program is attached
@@ -129,18 +129,18 @@
Attaching to malloc and free in pid 2614, Ctrl+C to quit.
[11:16:33] Top 2 stacks with outstanding allocations:
16 bytes in 1 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fdc11ce8790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
[11:16:38] Top 2 stacks with outstanding allocations:
16 bytes in 1 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fdc11ce8790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
[11:16:43] Top 2 stacks with outstanding allocations:
32 bytes in 2 allocations from stack
- main+0x6d [/home/vagrant/allocs] (400862)
- __libc_start_main+0xf0 [/usr/lib64/libc-2.21.so] (7fdc11ce8790)
+ main+0x6d [allocs]
+ __libc_start_main+0xf0 [libc-2.21.so]
Note that even though the application leaks 16 bytes of memory every second,
the report (printed every 5 seconds) doesn't "see" all the allocations because
diff --git a/tools/old/memleak.py b/tools/old/memleak.py
index bff7cfd..0e42a4f 100755
--- a/tools/old/memleak.py
+++ b/tools/old/memleak.py
@@ -11,36 +11,21 @@
# Licensed under the Apache License, Version 2.0 (the "License")
# Copyright (C) 2016 Sasha Goldshtein.
-from bcc import BPF, ProcessSymbols
+from bcc import BPF, SymbolCache
from time import sleep
from datetime import datetime
import argparse
import subprocess
import os
-class StackDecoder(object):
- def __init__(self, pid):
- self.pid = pid
- if pid != -1:
- self.proc_sym = ProcessSymbols(pid)
-
- def refresh(self):
- if self.pid != -1:
- self.proc_sym.refresh_code_ranges()
-
- def decode_stack(self, info, is_kernel_trace):
- stack = ""
- if info.num_frames <= 0:
- return "???"
- for i in range(0, info.num_frames):
- addr = info.callstack[i]
- if is_kernel_trace:
- stack += " %s [kernel] (%x) ;" % \
- (BPF.ksym(addr), addr)
- else:
- stack += " %s (%x) ;" % \
- (self.proc_sym.decode_addr(addr), addr)
- return stack
+def decode_stack(bpf, pid, info):
+ stack = ""
+ if info.num_frames <= 0:
+ return "???"
+ for i in range(0, info.num_frames):
+ addr = info.callstack[i]
+ stack += " %s ;" % bpf.sym(addr, pid, show_address=True)
+ return stack
def run_command_get_output(command):
p = subprocess.Popen(command.split(),
@@ -255,8 +240,6 @@
bpf_program.attach_kretprobe(event="__kmalloc", fn_name="alloc_exit")
bpf_program.attach_kprobe(event="kfree", fn_name="free_enter")
-decoder = StackDecoder(pid)
-
def print_outstanding():
stacks = {}
print("[%s] Top %d stacks with outstanding allocations:" %
@@ -265,7 +248,7 @@
for address, info in sorted(allocs.items(), key=lambda a: a[1].size):
if BPF.monotonic_time() - min_age_ns < info.timestamp_ns:
continue
- stack = decoder.decode_stack(info, kernel_trace)
+ stack = decode_stack(bpf_program, pid, info)
if stack in stacks:
stacks[stack] = (stacks[stack][0] + 1,
stacks[stack][1] + info.size)
@@ -288,7 +271,6 @@
sleep(interval)
except KeyboardInterrupt:
exit()
- decoder.refresh()
print_outstanding()
count_so_far += 1
if num_prints is not None and count_so_far >= num_prints: