歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

強大的C/C++ 程序調試工具GDB

分享下強大的C/C++ 程序調試工具GDB

1.基本調試

這裡只列舉最最常用的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 getbuf
Breakpoint 1 at 0x8048ad6
(gdb) run -t cdai
Starting program: /root/Temp/bufbomb/bufbomb -t cdai
Team: cdai
Cookie: 0x5e5ee04e

Breakpoint 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 0
Stack 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 registers
eax            0xc      12
ecx            0xffffb548       -19128
edx            0xc8c340 13157184
ebx            0x0      0
esp            0xffffb510       0xffffb510
ebp            0xffffb538       0xffffb538
esi            0x804b018        134524952
edi            0xffffffff       -1
eip            0x8048ad6        0x8048ad6 <getbuf+6>
eflags         0x282    [ SF IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x63     99
(gdb) x/10x $sp
0xffffb510:     0xf7ffc6b0      0x00000001      0x00000001      0xffffb564
0xffffb520:     0x08048448      0x0804a12c      0xffffb548      0x00c8aff4
0xffffb530:     0x0804b018      0xffffffff

(gdb) si
0x08048ad9 in getbuf ()
(gdb) si
0x08048adc in getbuf ()
(gdb) si
0x080489c0 in Gets ()
(gdb) n
Single stepping until exit from function Gets,
which has no line number information.
Type string:123
0x08048ae1 in getbuf ()
(gdb) si
0x08048ae2 in getbuf ()
(gdb) c
Continuing.
Dud: getbuf returned 0x1
Better luck next time

Program 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 getbuf
Breakpoint 1 at 0x8048ad6
(gdb) b main
Breakpoint 2 at 0x80490c6

(gdb) run -t cdai
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /root/Temp/bufbomb/bufbomb -t cdai

Breakpoint 2, 0x080490c6 in main ()
(gdb) record
(gdb) c
Continuing.
Team: cdai
Cookie: 0x5e5ee04e

Breakpoint 1, 0x08048ad6 in getbuf ()

(gdb) rn
Single stepping until exit from function getbuf,
which has no line number information.
0x08048dad in test ()
(gdb) rn
Single stepping until exit from function test,
which has no line number information.
0x08049080 in launch ()
(gdb) rn
Single stepping until exit from function launch,
which has no line number information.
0x08049252 in main ()

GDB調試程序用法 http://www.linuxidc.com/Linux/2013-06/86044.htm

GDB+GDBserver無源碼調試Android 動態鏈接庫的技巧 http://www.linuxidc.com/Linux/2013-06/85936.htm

使用hello-gl2建立ndk-GDB環境(有源碼和無源碼調試環境) http://www.linuxidc.com/Linux/2013-06/85935.htm

在Ubuntu上用GDB調試printf源碼 http://www.linuxidc.com/Linux/2013-03/80346.htm

Linux下用GDB調試可加載模塊 http://www.linuxidc.com/Linux/2013-01/77969.htm

Ubuntu下使用GDB斷點Go程序 http://www.linuxidc.com/Linux/2012-06/62941.htm

使用GDB命令行調試器調試C/C++程序 http://www.linuxidc.com/Linux/2014-11/109845.htm

GDB調試命令總結  http://www.linuxidc.com/Linux/2016-08/133988.htm

GDB調試工具入門  http://www.linuxidc.com/Linux/2016-09/135168.htm

GDB 的詳細介紹:請點這裡
GDB 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved