一、gdb調(diào)試基本知識 a.調(diào)試器指示的是將要執(zhí)行的代碼行 b.只有在編譯時擁有調(diào)試符號(-g)的程序才能在調(diào)試時看到源碼 c.同一行上有多個斷點(diǎn)時,gdb僅中斷在斷點(diǎn)號最小的那個斷點(diǎn)上 d.斷點(diǎn)可以設(shè)置在同一程序的不同文件中 e.在任何給定時間,gdb只有一個焦點(diǎn),即當(dāng)前“活動”的文件 f.源文件改變后,斷點(diǎn)發(fā)生移動,帶式斷點(diǎn)屬性的行號不變 二、GDB基本命令清單查詢 在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有: * aliases:命令別名 * breakpoints:斷點(diǎn)定義; * data:數(shù)據(jù)查看; * files:指定并查看文件; * internals:維護(hù)命令; * running:程序執(zhí)行; * stack:調(diào)用棧查看; * statu:狀態(tài)查看; * tracepoints:跟蹤程序執(zhí)行。 鍵入 help 后跟命令的分類名(如help aliases),可獲得該類命令的詳細(xì)清單。 三、GDB基本命令用法 1、運(yùn)行退出 run(簡寫r):執(zhí)行程序 (gdb)run app [argv1] [argv2] ... run命令后可跟隨發(fā)給該程序的任何參數(shù),包括標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出說明符(<和>)和外殼通配符(*、?、[、])在內(nèi)。 如果使用不帶參數(shù)的run命令,gdb就再次使用前一條run命令的參數(shù)。 set args:設(shè)定傳遞給程序的參數(shù) (gdb)set args [argv1] [argv2] ... show args:查看其缺省參數(shù)的列表 (gdb)show args kill(簡寫k):異常終止在gdb 控制下運(yùn)行的程序 (gdb)kill quit(簡寫q):退出gdb (gdb)quit 2、查看信息 list(簡寫l):查看源碼 (gdb) list line_num或l line_num,line_num為行號。 pirnt(簡寫p): print var:查看變量var的值。 (gdb) print var 可以通過添加參數(shù)來設(shè)置輸出格式: /x 按十六進(jìn)制格式顯示變量 /d 按十進(jìn)制格式顯示變量 /u 按十六進(jìn)制格式顯示無符號整型 /o 按八進(jìn)制格式顯示變量 /t 按二進(jìn)制格式顯示變量 /a 按十六進(jìn)制格式顯示變量 /c 按字符格式顯示變量 /f 按浮點(diǎn)數(shù)格式顯示變量 例如:print /x var print可以顯示被調(diào)試的語言中任何有效的表達(dá)式。表達(dá)式除了包含程序中的變量外,還可以包含以下內(nèi)容: a).對程序中函數(shù)的調(diào)用 (gdb) print find_entry(1,0) b).數(shù)據(jù)結(jié)構(gòu)和其他復(fù)雜對象 (gdb) print *table_start $8={e=reference=’\000’,location=0x0,next=0x0} c).值的歷史成分 (gdb)print $1 ($1為歷史記錄變量,在以后可以直接引用 $1 的值) d).人為數(shù)組 人為數(shù)組提供了一種去顯示存儲器塊(數(shù)組節(jié)或動態(tài)分配的存儲區(qū))內(nèi)容的方法。早期的調(diào)試程序沒有很好的方法將任意的指針換成一個數(shù)組。就像對待參數(shù)一樣,讓我們查看內(nèi)存中在變量h后面的10個整數(shù),一個動態(tài)數(shù)組的語法如下所示: base@length 因此,要想顯示在h后面的10個元素,可以使用h@10: (gdb)print h@10 $13=(-1,345,23,-234,0,0,0,98,345,10) e).給變量賦值 print除了顯示一個變量的值外,還可以用來賦值,如: (gdb)print var=1 info(簡寫i): info break:顯示斷點(diǎn)信息,下面斷點(diǎn)部分詳述。 (gdb)info break info local:顯示當(dāng)前函數(shù)中的局部變量信息。 (gdb)info local info var:系那是所有的全局和靜態(tài)變量名稱。 (gdb)info var info func:顯示所有的函數(shù)名稱。 (gdb)info func info prog:顯示被調(diào)試程序的執(zhí)行狀態(tài)。 (gdb)info prog info files:顯示被調(diào)試文件的詳細(xì)信息。 (gdb)info files whatis:顯示變量的類型 如程序中定義struct timeval var; (gdb) whatis var type = struct timeval ptype:比whatis的功能更強(qiáng),它可以提供一個結(jié)構(gòu)的定義 (gdb)ptype var type = struct timeval{ __time_t tv_sec; __suseconds_t tv_usec; } 3、暫停執(zhí)行 break(簡寫b):在調(diào)試的程序中設(shè)置斷點(diǎn) 該命令有如下四種形式: (gdb)break line_number:使程序在執(zhí)行給定行之前停止。 (gdb)break function_name:使程序在進(jìn)入指定的函數(shù)之前停止。 (gdb)break line-or-function if condition:如果condition(條件)是真,程序到達(dá)指定行或函數(shù)時停止。 (gdb)break routine-name:在指定例程的入口處設(shè)置斷點(diǎn) 多源文件中設(shè)置斷點(diǎn): (gdb) break filename:line-number (gdb) break filename:function-name break if:條件斷點(diǎn),滿足特定條件后才會中斷 (gdb) break line-or-function if (condition) 例如: (gdb) break 46 if testsize==100 break thread:線程中斷 (gdb)break [line_number] thread [thread_number] [if ...] line_number:斷點(diǎn)設(shè)置所在代碼行號 thread_number:線程的ID。由GDB分配,通過info threads查看運(yùn)行中程序的線程信息。 if ...:設(shè)置中斷條件。 condition(簡寫cond):與break if 類似,只是condition只能用在已存在的斷點(diǎn)上 (gdb)condition <break_list> (condition) 例如: (gdb)cond 3 i==3 將在斷點(diǎn)3上附加條件(i==3) tbreak(簡寫tb):臨時斷點(diǎn),中斷一次后自動刪除斷點(diǎn),形式參照break 斷點(diǎn)的管理 1.顯示當(dāng)前gdb的斷點(diǎn)信息info(簡寫i): (gdb) info break或i b 它會以如下的形式顯示所有的斷點(diǎn)信息: Num Type Disp Enb Address What 1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155 2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168 Num:斷點(diǎn)號 Type:斷點(diǎn)類型(斷點(diǎn)、監(jiān)視點(diǎn)、捕獲點(diǎn)) Disp:斷點(diǎn)部署(該斷點(diǎn)下次中斷后該如何處理該斷點(diǎn)) keep:保持不變 del: 刪除該斷點(diǎn) dis: 禁用該斷點(diǎn) Enb:斷點(diǎn)當(dāng)前啟用狀態(tài) What:斷點(diǎn)位置 2.刪除斷點(diǎn): (gdb) delete breakpoint 1 刪除編號為1的斷點(diǎn),如果不帶編號參數(shù),將刪除所有的斷點(diǎn) (gdb) delete breakpoint 3.禁止使用某個斷點(diǎn) (gdb) disable breakpoint 1 禁止斷點(diǎn) 1,斷點(diǎn)信息的 (Enb)域?qū)⒆優(yōu)?nbsp;n 4.允許使用某個斷點(diǎn) (gdb) enable breakpoint 1 允許斷點(diǎn) 1,斷點(diǎn)信息的 (Enb)域?qū)⒆優(yōu)?nbsp;y (gdb)enable once breakpoint 1 斷點(diǎn)1中斷一次后自動禁用 5.刪除剛才停止處的斷點(diǎn) (gdb)clear 6.清除某一代碼行上的所有斷點(diǎn) (gdb)clear [filename:]line_number 7.清除某一函數(shù)的斷點(diǎn) (gdb)clear [filename:]function_name 8.移動斷點(diǎn) gdb中移動斷點(diǎn)的唯一方法是刪除斷點(diǎn)后在新的位置再放置一個一模一樣的斷點(diǎn),但ddd中只需要拖曳斷點(diǎn)符號就可以移動新的斷點(diǎn),并且保留該斷點(diǎn)的所有屬性。 為斷點(diǎn)設(shè)置命令列表 通常,設(shè)置一個斷點(diǎn)并且在上面中斷后,一般會查詢一些變量或做一些其他動作。使用命令列表(commands)就能使程序到達(dá)斷點(diǎn)后自動執(zhí)行這些動作。 步驟如下: 1.建立斷點(diǎn) 2.使用commands命令,用法(gdb)command break_list,如: (gdb)commands 1 Type commands for when breakpoint 1 is hit, one per line. End with a line saying just "end". >silent >printf "n = %d\n", n >continue >end 監(jiān)視點(diǎn) watch:監(jiān)視變量的變化達(dá)到條件時停止程序執(zhí)行 (gdb)watch i>99 注意:監(jiān)視點(diǎn)的設(shè)定不依賴于斷點(diǎn)的位置,但是與變量的作用域有關(guān)。也就是說,要設(shè)置監(jiān)視點(diǎn)必須在程序運(yùn)行時才可設(shè)置。 捕捉點(diǎn) catch event:當(dāng)event發(fā)生時,停止執(zhí)行程序 event可為以下情況: throw:一個C++拋出的異常(throw為關(guān)鍵字) catch:一個C++捕捉到的異常(catch為關(guān)鍵字) exec:調(diào)用系統(tǒng)調(diào)用exec時(exec為關(guān)鍵字,目前此功能只在HP-UX下有用)fork:調(diào)用系統(tǒng)調(diào)用fork時(fork為關(guān)鍵字,目前此功能只在HP-UX下有用) vfork:調(diào)用系統(tǒng)調(diào)用vfork時(vfork為關(guān)鍵字,目前此功能只在HP-UX下有用) load 或 load 載入共享庫(動態(tài)鏈接庫)時(load為關(guān)鍵字,目前此功能只在HP-UX下有用) unload 或 unload 卸載共享庫(動態(tài)鏈接庫)時(unload為關(guān)鍵字,目前此功能只在HP-UX下有用) 4、恢復(fù)執(zhí)行 next(簡寫n):不進(jìn)入的單步執(zhí)行 (gdb)next或n step(簡寫s):進(jìn)入的單步執(zhí)行 (gdb)step或s continue(簡寫c):從斷點(diǎn)繼續(xù)運(yùn)行 (gdb)continue [n] 參數(shù)n使gdb忽略接下來的n個斷點(diǎn)。 finish:程序已經(jīng)進(jìn)入了某函數(shù),執(zhí)行finish退出該函數(shù)返回到它的調(diào)用函數(shù)中 (gdb)finish until:無參的until命令恢復(fù)程序的運(yùn)行,并執(zhí)行完循環(huán)的其余部分 until官方定義:執(zhí)行程序,直到到達(dá)當(dāng)前循環(huán)體外的下一行源代碼 實(shí)際上,由于高級語言到機(jī)器語言在順序上并不一定完全對應(yīng),until在到達(dá)內(nèi)存地址比當(dāng)前高的機(jī)器指令后就會停止 用法: until [filename:]line_number until [filename:]function 以上兩種用法在到達(dá)指定的行號或者函數(shù)后即停止。 5、變量賦值 除了使用print給變量賦值,還可以使用set variable命令賦值。 set variable:給變量賦值 (gdb)set variable i=1 6、函數(shù)調(diào)用 call func_name:調(diào)用和執(zhí)行一個函數(shù) (gdb) call gen_and_sork(1234, 1, 0) (gdb) call printf(“abcd\n”) abcd $1=4 jump:在源程序中的另一點(diǎn)開始運(yùn)行 (gdb)jump line_number 7、棧信息 backtrace(簡寫bt):為堆棧提供向后跟蹤功能 backtrace [-n] [n] 顯示程序中的當(dāng)前位置和表示如何到達(dá)當(dāng)前位置的棧跟蹤。 -n:表示只打印棧底上n層的棧信息 n:表示只打印棧頂上n層的棧信息 不加參數(shù),表示打印所有棧信息。 down:下移棧幀,使得另一個函數(shù)成為當(dāng)前函數(shù) up:上移棧幀,使另一函數(shù)成為當(dāng)前函數(shù) 8、信號 handle signals [argu]:捕捉信號 signals:是Linux/Unix定義的信號,SIGINT表示中斷字符信號,也就是Ctrl+C的信號,SIGBUS表示硬件故障的信號等等。 argu: nostop:接收到信號時,GDB不會停止程序的運(yùn)行,但會打出消息通知收到這種信號。 stop:接受到信號時停止程序的執(zhí)行,允許程序調(diào)試;顯示一條表示已接受到信號的消息(禁止使用消息除外)。 print:接受到信號時顯示一條消息。 noprint:接受到信號時不要顯示消息。 pass or noignore:接收到信號時,GDB不處理信號。這表示,GDB會把這個信號交給被調(diào)試程序處理。 nopass or ignore:接收到信號時,GDB不會讓調(diào)試程序來處理這個信號。 例如,假定截獲SIGPIPE信號,以防止正在調(diào)試的程序接受到該信號,而且只要該信號一到達(dá),就要求該程序停止,并通知你。要完成這一任務(wù),可利用如下命令: (gdb) handle SIGPIPE stop print UNIX的信號名總是采用大寫字母!可以用信號編號替代信號名 如果程序要測試其信號處理程序,就需要一種能將信號發(fā)送給程序的簡便方法:signal命令。signal的參數(shù)是一個數(shù)字或者一個名字,如SIGINT。假定程序已將一個專用的SIGINT(鍵盤輸入,或CTRL-C;信號2)信號處理程序設(shè)置成某個動作,要測試該信號處理程序,可設(shè)置一個斷點(diǎn)并使用如下命令: (gdb)signal 2 continuing with signal SIGINT(2) 該程序繼續(xù)執(zhí)行,但是立即傳輸該信號,而且處理程序開始運(yùn)行。 9、字段搜索 search text:至上往下搜索,顯示在當(dāng)前文件中包含text的代碼行 reverse-search text:至下往上搜索,顯示包含text的代碼行 10、UNIX接口 shell:使可不用離開gdb下啟動unix外殼 (gdb)shell exit(快捷鍵ctrl+d):退出unix外殼,返回到 gdb #exit 11、工作目錄 cd:改變工作目錄 (gdb)cd [path] pwd:顯示工作目錄 (gdb)pwd 12、機(jī)器語言工具 有一組專用的gdb變量可以用來檢查和修改計(jì)算機(jī)的通用寄存器,gdb提供了目前每一臺計(jì)算機(jī)中實(shí)際使用的4個寄存器的標(biāo)準(zhǔn)名字: $pc : 程序計(jì)數(shù)器 $fp : 幀指針(當(dāng)前堆棧幀) $sp : 棧指針 $ps : 處理器狀態(tài) 13、命令的歷史 為了允許使用歷史命令,可使用 set history expansion on 命令 (gdb) set history expansion on 參考資料: http://www./baby-fly/archive/2010/07/27/121395.html http:///blog/2011/05/21/gdb-basic-knowledge/ http://fanqiang./program/other/2006-07-14/4834.shtml |
|