參考資訊:
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 y
breakpoint 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