第一部分牛刀小試:啟動GDB開始調試
1. 編譯帶調試信息的可執行程序:用gcc(g++)編譯的時候帶上-g選項即可
2. 啟動GDB開始調試
(1)gdb program ///最常用的用gdb啟動程序,開始調試的方式
(2)gdb program core ///用gdb查看core dump文件,跟蹤程序core的原因
(3)gdb program pid ///用gdb調試已經開始運行的程序,指定pid即可
3. 應用程序帶命令行參數的情況,可以通過下面三種方法啟動:
(1)啟動GDB的時候,加上--args選項,然后把應用程序和其命令行參數帶在后面,具體格式為:gdb --args program args
(2)先按1中講的方法啟動GDB,然后在執行run命令的時候,后面加上參數
(3)先按1中講的方法啟動GDB,然后用set argsarglist設置命令行參數,接下來再執行run(r)命令運行程序
4. 退出GDB:
(1)End-of-File(Ctrl+d)
(2)quit或者q
5. 在GDB調試程序的時候執行shell命令:
(1)shellcommand args(也可以先執行shell命令,GDB會退出到當前shell,執行完command后,然后在shell中執行exit命令,便可回到GDB)
(2)makemake-args(等同於shell makemake-args)
6. 在GDB中獲取幫助:
(1)在GDB中執行help命令,可以得到如圖1所示的幫助信息:
圖1 GDB幫助菜單
由圖1可以看出,GDB中的命令可以分為八類:別名(aliases)、斷點(breakpoints)、數據(data)、文件(files)、內部(internals)、隱含(obscure)、運行(running)、棧(stack)、狀態(status)、支持(support)、跟蹤點(tracepoints)和用戶自定義(user-defined)。
(2)helpclass-name:查看該類型的命令的詳細幫助說明
(3)help all:列出所有命令的詳細說明
(4)helpcommand:列出命令command的詳細說明
(5)aproposword:列出與word這個詞相關的命令的詳細說明
(6)completeargs:列出所有以args為前輟的命令
7. info和show:
(1)info:用來獲取和被調試的應用程序相關的信息
(2)show:用來獲取GDB本身設置相關的一些信息
第二部分 Breakpoint, Watchpoint和Catchpoint
1. Breakpoints相關命令:(Breakpoint的作用是讓程序執行到某個特定的地方停止運行)
(1)設置breakpoint:
a. breakfunction: 在函數funtion入口處設置breakpoint
b. break +offset:在程序當前停止的行向前offset行處設置breakpoint
c. break –offset:在程序當前停止的行向衙offset行處設置breakpoint
d. breaklinenum: 在當前源文件的第linenum行處設置breakpoint
e. breakfilename:linenum: 在名為filename的源文件的第linenum行處設置breakpoint
f. breakfilename:function: 在名為filename的源文件中的function函數入口處設置breakpoint
g. break *address:在程序的地址address處設置breakpoint
h. break:
i. break … ifcond: …代表上面講到的任意一個可能的參數,在某處設置一個breakpoint,但且僅但cond為true時,程序停下來
j. tbreakargs: 設置一個只停止一次的breakpoints,args與break命令的一樣。這樣的breakpoint當第一次停下來后,就會被自己刪除
k. rbreakregex: 在所有符合正則表達式regex的函數處設置breakpoint
(2)info breakpoints [n]:查看第n個breakpoints的相關信息,如果省略了n,則顯示所有breakpoints的相關信息
(3)pending breakpoints:是指設置在程序開始調試后加載的動態庫中的位置處的breakpoints
a. set breakpoint pending auto: GDB缺省設置,詢問用戶是否要設置pending breakpoint
b. set breakpoint pending on: GDB當前不能識別的breakpoint自動成為pending breakpoint
c. set breakpoint pending off: GDB當前不能識別某個breakpoint時,直接報錯
d. show breakpoint pending:查看GDB關於pending breakpoint的設置的行為(auto, on, off)
(4)breakpoints的刪除:
a. clear:清除當前stack frame中下一條指令之后的所有breakpoints
b. clearfunction & clear filename:function: 清除函數function入口處的breakpoints
c. clearlinenum & clear filename:linenum: 清除第linenum行處的breakpoints
d. delete [breakpoints] [range…]:刪除由range指定的范圍內的breakpoints,range范圍是指breakpoint的序列號的范圍
(5)breakpoints的禁用、啟用:
a. disable [breakpoints] [range…]:禁用由range指定的范圍內的breakpoints
b. enable [breakpoints] [range…]:啟用由range指定的范圍內的breakpoints
c. enable [breakpoints]once [range…]: 只啟用一次由range指定的范圍內的breakpoints,等程序停下來后,自動設為禁用
d. enable [breakpoints]delete [range…]: 啟用range指定的范圍內的breakpoints,等程序停下來后,這些breakpoints自動被刪除
(6)條件breakpoints相關命令:
a. 設置條件breakpoints可以通過break …if cond來設置,也可以通過conditionbnum expression來設置,在這里首先要通過(1)中介紹的命令設置好breakpoints,然后用condition命令來指定某breakpoint的條件,該breakpoint由bnum指定,條件由expression指定
b. conditionbnum: 取消第bnum個breakpoint的條件
c. ignorebnum count: 第bnum個breakpoint跳過count次后開始生效
(7)指定程序在某個breakpoint處停下來后執行一串命令:
a. 格式:commands [bnum]
… command-list …
end
b. 用途:指定程序在第bnum個breakpoint處停下來后,執行由command-list指定的命令串,如果沒有指定bnum,則對最后一個breakpoint生效
c. 取消命令列表:commands [bnum]
end
d. 例子:
break foo if x>0
commands
silent
printf "x is %d\n",x
continue
end
上面的例子含義:當x>0時,在foo函數處停下來,然后打印出x的值,然后繼續運行程序
2. Watchpoints相關命令:(Watchpoint的作用是讓程序在某個表達式的值發生變化的時候停止運行,達到‘監視’該表達式的目的)
(1)設置watchpoints:
a. watchexpr: 設置寫watchpoint,當應用程序寫expr,修改其值時,程序停止運行
b. rwatchexpr: 設置讀watchpoint,當應用程序讀表達式expr時,程序停止運行
c. awatchexpr: 設置讀寫watchpoint, 當應用程序讀或者寫表達式expr時,程序都會停止運行
(2)info watchpoints:查看當前調試的程序中設置的watchpoints相關信息
(3)watchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也與breakpoints的類似
3. Catchpoints相關命令:(catchpoints的作用是讓程序在發生某種事件的時候停止運行,比如C++中發生異常事件,加載動態庫事件)
(1)設置catchpoints:
a. catchevent: 當事件event發生的時候,程序停止運行,這里event的取值有:
1)throw: C++拋出異常
2)catch: C++捕捉到異常
3)exec: exec被調用
4)fork: fork被調用
5)vfork: vfork被調用
6)load:加載動態庫
7)loadlibname: 加載名為libname的動態庫
8)unload:卸載動態庫
9)unloadlibname: 卸載名為libname的動態庫
10)syscall [args]:調用系統調用,args可以指定系統調用號,或者系統名稱
b. tcatchevent: 設置只停一次的catchpoint,第一次生效后,該catchpoint被自動刪除
(2)catchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也與breakpoints的類似
第三部分常用命令介紹
1. attach process-id/detach
(1)attachprocess-id: 在GDB狀態下,開始調試一個正在運行的進程,其進程ID為process-id
(2)detach:停止調試當前正在調試有進程,與attach配對試用
2. kill
(1)基本功能:殺掉當前GDB正在調試的應用程序所對應的子進程
(2)如果想不退出GDB而對當前正在調試的應用程序重新編譯、鏈接,可以在GDB中執行kill殺掉子進程,等編譯、鏈接完后,再重新執行run,GDB便可加載新的可執行程序啟動調試
3. 多線程程序調試相關:
(1)threadthreadno:切換當前線程到由threadno指定的線程
(2)info threads:查看GDB當前調試的程序的各個線程的相關信息
(3)thread apply [threadno] [all]args:對指定(或所有)的線程執行由args指定的命令
4. 多進程程序調試相關(fork/vfork):
(1)缺省方式:fork/vfork之后,GDB仍然調試父進程,與子進程不相關
(2)set follow-fork-modemode:設置GDB行為,mode為parent時,與缺省情況一樣;mode為child時,fork/vfork之后,GDB進入子進程調試,與父進程不再相關
(3)show follow-fork-mode:查看當前GDB多進程跟蹤模式的設置
5. step & stepi
(1)step [count]:如果沒有指定count, 則繼續執行程序,直到到達與當前源文件不同的源文件中時停止;如果指定了count,則重復行上面的過程count次
(2)stepi [count]:如果沒有指定count, 繼續執行下一條機器指令,然后停止;如果指定了count,則重復上面的過程count次
(3)step比較常見的應用場景:在函數func被調用的某行代碼處設置斷點,等程序在斷點處停下來后,可以用step命令進入該函數的實現中,但前提是該函數編譯的時候把調試信息也編譯進去了,負責step會跳過該函數。
6. next & nexti
(1)next [count]:如果沒有指定count, 單步執行下一行程序;如果指定了count,單步執行接下來的count行程序
(2)nexti [count]:如果沒有指定count, 單步執行下一條指令;如果指定了count,單步執行接下來的count條執行
(3)stepi和nexti的區別:nexti在執行某機器指令時,如果該指令是函數調用,那么程序執行直到該函數調用結束時才停止。
7. continue [ignore-count]: 喚醒程序,繼續運行,至到遇到下一個斷點,或者程序結束。如果指定ignore-count,那么程序在接下來的運行中,忽略ignore-count次斷點。
8. finish & return
(1)finish:繼續執行程序,直到當前被調用的函數結束,如果該函數有返回值,把返回值也打印到控制台
(2)return [expression]:中止當前函數的調用,如果指定了expression,把expresson值當做當前函數的返回值;如果沒有,直接結束當前函數調用
9. 信號的處理
(1)info signals &info handle:打印所有的信號相關的信息,以及GDB缺省的處理方式
(2)handlesignal keywords: 設置GDB對具體某個信號的處理方式。signal可以為信號整數值,也可以為SIGSEGV這樣的符號。keywords的取值有:
a. stop和nostop:nostop表示當GDB收到指定的信號,不會應用停止程序的執行,只會打印出一條收到信號的消息,因此,nostop也暗含了下面的print;而stop則表示,當GDB收到指定的信號,停止應用程序的執行。
b. print和noprint:print表示如果收到指定的信號,打印出一條信息;noprint與print表示相反的意思
c. pass和nopass:pass表示如果收到指定的信號,把該信號通知給應用程序;nopass表示與pass相反的意思
d. ignore和noignore:ignore與nopass同義,同理,noignore與pass同義
第四部分調用棧(Call Stack)
1. 查看調用棧信息:
a. backtrace:顯示程序的調用棧信息,可以用bt縮寫
b. backtracen: 顯示程序的調用棧信息,只顯示棧頂n楨(frame)
c. backtrace -n:顯示程序的調用棧信息,只顯示棧底部n楨(frame)
d. set backtrace limitn: 設置bt顯示的最大楨層數
e. where,info stack:都是bt的別名,功能一樣
2. 選擇某一楨進行查看:
a. framen: 查看第n楨的信息
b. frameaddr: 查看pc地址為addr的楨的相關信息
c. upn: 查看當前楨上面第n楨的信息
d. downn: 查看當前楨下面第n楨的信息
3. frame信息內容:
a. 用backtrace、framen或者frameaddr得到的簡要信息內容:
(1)楨序號(Frame number)
(2)函數名
(3)Program counter(除非set print address off)(在程序當前執行到的那一楨,PC不會被顯示)
(4)源代碼文件名和行號
(5)函數的參數名和傳入的值
b. 用info frame、info framen或者info frameaddr得到的詳細的信息內容:
(1)當前楨的地址
(2)下一楨的地址
(3)上一楨的地址
(4)源代碼所用的程序的語言(c/c++)
(5)當前楨的參數的地址
(6)當前相中局部變量的地址
(7)PC(program counter)
(8)當前楨中存儲的寄存器
4. info args:查看當前楨中的參數
5. info locals:查看當前楨中的局部變量
6. info catch:查看當前楨中的異常處理器(exception handlers)
第五部分數據和源代碼(Data and Source Code)
1. list命令(縮寫為l):
(1)listlinenum: 打印當前文件中第linenum行周圍的源代碼
(2)listfunction: 打印function函數周圍的源代碼
(3)list:在上一次使用list命令的基礎上,再多打印一些源代碼
(4)list -:打印和上一次使用list命令一樣的源代碼
(5)set listsizecount: 設置list命令顯示源代碼的行數
(6)show listsize:查看list命令顯示
2. 用edit命令在GDB模式下編輯源代碼:
(1)選擇合適的編輯器,gdb會選擇/bin/ex做為源代碼編輯器,有些linux發行版上可能會沒有安裝/bin/ex,可以把編輯器修改為比較常見的vim,具體做法為:有啟動gdb之前,在命令行執行export EDITOR=/usr/bin/vim(或者可以在.profile中設置EDITOR這個變量的值為/usr/bin/vim,這樣就不用每次啟動gdb的時候都去設置一下了)
(2)edit:編輯當前文件
(3)editnumber: 編輯當前文件的第number行
(4)editfunction: 編輯當前文件的function函數
(5)editfilename: number: 編輯名為filename的文件的第number行
(6)editfilename: function: 編輯名為filename的文件的function函數
3. 設置源代碼目錄
(1)directorydirname: 設置當前調試的程序的源代碼目錄為dirname
(2)directory:將當前調試的程序的源代碼目錄清空
(3)show directories:打印當前調試的程序的源代碼目錄
4. print命令打印數據:
(1)printexpr: 打印表達式expr的值
(2)print /f expr:以f指定的格式打印表達式expr的值
(3)print:打印上一次打印的表達式的值
(4)print /f:以f指定的形式打印上一次打印的表達式的值
(print支持的格式有:x-16進制整數,d-10進制整數,u-10進制無符號整數,o-8進制整數,t-2進制整數,a-地址形式整數,c-字符常量整數,f-浮點數)
5. GDB支持的表達式:
(1)Any kind of constant, variable or operator defined by the programming language you are using is valid in an expression inGDB.
(2)@address:把address指定的內存當作數組,語法為p *array@len
(3)file::variable:指定變量varialbe被定義的文件file
(4)function::varable:指定變量variable被定義的函數function
(5){type}address: 把address指定的內存解釋為type類型(類似於強制轉型,更加強)
6. 打印內存:x /nfu addr:
(1)n:重復次數,缺省是1
(2)f:打印格式,與print的相同的,還有s-C風格字符串,i-機器指令,缺省是x
(3)u:打印單位大小,b-byte,h-halfwords(2字節),w-words(4字節),g-Giant words(8字節)
7. 自動打印:
(1)display /f expr|addr:以f為格式,打印expr或者addr
(2)undisplaydnums,delete display dnums:刪除第dnums個display點
(3)disable displaydnums:禁用第dnums個display點
(4)enable displaydnums:啟用第dnums個display點
(5)info display:查看所有的display點
8. 打印選項:
a. set printfield: 打開field選項
b. set printfield on: 打開field選項
c. set printfield off: 關閉field選項
d. show printfield: 查看field選項的打開、關閉情況
(1)set print array:以一種比較好看的方式打印數組,缺省是關閉的
(2)set print elementsnum-of-elements:設置GDB打印數據時顯示元素的個數,缺省為200,設為0表示不限制(unlimited)
(3)set print null-stop:設置GDB打印字符數組的時候,遇到NULL時停止,缺省是關閉的
(4)set print pretty:設置GDB打印結構的時候,每行一個成員,並且有相應的縮進,缺省是關閉的
(5)set print object:設置GDB打印多態類型的時候,打印實際的類型,缺省為關閉
(6)set print static-members:設置GDB打印結構的時候,是否打印static成員,缺省是打開的
(7)set print vtbl:以漂亮的方式打印C++的虛函數表,缺省是關閉的
9. 寄存器:
(1)info registers:查看當前楨中的各個寄存器的情況
(2)info registersregname: 查看指定的寄存器
(3)各個寄存器:
10. 內存copy:
(1)dump [format]memory filename start_addr end_addr
(2)append [binary]memory filename start_addr end_addr
(3)restorefilename [binary] bias start end
11. 在GDB中定義宏:
(1)info macromacro:查看宏macro的定義
(2)macro definemacro replacement-list:(還沒實現)
(3)macro definemacro(arglist) replacement-list:(還沒實現)
(4)macro undefmacro:(還沒實現)
12. 修改程序的運行(Altering Execution)
(1)修改變量值:
a. printv=value: 修改變量值的同時,把修改后的值顯示出來
b. set [var]v=value: 修改變量值,需要注意如果變量名與GDB中某個set命令中的關鍵字一樣的話,前面加上var關鍵字
c. whatisv: 查看變量類型
(2)signalsignal: 向程序發送信號signal,signal可以是信號的符號或數字形式,如果signal=0,那么程序將會繼續運行,程序不會收到任何信號。
(3)return [expression]:中斷函數執行,從當前位置直接返回。(注意:finish是把函數運行完,再返回,return是直接返回。)
(4)callexpr: 在GDB中調用應用程序中的函數
13. 用戶自定義命令:
(1)定義一個命令
definecommandname
…
end
(2)條件語句:
if cond-expr
…
else
…
end
(4)循環語句:
whilecond-expr
…
end
(5)定義一個命令的文檔信息,在helpcommandname的時候可以顯示:
documentcommandname
…
end
(6)$arg0…$arg9:表示命令行參數,最多10個
(7)help user-defined:查看所有的用戶自定義命令
(8)show usercommandname:查看自定義命令commandname的定義
(9)helpcommandname:查看自定義命令commandname的幫助信息
(10)show max-user-call-depth:查看用戶自定義命令的最大遞歸調用深度
(11)set max-user-call-depth:設置用戶自定義命令的最大遞歸調用深度
轉載自:http://www.wuzesheng.com