GDB使用 常用指令

轉載:http://blog.csdn.net/horkychen 

GDB使用介紹

Linux下最強大的Debug工具就是GDB了,許多IDE都集成了GDB進行調試。使用源代碼級調試能夠更直接的進行調試,效率明顯高於輸出Log信息。但目前無論是Mac下的XCode,還是Linux下的其它集成工具,對於調試庫函數都是相當困難的,如果直接使用GDB這些問題就迎刃而解。我們首先來探討一下GDB的基礎知識。

 

GDB調試流程

 

GDB調試依賴於編譯器輸出的調試信息,所以進行調試前必須確定GCC輸出了調試信息。

1.生成符號文件

使用GCC編譯時需要生成相應的調試信息,編譯時可以使用-g選項:

<<詳細內容參GCC Manual>> Section 3.9

-g  表示將Symbol Table以系統原生格式直接生成到可執行文件中

 -g選項最好不要同-O一起使用,因爲代碼經過優化後有時會同源代碼差異很大,可能找不到指定的變量等等。

-ggdb  表示將專門爲GDB調試使用生成調試信息,它會包括很多GDB的擴展信息

其它的Symbol Table的格式還有COFF,DWARF,Stabs. (Mac OS默認爲DWARF. DWARF也是基於COFF實現[Common Object File Format])

 

輸出的調試信息的多少由三個等級:

-g[level]  默認爲2

  0  表示不生成任何調試信息

  1  表示生成最少的調試信息,不提供局部變量及源代碼行列等信息。

  2  標準模式

  3  2而言,包含了宏定義等額外信息

 

其它同調試相關的編譯選項還有:

-p 生成額外的代碼用於輸出profile信息,用於另一個工具程序使用:prof

--coverage 用於統於代碼的覆蓋率

--ftest-coverage 類似上面的--coverage

-d*  用於Dump一些有用的信息,詳細內容參GDB Manual.

 

 

2.啓動GDB進行調試

下面的過程,我都以下面的工程進行解釋:

 目標程序: text2bin

 源代碼:text2bin.c

 功能將文本文件轉成二進制文件

  使用方法: ./text2bin txt_file_name  [offset]

                    txt_file_name爲源文本文件名

                    offset指定忽略左側多少字節

 

A.調試應用程序

(1)啓動  

  直接在命令行下輸入gdb ./text2bin 或者運行gdb後輸入file ./text2bin都可以加載指定的應用程序.

GDB會顯示加載Symbols的過程,注意如果沒有出現加載text2bin的調試信息的過程,就是表明無法獲取調試信息!

Reading symbols for shared libraries ... done

Reading symbols from /Horky/Project/WINBASE/WINBASE/TextToRaw/text2bin...

warning: UUID mismatch detected between:

    /Horky/Project/WINBASE/WINBASE/TextToRaw/text2bin

 

(2)設置斷點

  *除了斷點外還有Watchpoints(觀測點)Catchpoints (異常捕捉點)

  輸入bbreak加上斷點位置或斷點函數名,

  b main  #main函數入口設置斷點

  b text2bin.c:50  在源代碼第50行設置斷點

 

 如果需要查看斷點信息可以使用指令:

 info breakpoints

 

 清除所有斷點使用指令:

 clear

 清除特定的斷點使用指令:

 clear text2bin.c:50

  clear main

 

 在調試過程可以使用disableenable開關某個特定的斷點.enable 2 disable 2開關第2個斷點。

在使用info b查看斷點時,注意其中Enb欄位的變化。

 

對於觀測點(Watchpoints),是指在某個條件下觸發的斷點,text2bin77:

Buffer2[nCount++] = ConvertTextToInt(sData);

 

我們要查看當nCount10時的運行狀況,我們可以通過下面的步驟完成:

 a. 執行b 77,返回這個斷點號是3

 b. 執行condition 3 nCount=10

 過程如下:

(gdb) b 77

Breakpoint 3 at 0x1c73: file text2bin.c, line 77.

(gdb) condition 3 nCount=10

(gdb) info breakpoints

Num Type           Disp Enb Address    What

1   breakpoint     keep y   0x00001e1e in ConvertTextToInt at text2bin.c:124

    breakpoint already hit 1 time

2   breakpoint     keep y   0x00001e25 in ConvertTextToInt at text2bin.c:125

3   breakpoint     keep y   0x00001c73 in main at text2bin.c:77

    stop only if nCount = 10

 

這樣就可以控制當nCount10時在77行處中斷.

 

如果在調試時,需在下面若干行代碼後追加一個斷點,在指定位置可以使用偏移量來指定斷點,

b +5 b -5,即表示在當前行的後五行及前五行位置設置斷點

 

 

(3)控制調試過程

在開始時需要告訴GDB目標程序是哪一個,可以用gdb ./text2bin,也可以在啓動gdb後使用指令:

file ./text2bin來指定。

運行則使用r/run指令,可以同時帶上參數,

r ./expert.txt 7

 

在調試過程中需要有一系列操作控制調試的過程:

 c / continue  /fg

 *fgforeground的縮寫

從斷點狀態恢復程序的執行.

 

 s / step [count]

 單步執行 (step in)

 

 n / next [count]

 單步執行,跳過函數 (step out)

 

 u / until [location]

 執行到某個位置。 當遇到循環時可以使用此指令方便地跳轉到指定的位置。

 

 finish

 執行到當前函數結束位置爲止,同時顯示函數返回值

 

 backtrace

 查看當前位置的被調用路徑

 

(4)監測變量及內存

簡單地顯示變量的值可以使用print指令直接輸出.

p / print [expression]

如輸出main函數中的文件名變量 p argv[1]

    輸出ConvertTextToInt函數中n的值 p np ConvertTextToInt::n

 

查看內存內容時則使用x指令:

x /nfu addr  以指定格式顯示內存內容

x addr  顯示指定地址處理內存內容

顯示當前數據段內容

 

如以字串形顯示某內存內容的指令爲:

   x /sb 0xbffff80e

以數據形式顯示某內存中5個字節的內容的指令爲:

  x /5db 0xbffff80e

 

設定local variable watch,用來在每條執行後顯示某些變量的值,可以使用display指令來指定,:

display S

display /sb 0xbffff707

 

去除時使用undisplay #  (#display列表中的序號)

 

display後面所帶的參數同x指令:

表示repeat count

表示格式,分爲:

  x  十六制數據

  d  帶符號之整型數據

  u  無符號整型數據

  o  八進制整型數據

  t  二進制數據

  a 以地址格式顯示,包括十六進制及偏移量

  c 以字符形式輸出

  f  小數位輸出

  s  以字串形式輸出

 

u表示大小單位:

  b                 Bytes

  h                 Halfwords

  w                 Words

  g                  Giant words (eight bytes) 

 

(5)查看源代碼

使用l / list指令就可查看源代碼了,

:

 l 150 查看當前代碼的第150

l text2bin.c:150  查看text2bin.c150.

l main  查看main函數內容

查看時如果需要翻頁,直接回車.

 

默認GDB一次顯示10,我們也可以通過set linesize [count]進行調整。

 

B.如何調試動態庫或靜態庫

當調試庫函數時,需要透過主程序調用的形式來掛載,所以不能直接使用GDB對目標庫進行調試,而是需要attach指定的父進程,然後再進行測試.這裏有兩種情況:

(1)主程序啓動時自動加載庫,此時使用GDB掛載時也會自動加載相應的調試信息.

(2)主程序動態加載庫,對於這種情況則需要另外使用symbol filename來加載特定的調試信息。

 

*提醒:當進行多線程調試時,一定要確保能找出真正的主線程。

*斷開主線程時,使用detach指令來完成

 

    

C.如何調試多線程的程序

我們在寫程序時常常會有多線程的運用比如有些程序中讀取數據及數據處理,就是通過兩個線程來完成的。對

多線程進行調試最大的難點在於線程的同步問題.

GDB提供了一套指令針對多線程:

info threads

  查看當前有多少線程

thread # 

  切換到指定線程

set print thread-events on/off

  設定是否打印線程狀態

當設置中斷時,也可以專爲某個線程設置,

 b/break [location]  thread #

即表示爲#線程在location處設置斷點,這樣就可以進行線程別的調試。

 

 

3. 技巧

(1)GDB中如果需要調用外部程序可以使用shell [command]來完成

(2)當源代碼目錄被移動了,或者在另一臺PC上調試,GDB不能通過Debug信息找到源代碼時,可以使用directory/dir來指搜索的目錄

 

4.GDB的前臺程序(GDB frontend)

  使用命令行是顯得不方便了,所以我們可以選擇一些GDB前端程序:

  DDD   [GNU] (http://www.gnu.org/software/ddd  目前功能最爲強大的GDB前端程序)  

  Nemiver  [GNOME]  (http://home.gna.org/nemiver/)

  Kdbg   [KDE] (www.kdbg.org)

  Insight  [Wirte in Tcl/Tk] (http://sourceware.org/insight)

  Emacs (不用介紹了!)

  一般的IDE也帶有GDB frontend程序,XCode,KDevelop,Anjuta,Eclipse.

 

 *GDB Frontend都是通過僞終端(pseudo-terminal)的方式來實現,有興趣可以瞭解一下.

 

 

 擴展GDB的功能

已經有人在通GDB進行代碼覆蓋率測試,事實上我們也可以通過類似GDB的方式讀取Debug信息中的符號表來進行語法檢查。有關Debug信息的存放,可以使用objdump -xreadelf -a來查看其中的不同,這有助更好的理解程序的結構.

 

需求是多樣的,GDB本身提供了兩種方式來擴展GDB,一種爲組合GDB的指令,類似宏的方式,另一種方式則是功能強大的python腳本。

(1)GDB環境下使用define指令來定義一個指令,

 define localv

  info scope $arg0

 end

這樣我們在使用時,想查看main函數中的所有的變量,就可以通過下面的指令完成:

(gdb) localv main

Scope for main:

Symbol argc is at the address (reg 5 + 8), length 4.

Symbol argv is at the address (reg 5 + 12), length 4.

Symbol fpSrc is at the address (reg 5 + -44), length 4.

......

 

如果這樣的指令非常好用,每次調試時都定義一次不太現實。所以GDB允許將這些操作定義在一個文本文件中,然後在GDB中使用source [command_file]來執行,source /TestData/localv.cmd 

在執行過程中GDB不會顯示每個指令的執行結果,如果需要顯示就在source-v來打開。

 

除了組織指令集外,還有另一種有用的自定義指令: Hooks. GDB允許用戶指定在特定的GDB指令執行前後執行一段自定義指令。比如,如果希望在設置斷點前後都顯示當前斷點狀況,就可以定義兩個如下指令:

(gdb) define hook-break

Type commands for definition of "hook-break".

End with a line saying just "end".

>info b

>end

(gdb) define hookpost-break

Type commands for definition of "hookpost-break".

End with a line saying just "end".

>info b

>end

 

然後執行break / b指令時就可以看到類似下面的輸出:

(gdb) b GetFileSize

Num Type           Disp Enb Address    What

1   breakpoint     keep y   0x00001a68 in main at text2bin.c:25

2   breakpoint     keep y   0x00001e1e in ConvertTextToInt at text2bin.c:124

Breakpoint 3 at 0x1d86: file text2bin.c, line 108.

Num Type           Disp Enb Address    What

1   breakpoint     keep y   0x00001a68 in main at text2bin.c:25

2   breakpoint     keep y   0x00001e1e in ConvertTextToInt at text2bin.c:124

3   breakpoint     keep y   0x00001d86 in GetFileSize at text2bin.c:108

 

hookhookpost即表示在某個指令的前後。後面的指令一定要使用GDB指令的全寫,如上面就不能寫成define hook-bdefine hookpost-b

 

*如果需要更爲詳細的資料,請參考GDB Manual,20. Extending GDB

 

(2)GDB環境可以直接調用python,如在GDB環境下執行python print 23

使用Python編寫腳本同上面定義指令集是類似的,可以執行指令python, GDB就會要求輸入python腳本,並以end爲結束標誌。

GDB爲編寫Python提供了一個新的模塊gdb,在腳本中可以進行引用,其中包括了幾個主要的指令:

  execute command    commandGDB CLI(Command Line Interface)指令字串.

  get_parameter parameter  獲取一項GDB的參數,諸如上面提到的linesize.

  write string  輸出一個字串到GDB輸出窗口

  flush    Flush當前GDB輸出流

 

*只有當編譯GDB時指定了—with-python,GDB纔會支持python指令.

 

參考文檔:

(1) 使用GDB進行代碼覆蓋率測試

       http://www.ibm.com/developerworks/cn/linux/l-cn-gdb/

(2)  使用 GDB 調試 Linux軟件

       http://www.ibm.com/developerworks/cn/linux/sdk/gdb/

 (3)  掌握 Linux 調試技術

       http://www.ibm.com/developerworks/cn/linux/sdk/l-debug/

(4)  GDB調試程序

       http://docs.chinalinuxpub.com/doc/pro/gdb.html

 (5) GDB調試精粹及使用實例

       http://fanqiang.chinaunix.net/program/other/2006-07-14/4834.shtml

 (6) GDB的官方文檔

       http://www.gnu.org/software/gdb/documentation/

 (7) GDB指令參考 (可以打出來方便查詢)

       http://users.ece.utexas.edu/~adnan/gdb-refcard.pdf

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