參考資訊:
https://ephrain.net/gdb-%E8%BC%89%E5%85%A5%E6%9F%90%E5%80%8B-library-%E7%9A%84-symbol-file/
一般Release給客戶的檔案都是移掉Debug資訊的檔案,不過,在編譯Release檔案時,通常會額外編譯一份具有Debug Symbol的檔案,如何透過這份Debug檔案除錯,就是這次要介紹的東西
main.c
#include <stdio.h> void test(int, char*); int main(int argc, char** argv) { test(1, "I am error !"); return 0; }
m.c
#include <stdio.h> #include <stdlib.h> void test(int a1, char* a2) { printf("a1:%d, a2:%s\n", a1, a2); }
編譯
$ gcc m.c -no-pie -fPIC -shared -o m.so $ gcc m.c -no-pie -fPIC -shared -ggdb -o m.so.debug $ gcc main.c -o main m.so $ strip m.so $ strip main $ file main m.so m.so.debug main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped m.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped m.so.debug: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, with debug_info, not stripped
設定斷點在test()
$ gdb main Type "apropos word" to search for commands related to "word"... Reading symbols from main...(no debugging symbols found)...done. (gdb) b test Breakpoint 1 at 0x1030 (gdb) r Starting program: /home/steward/Downloads/test/main Breakpoint 1, 0x00007ffff7fca109 in test () from ./m.so
由於沒有Debug Symbol,無法看到多餘資訊
(gdb) bt #0 0x00007ffff7fca109 in test () from ./m.so #1 0x0000555555555155 in ?? () #2 0x00007ffff7de509b in __libc_start_main (main=0x555555555135, argc=1, argv=0x7fffffffe178, init=, fini= , rtld_fini= , stack_end=0x7fffffffe168) at ../csu/libc-start.c:308 #3 0x000055555555507a in ?? () (gdb) list 1 ../sysdeps/x86/dl-procinfo.c: No such file or directory.
載入具有Debug Symbol的檔案
(gdb) add-symbol-file m.so.debug add symbol table from file "m.so.debug" (y or n) y Reading symbols from m.so.debug...done.
不過,竟然還是無法看到相關資訊
(gdb) bt #0 0x00007ffff7fca109 in test () from ./m.so #1 0x0000555555555155 in ?? () #2 0x00007ffff7de509b in __libc_start_main (main=0x555555555135, argc=1, argv=0x7fffffffe178, init=, fini= , rtld_fini= , stack_end=0x7fffffffe168) at ../csu/libc-start.c:308 #3 0x000055555555507a in ?? () (gdb) list 1 in ../sysdeps/x86/dl-procinfo.c
仔細一看,竟然有兩個斷點,代表載入兩份程式
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep ybreakpoint already hit 1 time 1.1 y 0x0000000000001105 in test at m.c:5 1.2 y 0x00007ffff7fca109
接著移除Debug Symbol檔案
(gdb) symbol-file Discard symbol table from `/home/steward/Downloads/test/main'? (y or n) y No symbol file now.
列出m.so的位址
(gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00007ffff7fca050 0x00007ffff7fca131 No ./m.so 0x00007ffff7de3320 0x00007ffff7f2939b No /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff7fd6090 0x00007ffff7ff3b20 No /lib64/ld-linux-x86-64.so.2
重新加載Debug Symbol的檔案到m.so的原本位址
(gdb) add-symbol-file m.so.debug 0x00007ffff7fca050 add symbol table from file "m.so.debug" at .text_addr = 0x7ffff7fca050 (y or n) y Reading symbols from m.so.debug...done.
重新設定斷點test()
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x00007ffff7fca114 in test at m.c:6 breakpoint already hit 1 time (gdb) del 1 (gdb) b test Breakpoint 2 at 0x7ffff7fca114: file m.c, line 6. (gdb) info b Num Type Disp Enb Address What 2 breakpoint keep y 0x00007ffff7fca114 in test at m.c:6
重新執行main就可以看到除錯資訊
(gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/steward/Downloads/test/main Breakpoint 2, test (a1=1, a2=0x555555556004 "I am error !") at m.c:6 6 printf("a1:%d, a2:%s\n", a1, a2); (gdb) list 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void test(int a1, char* a2) 5 { 6 printf("a1:%d, a2:%s\n", a1, a2); 7 } (gdb) p a1 $1 = 1 (gdb) p a2 $2 = 0x555555556004 "I am error !" (gdb) info f Stack level 0, frame at 0x7fffffffe080: rip = 0x7ffff7fca114 in test (m.c:6); saved rip = 0x555555555155 called by frame at 0x7fffffffe088 source language c. Arglist at 0x7fffffffe070, args: a1=1, a2=0x555555556004 "I am error !" Locals at 0x7fffffffe070, Previous frame's sp is 0x7fffffffe080 Saved registers: rbp at 0x7fffffffe070, rip at 0x7fffffffe078