標籤:gdb c 調試
C實戰:強大的程式調試工具GDB1.基本調試
這裡只列舉最最常用的GDB命令。
1.1 啟動GDB
gdb program:準備偵錯工具。也可以直接進入gdb,再通過file命令載入。
1.2 添加斷點
b function:為函數設定斷點。b是break的縮寫,除了函數名,還可以是地址、當前執行處的+/-位移等。
1.3 運行程式
run args:開始運行程式,run後面可以加程式需要的參數,就像在命令列正常運行時那樣。
1.4 單步調試
s/n/si/c/kill:s即step in,進入下一行代碼執行;n即step next,執行下一行代碼但不進入;si即step instruction,執行下一條彙編/CPU指令;c即continue,繼續執行直到下一個斷點處;kill終止調試;quit退出GDB。
1.5 列印調試資訊
bt:bt是backtrace的縮寫,列印當前所在函數的堆棧路徑。
info frame id:列印選中的棧幀的資訊。
info args:列印選中棧幀的參數。
print variable:列印指定變數的值。
list:列出相應的原始碼。
info registers:查看所有寄存器的值。
還有個更靈活強大的是直接列印%esp開始的前N個元素,例如列印棧上前10個元素就是:x/10x $sp。
2.GDB實戰
下面是一個使用了上述命令的實戰例子:
[[email protected] bufbomb]# gdb bufbomb GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /root/Temp/bufbomb/bufbomb...done.(gdb) b getbufBreakpoint 1 at 0x8048ad6(gdb) run -t cdaiStarting program: /root/Temp/bufbomb/bufbomb -t cdaiTeam: cdaiCookie: 0x5e5ee04eBreakpoint 1, 0x08048ad6 in getbuf ()Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6_6.4.i686(gdb) bt#0 0x08048ad6 in getbuf ()#1 0x08048db2 in test ()#2 0x08049085 in launch ()#3 0x08049257 in main ()(gdb) info frame 0Stack frame at 0xffffb540: eip = 0x8048ad6 in getbuf; saved eip 0x8048db2 called by frame at 0xffffb560 Arglist at 0xffffb538, args: Locals at 0xffffb538, Previous frame‘s sp is 0xffffb540 Saved registers: ebp at 0xffffb538, eip at 0xffffb53c(gdb) info registerseax 0xc 12ecx 0xffffb548 -19128edx 0xc8c340 13157184ebx 0x0 0esp 0xffffb510 0xffffb510ebp 0xffffb538 0xffffb538esi 0x804b018 134524952edi 0xffffffff -1eip 0x8048ad6 0x8048ad6 <getbuf+6>eflags 0x282 [ SF IF ]cs 0x23 35ss 0x2b 43ds 0x2b 43es 0x2b 43fs 0x0 0gs 0x63 99(gdb) x/10x $sp0xffffb510: 0xf7ffc6b0 0x00000001 0x00000001 0xffffb5640xffffb520: 0x08048448 0x0804a12c 0xffffb548 0x00c8aff40xffffb530: 0x0804b018 0xffffffff(gdb) si0x08048ad9 in getbuf ()(gdb) si0x08048adc in getbuf ()(gdb) si0x080489c0 in Gets ()(gdb) nSingle stepping until exit from function Gets,which has no line number information.Type string:1230x08048ae1 in getbuf ()(gdb) si0x08048ae2 in getbuf ()(gdb) cContinuing.Dud: getbuf returned 0x1Better luck next timeProgram exited normally.(gdb) quit
3.逆向調試
GDB 7.0後加入了Reversal Debugging功能。具體來說,比如我在getbuf()和main()上設定了斷點,當啟動程式時會停在main()函數的斷點上。此時敲入record後continue到下一斷點getbuf(),GDB就會記錄從main()到getbuf()的運行時資訊。現在用rn就可以逆向地從getbuf()調試到main()。就像《X戰警:逆轉未來》裡一樣,挺神奇吧!
這種方式適合從bug處反向去找引起bug的代碼,實用性因情況而異。當然,它也是有局限性的。像程式假如有I/O輸出等外部條件改變時,GDB是沒法“逆轉”的。
[[email protected] bufbomb]# gdb bufbomb GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)Copyright (C) 2010 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>...Reading symbols from /root/Temp/bufbomb/bufbomb...done.(gdb) b getbufBreakpoint 1 at 0x8048ad6(gdb) b mainBreakpoint 2 at 0x80490c6(gdb) run -t cdaiThe program being debugged has been started already.Start it from the beginning? (y or n) yStarting program: /root/Temp/bufbomb/bufbomb -t cdaiBreakpoint 2, 0x080490c6 in main ()(gdb) record(gdb) cContinuing.Team: cdaiCookie: 0x5e5ee04eBreakpoint 1, 0x08048ad6 in getbuf ()(gdb) rnSingle stepping until exit from function getbuf,which has no line number information.0x08048dad in test ()(gdb) rnSingle stepping until exit from function test,which has no line number information.0x08049080 in launch ()(gdb) rnSingle stepping until exit from function launch,which has no line number information.0x08049252 in main ()
C實戰:強大的程式調試工具GDB