Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
libbpf-tools: Fix trace_helper symbol search bug
dso__find_sym function considers elf file is not stripped. So it could find wrong symbol if the target elf file is stripped. Consider if the start address of each function 'foo', 'bar', 'baz' is '0x1000', '0x4000', '0x9000' respectively, and 'bar' is stripped. If user wants to find the symbol of address '0x4080', user expected result will be 'bar', and dso__find_sym function expected result will be NULL, but actual result is 'foo' which is incorrect. To fix this problem, use symbol size on dso__find_sym function to check whether the offset exists within the found symbol range. strip can be used to remove certain non-allocable sections from the elf file. This reduces file size by throwing away information. static function name is one of the most popular non-allocable information. Please refer this document for further information: http:https://www.linker-aliens.org/blogs/ali/entry/inside_elf_symbol_tables/ Followings are the way to reproduce this issue with tool memleak and tell how this patch fix this issue. On folder bcc/libbpf-tools Build test program a.out with file libtest.c and test.c $ gcc -c -o libtest.o libtest.c $ ld -shared libtest.o -o libtest.so $ gcc test.c -L. -ltest File libtest.c #include <stdlib.h> int* foo() { return NULL; } static int* bar() { return malloc(4); } int* baz() { return bar(); } File test.c #include <unistd.h> int* baz(); int main(int argc, char* argv[]) { int *a; while (1) { sleep(5); a = baz(); } return 0; } Build memleak without blazesym $ USE_BLAZESYM=0 make memleak Run test program a.out and check the normal result $ LD_LIBRARY_PATH=. ./a.out & [1] 335459 $ sudo ./memleak -p 335459 using default object: libc.so.6 using page size: 4096 tracing kernel: false Tracing outstanding memory allocs... Hit Ctrl-C to end [13:31:12] Top 1 stacks with outstanding allocations: 4 bytes in 1 allocations from stack 0 [<00007f60fe8e0051>] bar+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007f60fe8e0065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055d3a2992190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f60fe629d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] [13:31:17] Top 1 stacks with outstanding allocations: 8 bytes in 2 allocations from stack 0 [<00007f60fe8e0051>] bar+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007f60fe8e0065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055d3a2992190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f60fe629d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] ^C[13:31:22] Top 1 stacks with outstanding allocations: 12 bytes in 3 allocations from stack 0 [<00007f60fe8e0051>] bar+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007f60fe8e0065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055d3a2992190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f60fe629d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] done Run test program a.out after strip libtest.so and check the result $ strip libtest.so $ LD_LIBRARY_PATH=. ./a.out & [1] 335467 $ sudo ./memleak -p 335467 using default object: libc.so.6 using page size: 4096 tracing kernel: false Tracing outstanding memory allocs... Hit Ctrl-C to end [13:33:5] Top 1 stacks with outstanding allocations: 4 bytes in 1 allocations from stack 0 [<00007fe1eeba5051>] foo+0x21 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007fe1eeba5065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<00005648ff9d0190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007fe1ee829d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] [13:33:10] Top 1 stacks with outstanding allocations: 8 bytes in 2 allocations from stack 0 [<00007fe1eeba5051>] foo+0x21 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007fe1eeba5065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<00005648ff9d0190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007fe1ee829d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] ^C[13:33:12] Top 1 stacks with outstanding allocations: 8 bytes in 2 allocations from stack 0 [<00007fe1eeba5051>] foo+0x21 [/home/bojun/bcc/libbpf-tools/libtest.so] 1 [<00007fe1eeba5065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<00005648ff9d0190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007fe1ee829d90>] __libc_init_first+0x90 [/usr/lib/x86_64-linux-gnu/libc.so.6] done This is the point, baz never calls foo but the report seems like baz calls foo! After apply this patch and build memleak and check the result $ USE_BLAZESYM=0 make memleak $ LD_LIBRARY_PATH=. ./a.out & [1] 335540 $ sudo ./memleak -p 1234 using default object: libc.so.6 using page size: 4096 tracing kernel: false Tracing outstanding memory allocs... Hit Ctrl-C to end [13:35:20] Top 1 stacks with outstanding allocations: 4 bytes in 1 allocations from stack 0 [<00007f5e93839051>] <null sym> 1 [<00007f5e93839065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055b4e197d190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f5e93429d90>] <null sym> [13:35:25] Top 1 stacks with outstanding allocations: 8 bytes in 2 allocations from stack 0 [<00007f5e93839051>] <null sym> 1 [<00007f5e93839065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055b4e197d190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f5e93429d90>] <null sym> ^C[13:35:28] Top 1 stacks with outstanding allocations: 8 bytes in 2 allocations from stack 0 [<00007f5e93839051>] <null sym> 1 [<00007f5e93839065>] baz+0x12 [/home/bojun/bcc/libbpf-tools/libtest.so] 2 [<000055b4e197d190>] main+0x27 [/home/bojun/bcc/libbpf-tools/a.out] 3 [<00007f5e93429d90>] <null sym> done Unknown symbol is correct result since the symbol bar is stripped
- Loading branch information