1 测试程序源代码
// file a.c
#include <stdio.h>
#include <unistd.h>
int f()
{
printf("f() @ %p\n", f);
}
extern int f2();
int main()
{
while(1)
{
f();
f2();
sleep(1);
}
return 0;
}
// file b.c
#include <stdio.h>
int f2()
{
printf("f2() @ %p\n", f2);
}
2 编译生成测试文件
编译动态库libb.so
gcc -g -shared -fPIC b.c -o libb.so
objcopy --only-keep-debug libb.so libb.so.debug
strip libb.so
编译可执行文件a.out
gcc -g a.c -o a.out -L. -lb # 生成带调试信息的可执行文件
objcopy --only-keep-debug a.out a.out.debug # 将符号表从程序中剥离出来
strip a.out # 去除可执行文件中的符号表
3 GDB手动加载符号表调试
3.1 运行测试文件
user@host:~/mpt/c/hello$ LD_LIBRARY_PATH+=. ./a.out
f() @ 0x56268ccbd79a
f2() @ 0x7fde6134d62a
f() @ 0x56268ccbd79a
f2() @ 0x7fde6134d62a
f() @ 0x56268ccbd79a
f2() @ 0x7fde6134d62a
f() @ 0x56268ccbd79a
f2() @ 0x7fde6134d62a
...
3.2 使用GDB调试
1 - 启动GDB
user@host:~/mpt/c/hello$ sudo gdb
(gdb)
2 - 获取要调试程序的进程号
(gdb) shell ps -u user | grep a.out
18997 pts/42 00:00:00 a.out
3 - attach
(gdb) attach 18997
Attaching to process 18997
Reading symbols from /home/user/mpt/c/hello/a.out...(no debugging symbols found)...done.
Reading symbols from ./libb.so...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.27.so...done.
done.
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/ld-2.27.so...done.
done.
0x00007fde61040654 in __GI___nanosleep (requested_time=requested_time@entry=0x7fff323b0800, remaining=remaining@entry=0x7fff323b0800)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
3 - 查看进程文件地址绑定信息
(gdb) info files
Symbols from "/home/user/mpt/c/hello/a.out".
Native process:
Using the running image of attached process 18997.
While running this, GDB does not access memory from...
Local exec file:
`/home/user/mpt/c/hello/a.out', file type elf64-x86-64.
Entry point: 0x56268ccbd690
0x000056268ccbd238 - 0x000056268ccbd254 is .interp
0x000056268ccbd254 - 0x000056268ccbd274 is .note.ABI-tag
0x000056268ccbd274 - 0x000056268ccbd298 is .note.gnu.build-id
0x000056268ccbd298 - 0x000056268ccbd2d0 is .gnu.hash
0x000056268ccbd2d0 - 0x000056268ccbd420 is .dynsym
0x000056268ccbd420 - 0x000056268ccbd4d9 is .dynstr
0x000056268ccbd4da - 0x000056268ccbd4f6 is .gnu.version
0x000056268ccbd4f8 - 0x000056268ccbd518 is .gnu.version_r
0x000056268ccbd518 - 0x000056268ccbd5d8 is .rela.dyn
0x000056268ccbd5d8 - 0x000056268ccbd620 is .rela.plt
0x000056268ccbd620 - 0x000056268ccbd637 is .init
0x000056268ccbd640 - 0x000056268ccbd680 is .plt
0x000056268ccbd680 - 0x000056268ccbd688 is .plt.got
0x000056268ccbd690 - 0x000056268ccbd852 is .text
0x000056268ccbd854 - 0x000056268ccbd85d is .fini
0x000056268ccbd860 - 0x000056268ccbd86e is .rodata
0x000056268ccbd870 - 0x000056268ccbd8b4 is .eh_frame_hdr
0x000056268ccbd8b8 - 0x000056268ccbd9e0 is .eh_frame
0x000056268cebdd98 - 0x000056268cebdda0 is .init_array
0x000056268cebdda0 - 0x000056268cebdda8 is .fini_array
0x000056268cebdda8 - 0x000056268cebdfa8 is .dynamic
0x000056268cebdfa8 - 0x000056268cebe000 is .got
0x000056268cebe000 - 0x000056268cebe010 is .data
0x000056268cebe010 - 0x000056268cebe018 is .bss
0x00007fde6134d1c8 - 0x00007fde6134d1ec is .note.gnu.build-id in ./libb.so
0x00007fde6134d1f0 - 0x00007fde6134d22c is .gnu.hash in ./libb.so
0x00007fde6134d230 - 0x00007fde6134d350 is .dynsym in ./libb.so
0x00007fde6134d350 - 0x00007fde6134d3e9 is .dynstr in ./libb.so
0x00007fde6134d3ea - 0x00007fde6134d402 is .gnu.version in ./libb.so
0x00007fde6134d408 - 0x00007fde6134d428 is .gnu.version_r in ./libb.so
0x00007fde6134d428 - 0x00007fde6134d4e8 is .rela.dyn in ./libb.so
0x00007fde6134d4e8 - 0x00007fde6134d500 is .rela.plt in ./libb.so
0x00007fde6134d500 - 0x00007fde6134d517 is .init in ./libb.so
0x00007fde6134d520 - 0x00007fde6134d540 is .plt in ./libb.so
0x00007fde6134d540 - 0x00007fde6134d548 is .plt.got in ./libb.so
0x00007fde6134d550 - 0x00007fde6134d64c is .text in ./libb.so
0x00007fde6134d64c - 0x00007fde6134d655 is .fini in ./libb.so
0x00007fde6134d655 - 0x00007fde6134d660 is .rodata in ./libb.so
0x00007fde6134d660 - 0x00007fde6134d684 is .eh_frame_hdr in ./libb.so
---Type <return> to continue, or q <return> to quit---q
Quit
4 - 加载符号表调试
从上一步中获取a.out
文件的.text
段在内存中的实际地址0x000056268ccbd690
(gdb) add-symbol-file a.out.debug 0x000056268ccbd690
add symbol table from file "a.out.debug" at
.text_addr = 0x56268ccbd690
(y or n) y
Reading symbols from a.out.debug...done.
从上一步中获取libb.so
文件的.text
段在内存中的实际地址0x00007fde6134d550
(gdb) add-symbol-file libb.so.debug 0x00007fde6134d550
add symbol table from file "libb.so.debug" at
.text_addr = 0x7fde6134d550
(y or n) y
Reading symbols from libb.so.debug...done.
5 - 可以正常使用GDB断点调试,符号表被正确加载,符号能正确解析
(gdb) b f
Breakpoint 1 at 0x56268ccbd79e: file a.c, line 6.
(gdb) b f2
Breakpoint 2 at 0x7fde6134d62e: file b.c, line 5.
(gdb) c
Continuing.
Breakpoint 1, f () at a.c:6
6 printf("f() @ %p\n", f);
(gdb) c
Continuing.
Breakpoint 2, f2 () at b.c:5
5 printf("f2() @ %p\n", f2);
(gdb) c
Continuing.
Breakpoint 1, f () at a.c:6
6 printf("f() @ %p\n", f);
(gdb) c
Continuing.
Breakpoint 2, f2 () at b.c:5
5 printf("f2() @ %p\n", f2);
(gdb) c
Continuing.
Breakpoint 1, f () at a.c:6
6 printf("f() @ %p\n", f);