Linux下gdb的安裝及使用入門

1、安裝gdb。

在root用戶權限下:

root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get update
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~# apt-get install gdb 
......
......
......
Do you want to continue? [Y/n] y
......
......
......
root@iZ2zeeailqvwws5dcuivdbZ:~# 

安裝好gdb了。

2、gdb的簡單使用。

用root權限的Terminal(或一般權限的Terminal)的vi編輯器編寫一個C程序a.c:

 1 #include <stdio.h>
 2 
 3 int main()
 4 {
 5   int a = 1;
 6   int b = a;
 7 
 8   printf("a = %d, b =%d\n", a, b);
 9 
10   return 0;
11 }

(1) 在可執行文件中加入源碼信息

這個過程通過gcc來完成:

gcc –o a a.c -g

-o選項的作用是:對命令輸出結果進行導入操作,這裏是把gcc –o a a.c -g的操作結果輸出到文件a(文件名可以自定義)中進行保存。

-g選項的作用是:在可執行文件中加入源碼信息,比如:可執行文件中第幾條機器指令對應源代碼的第幾行,但並不是把整個源文件都嵌入到可執行文件中,而是在調試時必須保證gdb能找到源文件。

(2) 進入gdb

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gcc -o a a.c -g
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a...done.
(gdb) 

如下圖所示:

gdb提供一個類似Shell的命令行環境,上面的(gdb)就是提示符,在提示符後面輸入gdb的相應命令就可以實現其對應的功能。

(3) gdb調試常用命令

  [1] start

  用start命令開始執行程序:

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) 

  gdb提示準備執行a.c程序的第六行代碼。然後繼續用(gdb)提示需要輸入的命令。

  [2] 單步執行(n)

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) n
6           int b = a;
(gdb) n
8           printf("a = %d, b = %d\n", a, b);
(gdb) n
a = 1, b = 1
9           return 0;
(gdb) quit
A debugging session is active.

        Inferior 1 [process 22935] will be killed.

Quit anyway? (y or n) y
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# 

  在start命令後,每輸入一個n就能夠單步執行一條語句(輸入一個命令後,直接回車表示最近輸入命令的含義)。當程序執行完時,可以輸入quit命令來退出gdb模式。

  [3] gdb斷點調試

[ breakpoint,continue和display ]

(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) b 8
Breakpoint 2 at 0x40053b: file a.c, line 8.
(gdb) c
Continuing.

Breakpoint 2, main () at a.c:8
8           printf("a = %d, b = %d\n", a, b);
(gdb) display b
1: b = 1
(gdb) n
a = 1, b = 1
9           return 0;
1: b = 1
(gdb) 
10      }
1: b = 1
(gdb) quit
root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# 

  gdb  a會進入a可執行程序的gdb模式,start命令就使程序準備運行程序中的第一條語句。b 8是breakpoint  8的簡寫(breakpoint的參數也可以以是某個函數名,表示在此函數處設置一個斷點),表示在程序第八行設置一個斷點。c是continue的縮寫,表示繼續運行程序,程序會在設置斷點處停下來。displayb表示將b的值顯示出來(undisplay取消對變量的跟蹤),然後再輸入單步調試命令n(next)就可以使程序繼續運行。

  可見斷點有助於快速跳過沒有問題的代碼,然後在有問題的代碼上慢慢走慢慢分析,“斷點加單步”是使用調試器的基本方法。至於應該在哪裏設置斷點,怎麼知道哪些代碼可以跳過,而哪些代碼要慢慢走,也要通過對錯誤現象的分析和假設來確定,以前我們用printf打印中間結果時,也要分析應該在哪裏插入printf,打印哪些中間結果,調試的基本思路是一樣的。

  [4]info

  一次調試可以設置多個斷點,用info命令可以查看已經設置的斷點:

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) b 7
Breakpoint 2 at 0x40053b: file a.c, line 7.
(gdb) b 8
Note: breakpoint 2 also set at pc 0x40053b.
Breakpoint 3 at 0x40053b: file a.c, line 8.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
3       breakpoint     keep y   0x000000000040053b in main at a.c:8
(gdb) 

[5]delete

  每個斷點都有一個編號(有的斷點行數不一樣,但地址卻一樣,有的地方不能夠設置斷點或者說與上一個設置的斷點等效),可以用編號指定刪除某個斷點。

......
(gdb) b 7
Breakpoint 2 at 0x40053b: file a.c, line 7.
(gdb) b 8
Note: breakpoint 2 also set at pc 0x40053b.
Breakpoint 3 at 0x40053b: file a.c, line 8.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
3       breakpoint     keep y   0x000000000040053b in main at a.c:8
(gdb) delete 3
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x000000000040053b in main at a.c:7
(gdb) 

  有時候一個斷點暫時不用可以禁用掉而不必刪除,這樣以後想用的時候可以直接啓用,而不必重新從代碼裏找應該在哪一行設斷點,這個過程用 disable 和 enable 來完成。

  [6]條件斷點 (break 和run)

  gdb的斷點功能非常靈活,還可以設置斷點在滿足某個條件時才激活,例如:

......
//先把其餘的斷點刪掉。
(gdb) b 9 if a == 2
Breakpoint 5 at 0x400552: file a.c, line 9.
(gdb) i breakpoints 
Num     Type           Disp Enb Address            What
5       breakpoint     keep y   0x0000000000400552 in main at a.c:9
        stop only if a == 2
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/2/02/a 
a = 1, b = 1
[Inferior 1 (process 22968) exited normally]
(gdb) 

  r表示從頭開始運行程序,在a==2的條件下中斷纔有效。a不等於2,所以中斷無效。  

  [7] gdb的觀察點(watch 和c)

斷點是當程序執行到某一代碼行時中斷,而觀察點是當程序訪問某個存儲單元時中斷,如果我們不知道某個存儲單元是在哪裏被改動的,這時候觀察點尤其有用。

root@iZ2zeeailqvwws5dcuivdbZ:~/2/02# gdb a
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a...done.
(gdb) start
Temporary breakpoint 1 at 0x40052e: file a.c, line 5.
Starting program: /root/2/02/a 

Temporary breakpoint 1, main () at a.c:5
5           int a = 1;
(gdb) watch b
Hardware watchpoint 2: b
(gdb) c
Continuing.

Hardware watchpoint 2: b

Old value = 0
New value = 1
main () at a.c:8
8           printf("a = %d, b = %d\n", a, b);
(gdb) 

  程序執行到b存儲單元,將此執行單元執行前後的值都顯示出來。

  [8] 段錯誤

  如果程序運行時出現段錯誤,用gdb可以很容易定位到究竟是哪一行引發的段錯誤。在gdb中運行,遇到段錯誤會自動停下來,這時可以用命令查看當前執行到哪一行代碼了。

  gdb顯示段錯誤出現在 _IO_vfscanf 函數中,用bt命令可以看到是哪一個函數調用了它。

  [9] gdb基本命令

  gdb有許多有用的命令如list(顯示源代碼),這樣就可以結合源碼與調試信息更好的進行調試。將gdb常用命令摘抄如下表:

命令

描述

backtrace(bt)

查看各級函數調用及參數

finish

連續運行到當前函數返回爲止,然後停下來等待命令

frame(f)  幀編號

選擇棧幀

info(i)  locals

查看當前棧幀局部變量的值

list(l)

列出源代碼,接着上次的位置往下列,每次列十行

list  行號

列出第幾行開始的源代碼

list  函數名

列出某個函數的源代碼

next(n)

執行下一行語句

print(p)

打印表達式的值,通過表達式的值可以修改變量的值或者調用函數

quit(q)

退出gdb調試環境

set  var

修改變量的值

start

開始執行程序,停在main函數第一行語句前面等待命令

step(s)

執行下一行語句,如果有函數則進入到函數中

break(b)  行號

在某一行設置斷點

break  函數名

在某個函數開頭設置斷點

break(b)… if…

設置條件斷點

continue(c)

從當前位置開始連續運行程序

delete breakpoints 斷點號

刪掉此號的斷點

display  變量名

跟蹤查看某個變量,每次停下來都顯示它的值

disable  breakpoints 斷點號

禁用此斷點

enable  斷點號

啓用此斷點

info(i)  breakpoints

查看當前設置了哪些斷點

run(r)

從頭開始連續運行程序

undisplay  跟蹤顯示行號

取消跟蹤顯示

watch

設置觀察點

info(i)   watchpoints

查看當前設置了哪些觀察點

x

從某個位置開始打印存儲單元的內容,全部當成字節來看,而不區分哪個字節屬於哪個變量

disassemble

反彙編當前函數或者指定的函數,單獨用disassemble命令是反彙編當前函數,如果disassemble命令後面跟函數名或地址則反彙編指定的函數。

si

可以一條指令一條指令地單步調試。

info  registers

可以顯示所有寄存器的當前值。在gdb中表示寄存器名時前面要加個$,例如p $esp可以打印esp寄存器的值。

set follow-fork-mode child/parent

設置gdb在fork之後跟蹤子進程/父進程

set  args  'command-line'

給執行的程序傳命令行參數

s(stepin)

進入子函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章