GDB的使用方法_第1頁
GDB的使用方法_第2頁
GDB的使用方法_第3頁
GDB的使用方法_第4頁
GDB的使用方法_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

GDB是一個(gè)強(qiáng)大的命令行調(diào)試工具。大家知道命令行的強(qiáng)大就是在于,其可以形成執(zhí)行序列,形成腳本。UNIX下的軟件全是命令行的,這給程序開發(fā)提代供了極大的便利,命令行軟件的優(yōu)勢在于,它們可以非常容易的集成在一起,使用幾個(gè)簡單的已有工具的命令,就可以做出一個(gè)非常強(qiáng)大的功能。于是UNIX下的軟件比Windows下的軟件更能有機(jī)地結(jié)合,各自發(fā)揮各自的長處,組合成更為強(qiáng)勁的功能。而Windows下的圖形軟件基本上是各自為營,互相不能調(diào)用,很不利于各種軟件的相互集成。在這里并不是要和Windows做個(gè)什么比較,所謂“寸有所長,尺有所短”,圖形化工具還是有不如命令行的地方。GDB概述GDB是GNU開源組織發(fā)布的一個(gè)強(qiáng)大的UNIX下的程序調(diào)試工具?;蛟S,各位比較喜歡那種圖形界面方式的,像VC、BCB等IDE的調(diào)試,但如果你是在UNIX平臺下做軟件,你會(huì)發(fā)現(xiàn)GDB這個(gè)調(diào)試工具有比VC、BCB的圖形化調(diào)試器更強(qiáng)大的功能。所謂“寸有所長,尺有所短”就是這個(gè)道理。一般來說,GDB主要幫忙你完成下面四個(gè)方面的功能:1、啟動(dòng)你的程序,可以按照你的自定義的要求隨心所欲的運(yùn)行程序。2、可讓被調(diào)試的程序在你所指定的調(diào)置的斷點(diǎn)處停住。(斷點(diǎn)可以是條件表達(dá)式)3、當(dāng)程序被停住時(shí),可以檢查此時(shí)你的程序中所發(fā)生的事。4、動(dòng)態(tài)的改變你程序的執(zhí)行環(huán)境。從上面看來,GDB和一般的調(diào)試工具沒有什么兩樣,基本上也是完成這些功能,不過在細(xì)節(jié)上,你會(huì)發(fā)現(xiàn)GDB這個(gè)調(diào)試工具的強(qiáng)大,大家可能比較習(xí)慣了圖形化的調(diào)試工具,但有時(shí)候,命令行的調(diào)試工具卻有著圖形化工具所不能完成的功能。讓我們一一看來。一個(gè)調(diào)試示例源程序:tst.c代碼:1#include23intfunc(intn)45intsum=0,i;6for(i=0;i78sum+=i;910returnsum;11121314main()1516inti;17longresult=0;18for(i=1;icc-gtst.c-otst使用GDB調(diào)試:代碼:hchen/testgdbtst-啟動(dòng)GDBGNUgdb5.1.1Copyright2002FreeSoftwareFoundation,Inc.GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouarewelcometochangeitand/ordistributecopiesofitundercertainconditions.Typeshowcopyingtoseetheconditions.ThereisabsolutelynowarrantyforGDB.Typeshowwarrantyfordetails.ThisGDBwasconfiguredasi386-suse-linux.(gdb)l-l命令相當(dāng)于list,從第一行開始例出原碼。1#include23intfunc(intn)45intsum=0,i;6for(i=0;i78sum+=i;910returnsum;(gdb)-直接回車表示,重復(fù)上一次命令11121314main()1516inti;17longresult=0;18for(i=1;i=100;i+)1920result+=i;(gdb)break16-設(shè)置斷點(diǎn),在源程序第16行處。Breakpoint1at0x8048496:filetst.c,line16.(gdb)breakfunc-設(shè)置斷點(diǎn),在函數(shù)func()入口處。Breakpoint2at0x8048456:filetst.c,line5.(gdb)infobreak-查看斷點(diǎn)信息。NumTypeDispEnbAddressWhat1breakpointkeepy0x08048496inmainattst.c:162breakpointkeepy0x08048456infuncattst.c:5(gdb)r-運(yùn)行程序,run命令簡寫Startingprogram:/home/hchen/test/tstBreakpoint1,main()attst.c:17-在斷點(diǎn)處停住。17longresult=0;(gdb)n-單條語句執(zhí)行,next命令簡寫。18for(i=1;i=100;i+)(gdb)n20result+=i;(gdb)n18for(i=1;i=100;i+)(gdb)n20result+=i;(gdb)c-繼續(xù)運(yùn)行程序,continue命令簡寫。Continuing.result1-100=5050-程序輸出。Breakpoint2,func(n=250)attst.c:55intsum=0,i;(gdb)n6for(i=1;i=n;i+)(gdb)pi-打印變量i的值,print命令簡寫。$1=134513808(gdb)n8sum+=i;(gdb)n6for(i=1;i=n;i+)(gdb)psum$2=1(gdb)n8sum+=i;(gdb)pi$3=2(gdb)n6for(i=1;i=n;i+)(gdb)psum$4=3(gdb)bt-查看函數(shù)堆棧。#0func(n=250)attst.c:5#10x080484e4inmain()attst.c:24#20x400409edin_libc_start_main()from/lib/libc.so.6(gdb)finish-退出函數(shù)。Runtillexitfrom#0func(n=250)attst.c:50x080484e4inmain()attst.c:2424printf(result1-250=%d,func(250);Valuereturnedis$6=31375(gdb)c-繼續(xù)運(yùn)行。Continuing.result1-250=31375-程序輸出。Programexitedwithcode027.-程序退出,調(diào)試結(jié)束。(gdb)q好了,有了以上的感性認(rèn)識,還是讓我們來系統(tǒng)地認(rèn)識一下gdb好了,有了以上的感性認(rèn)識,還是讓我們來系統(tǒng)地認(rèn)識一下gdb吧。使用GDB一般來說GDB主要調(diào)試的是C/C+的程序。要調(diào)試C/C+的程序,首先在編譯時(shí),我們必須要把調(diào)試信息加到可執(zhí)行文件中。使用編譯器(cc/gcc/g+)的-g參數(shù)可以做到這一點(diǎn)。如:cc-ghello.c-ohellog+-ghello.cpp-ohello如果沒有-g,你將看不見程序的函數(shù)名、變量名,所代替的全是運(yùn)行時(shí)的內(nèi)存地址。當(dāng)你用-g把調(diào)試信息加入之后,并成功編譯目標(biāo)代碼以后,讓我們來看看如何用gdb來調(diào)試他。啟動(dòng)GDB的方法有以下幾種:1、gdb文件名program也就是你的執(zhí)行文件,一般在當(dāng)然目錄下。2、gdbcore用gdb同時(shí)調(diào)試一個(gè)運(yùn)行程序和core文件,core是程序非法執(zhí)行后coredump后產(chǎn)生的文件。3、gdbID如果你的程序是一個(gè)服務(wù)程序,那么你可以指定這個(gè)服務(wù)程序運(yùn)行時(shí)的進(jìn)程ID。gdb會(huì)自動(dòng)attach上去,并調(diào)試他。program應(yīng)該在PATH環(huán)境變量中搜索得到。GDB啟動(dòng)時(shí),可以加上一些GDB的啟動(dòng)開關(guān),詳細(xì)的開關(guān)可以用gdb-help查看。我在下面只例舉一些比較常用的參數(shù):-symbols-s從指定文件中讀取符號表。-sefile從指定文件中讀取符號表信息,并把他用在可執(zhí)行文件中。-core-c調(diào)試時(shí)coredump的core文件。-directory-d加入一個(gè)源文件的搜索路徑。默認(rèn)搜索路徑是環(huán)境變量中PATH所定義的路徑。GDB的命令概貌啟動(dòng)gdb后,就你被帶入gdb的調(diào)試環(huán)境中,就可以使用gdb的命令開始調(diào)試程序了,gdb的命令可以使用help命令來查看,如下所示:/home/hchengdbGNUgdb5.1.1Copyright2002FreeSoftwareFoundation,Inc.GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouarewelcometochangeitand/ordistributecopiesofitundercertainconditions.Typeshowcopyingtoseetheconditions.ThereisabsolutelynowarrantyforGDB.Typeshowwarrantyfordetails.ThisGDBwasconfiguredasi386-suse-linux.(gdb)helpListofclassesofcommands:aliases-Aliasesofothercommandsbreakpoints-Makingprogramstopatcertainpointsdata-Examiningdatafiles-Specifyingandexaminingfilesinternals-Maintenancecommandsobscure-Obscurefeaturesrunning-Runningtheprogramstack-Examiningthestackstatus-Statusinquiriessupport-Supportfacilitiestracepoints-Tracingofprogramexecutionwithoutstoppingtheprogramuser-defined-User-definedcommandsTypehelpfollowedbyaclassnameforalistofcommandsinthatclass.Typehelpfollowedbycommandnameforfulldocumentation.Commandnameabbreviationsareallowedifunambiguous.(gdb)gdb的命令很多,gdb把之分成許多個(gè)種類。help命令只是例出gdb的命令種類,如果要看種類中的命令,可以使用help命令,如:helpbreakpoints,查看設(shè)置斷點(diǎn)的所有命令。也可以直接help來查看命令的幫助。gdb中,輸入命令時(shí),可以不用打全命令,只用打命令的前幾個(gè)字符就可以了,當(dāng)然,命令的前幾個(gè)字符應(yīng)該要標(biāo)志著一個(gè)唯一的命令,在Linux下,你可以敲擊兩次TAB鍵來補(bǔ)齊命令的全稱,如果有重復(fù)的,那么gdb會(huì)把其例出來。示例一:在進(jìn)入函數(shù)func時(shí),設(shè)置一個(gè)斷點(diǎn)??梢郧萌隻reakfunc,或是直接就是bfunc(gdb)bfuncBreakpoint1at0x8048458:filehello.c,line10.示例二:敲入b按兩次TAB鍵,你會(huì)看到所有b打頭的命令:(gdb)bbacktracebreakbt(gdb)示例三:只記得函數(shù)的前綴,可以這樣:(gdb)bmake_(再按下一次TAB鍵,你會(huì)看到:)make_a_section_from_filemake_environmake_abs_sectionmake_function_typemake_blockvectormake_pointer_typemake_cleanupmake_reference_typemake_commandmake_symbol_completion_list(gdb)bmake_GDB把所有make開頭的函數(shù)全部例出來給你查看。示例四:調(diào)試C+的程序時(shí),有可以函數(shù)名一樣。如:(gdb)bbubble(M-?bubble(double,double)bubble(int,int)(gdb)bbubble(你可以查看到C+中的所有的重載函數(shù)及參數(shù)。(注:M-?和“按兩次TAB鍵”是一個(gè)意思)要退出gdb時(shí),只用發(fā)quit或命令簡稱q就行了。GDB中運(yùn)行UNIX的shell程序在gdb環(huán)境中,你可以執(zhí)行UNIX的shell的命令,使用gdb的shell命令來完成:shell調(diào)用UNIX的shell來執(zhí)行,環(huán)境變量SHELL中定義的UNIX的shell將會(huì)被用來執(zhí)行,如果SHELL沒有定義,那就使用UNIX的標(biāo)準(zhǔn)shell:/bin/sh。(在Windows中使用C或cmd.exe)還有一個(gè)gdb命令是make:make可以在gdb中執(zhí)行make命令來重新build自己的程序。這個(gè)命令等價(jià)于“shellmake”。在GDB中運(yùn)行程序當(dāng)以gdb方式啟動(dòng)gdb后,gdb會(huì)在PATH路徑和當(dāng)前目錄中搜索的源文件。如要確認(rèn)gdb是否讀到源文件,可使用l或list命令,看看gdb是否能列出源代碼。在gdb中,運(yùn)行程序使用r或是run命令。程序的運(yùn)行,你有可能需要設(shè)置下面四方面的事。1、程序運(yùn)行參數(shù)。setargs可指定運(yùn)行時(shí)參數(shù)。(如:setargs1020304050)showargs命令可以查看設(shè)置好的運(yùn)行參數(shù)。2、運(yùn)行環(huán)境。path可設(shè)定程序的運(yùn)行路徑。showpaths查看程序的運(yùn)行路徑。setenvironmentvarname=value設(shè)置環(huán)境變量。如:setenvUSER=hchenshowenvironmentvarname查看環(huán)境變量。3、工作目錄。cd相當(dāng)于shell的cd命令。pwd顯示當(dāng)前的所在目錄。4、程序的輸入輸出。infoterminal顯示你程序用到的終端的模式。使用重定向控制程序輸出。如:runoutfiletty命令可以指寫輸入輸出的終端設(shè)備。如:tty/dev/ttyb調(diào)試已運(yùn)行的程序兩種方法:1、在UNIX下用ps查看正在運(yùn)行的程序的PID(進(jìn)程ID),然后用gdbPID格式掛接正在運(yùn)行的程序。2、先用gdb關(guān)聯(lián)上源代碼,并進(jìn)行g(shù)db,在gdb中用attach命令來掛接進(jìn)程的PID。并用detach來取消掛接的進(jìn)程。暫停/恢復(fù)程序運(yùn)行調(diào)試程序中,暫停程序運(yùn)行是必須的,GDB可以方便地暫停程序的運(yùn)行。你可以設(shè)置程序的在哪行停住,在什么條件下停住,在收到什么信號時(shí)停往等等。以便于你查看運(yùn)行時(shí)的變量,以及運(yùn)行時(shí)的流程。當(dāng)進(jìn)程被gdb停住時(shí),你可以使用infoprogram來查看程序的是否在運(yùn)行,進(jìn)程號,被暫停的原因。在gdb中,我們可以有以下幾種暫停方式:斷點(diǎn)(BreakPoint)、觀察點(diǎn)(WatchPoint)、捕捉點(diǎn)(CatchPoint)、信號(Signals)、線程停止(ThreadStops)。如果要恢復(fù)程序運(yùn)行,可以使用c或是continue命令。一、設(shè)置斷點(diǎn)(BreakPoint)我們用break命令來設(shè)置斷點(diǎn)。正面有幾點(diǎn)設(shè)置斷點(diǎn)的方法:break在進(jìn)入指定函數(shù)時(shí)停住。C+中可以使用class:function或function(type,type)格式來指定函數(shù)名。break在指定行號停住。break+offsetbreak-offset在當(dāng)前行號的前面或后面的offset行停住。offiset為自然數(shù)。breakfilename:linenum在源文件filename的linenum行處停住。breakfilename:function在源文件filename的function函數(shù)的入口處停住。break*address在程序運(yùn)行的內(nèi)存地址處停住。breakbreak命令沒有參數(shù)時(shí),表示在下一條指令處停住。break.if.可以是上述的參數(shù),condition表示條件,在條件成立時(shí)停住。比如在循環(huán)境體中,可以設(shè)置breakifi=100,表示當(dāng)i為100時(shí)停住程序。查看斷點(diǎn)時(shí),可使用info命令,如下所示:(注:n表示斷點(diǎn)號)infobreakpointsninfobreakn二、設(shè)置觀察點(diǎn)(WatchPoint)觀察點(diǎn)一般來觀察某個(gè)表達(dá)式(變量也是一種表達(dá)式)的值是否有變化了,如果有變化,馬上停住程序。我們有下面的幾種方法來設(shè)置觀察點(diǎn):watch為表達(dá)式(變量)expr設(shè)置一個(gè)觀察點(diǎn)。一量表達(dá)式值有變化時(shí),馬上停住程序。rwatch當(dāng)表達(dá)式(變量)expr被讀時(shí),停住程序。awatch當(dāng)表達(dá)式(變量)的值被讀或被寫時(shí),停住程序。infowatchpoints列出當(dāng)前所設(shè)置了的所有觀察點(diǎn)。三、設(shè)置捕捉點(diǎn)(CatchPoint)你可設(shè)置捕捉點(diǎn)來補(bǔ)捉程序運(yùn)行時(shí)的一些事件。如:載入共享庫(動(dòng)態(tài)鏈接庫)或是C+的異常。設(shè)置捕捉點(diǎn)的格式為:catch當(dāng)event發(fā)生時(shí),停住程序。event可以是下面的內(nèi)容:1、throw一個(gè)C+拋出的異常。(throw為關(guān)鍵字)2、catch一個(gè)C+捕捉到的異常。(catch為關(guān)鍵字)3、exec調(diào)用系統(tǒng)調(diào)用exec時(shí)。(exec為關(guān)鍵字,目前此功能只在HP-UX下有用)4、fork調(diào)用系統(tǒng)調(diào)用fork時(shí)。(fork為關(guān)鍵字,目前此功能只在HP-UX下有用)5、vfork調(diào)用系統(tǒng)調(diào)用vfork時(shí)。(vfork為關(guān)鍵字,目前此功能只在HP-UX下有用)6、load或load載入共享庫(動(dòng)態(tài)鏈接庫)時(shí)。(load為關(guān)鍵字,目前此功能只在HP-UX下有用)7、unload或unload卸載共享庫(動(dòng)態(tài)鏈接庫)時(shí)。(unload為關(guān)鍵字,目前此功能只在HP-UX下有用)tcatch只設(shè)置一次捕捉點(diǎn),當(dāng)程序停住以后,應(yīng)點(diǎn)被自動(dòng)刪除。四、維護(hù)停止點(diǎn)上面說了如何設(shè)置程序的停止點(diǎn),GDB中的停止點(diǎn)也就是上述的三類。在GDB中,如果你覺得已定義好的停止點(diǎn)沒有用了,你可以使用delete、clear、disable、enable這幾個(gè)命令來進(jìn)行維護(hù)。clear清除所有的已定義的停止點(diǎn)。clearclear清除所有設(shè)置在函數(shù)上的停止點(diǎn)。clearclear清除所有設(shè)置在指定行上的停止點(diǎn)。deletebreakpointsrange.刪除指定的斷點(diǎn),breakpoints為斷點(diǎn)號。如果不指定斷點(diǎn)號,則表示刪除所有的斷點(diǎn)。range表示斷點(diǎn)號的范圍(如:3-7)。其簡寫命令為d。比刪除更好的一種方法是disable停止點(diǎn),disable了的停止點(diǎn),GDB不會(huì)刪除,當(dāng)你還需要時(shí),enable即可,就好像回收站一樣。disablebreakpointsrange.disable所指定的停止點(diǎn),breakpoints為停止點(diǎn)號。如果什么都不指定,表示disable所有的停止點(diǎn)。簡寫命令是dis.enablebreakpointsrange.enable所指定的停止點(diǎn),breakpoints為停止點(diǎn)號。enablebreakpointsoncerange.enable所指定的停止點(diǎn)一次,當(dāng)程序停止后,該停止點(diǎn)馬上被GDB自動(dòng)disable。enablebreakpointsdeleterange.enable所指定的停止點(diǎn)一次,當(dāng)程序停止后,該停止點(diǎn)馬上被GDB自動(dòng)刪除。五、停止條件維護(hù)前面在說到設(shè)置斷點(diǎn)時(shí),我們提到過可以設(shè)置一個(gè)條件,當(dāng)條件成立時(shí),程序自動(dòng)停止,這是一個(gè)非常強(qiáng)大的功能,這里,我想專門說說這個(gè)條件的相關(guān)維護(hù)命令。一般來說,為斷點(diǎn)設(shè)置一個(gè)條件,我們使用if關(guān)鍵詞,后面跟其斷點(diǎn)條件。并且,條件設(shè)置好后,我們可以用condition命令來修改斷點(diǎn)的條件。(只有break和watch命令支持if,catch目前暫不支持if)condition修改斷點(diǎn)號為bnum的停止條件為expression。condition清除斷點(diǎn)號為bnum的停止條件。還有一個(gè)比較特殊的維護(hù)命令ignore,你可以指定程序運(yùn)行時(shí),忽略停止條件幾次。ignore表示忽略斷點(diǎn)號為bnum的停止條件count次。六、為停止點(diǎn)設(shè)定運(yùn)行命令我們可以使用GDB提供的command命令來設(shè)置停止點(diǎn)的運(yùn)行命令。也就是說,當(dāng)運(yùn)行的程序在被停止住時(shí),我們可以讓其自動(dòng)運(yùn)行一些別的命令,這很有利行自動(dòng)化調(diào)試。對基于GDB的自動(dòng)化調(diào)試是一個(gè)強(qiáng)大的支持。mand-list.end為斷點(diǎn)號bnum指寫一個(gè)命令列表。當(dāng)程序被該斷點(diǎn)停住時(shí),gdb會(huì)依次運(yùn)行命令列表中的命令。例如:breakfooifx0commandsprintfxis%d,xcontinueend斷點(diǎn)設(shè)置在函數(shù)foo中,斷點(diǎn)條件是x0,如果程序被斷住后,也就是,一旦x的值在foo函數(shù)中大于0,GDB會(huì)自動(dòng)打印出x的值,并繼續(xù)運(yùn)行程序。如果你要清除斷點(diǎn)上的命令序列,那么只要簡單的執(zhí)行一下commands命令,并直接在打個(gè)end就行了。七、斷點(diǎn)菜單在C+中,可能會(huì)重復(fù)出現(xiàn)同一個(gè)名字的函數(shù)若干次(函數(shù)重載),在這種情況下,break不能告訴GDB要停在哪個(gè)函數(shù)的入口。當(dāng)然,你可以使用break也就是把函數(shù)的參數(shù)類型告訴GDB,以指定一個(gè)函數(shù)。否則的話,GDB會(huì)給你列出一個(gè)斷點(diǎn)菜單供你選擇你所需要的斷點(diǎn)。你只要輸入你菜單列表中的編號就可以了。如:(gdb)bString:after0cancel1all2file:String.cc;linenumber:8673file:String.cc;linenumber:8604file:String.cc;linenumber:8755file:String.cc;linenumber:8536file:String.cc;linenumber:8467file:String.cc;linenumber:735246Breakpoint1at0xb26c:fileString.cc,line867.Breakpoint2at0xb344:fileString.cc,line875.Breakpoint3at0xafcc:fileString.cc,line846.Multiplebreakpointswereset.Usethedeletecommandtodeleteunwantedbreakpoints.(gdb)可見,GDB列出了所有after的重載函數(shù),你可以選一下列表編號就行了。0表示放棄設(shè)置斷點(diǎn),1表示所有函數(shù)都設(shè)置斷點(diǎn)。八、恢復(fù)程序運(yùn)行和單步調(diào)試當(dāng)程序被停住了,你可以用continue命令恢復(fù)程序的運(yùn)行直到程序結(jié)束,或下一個(gè)斷點(diǎn)到來。也可以使用step或next命令單步跟蹤程序。continueignore-countcignore-countfgignore-count恢復(fù)程序運(yùn)行,直到程序結(jié)束,或是下一個(gè)斷點(diǎn)到來。ignore-count表示忽略其后的斷點(diǎn)次數(shù)。continue,c,fg三個(gè)命令都是一樣的意思。step單步跟蹤,如果有函數(shù)調(diào)用,他會(huì)進(jìn)入該函數(shù)。進(jìn)入函數(shù)的前提是,此函數(shù)被編譯有debug信息。很像VC等工具中的stepin。后面可以加count也可以不加,不加表示一條條地執(zhí)行,加表示執(zhí)行后面的count條指令,然后再停住。next同樣單步跟蹤,如果有函數(shù)調(diào)用,他不會(huì)進(jìn)入該函數(shù)。很像VC等工具中的stepover。后面可以加count也可以不加,不加表示一條條地執(zhí)行,加表示執(zhí)行后面的count條指令,然后再停住。setstep-modesetstep-modeon打開step-mode模式,于是,在進(jìn)行單步跟蹤時(shí),程序不會(huì)因?yàn)闆]有debug信息而不停住。這個(gè)參數(shù)有很利于查看機(jī)器碼。setstep-modoff關(guān)閉step-mode模式。finish運(yùn)行程序,直到當(dāng)前函數(shù)完成返回。并打印函數(shù)返回時(shí)的堆棧地址和返回值及參數(shù)值等信息。until或u當(dāng)你厭倦了在一個(gè)循環(huán)體內(nèi)單步跟蹤時(shí),這個(gè)命令可以運(yùn)行程序直到退出循環(huán)體。stepi或sinexti或ni單步跟蹤一條機(jī)器指令!一條程序代碼有可能由數(shù)條機(jī)器指令完成,stepi和nexti可以單步執(zhí)行機(jī)器指令。與之一樣有相同功能的命令是“display/i$pc”,當(dāng)運(yùn)行完這個(gè)命令后,單步跟蹤會(huì)在打出程序代碼的同時(shí)打出機(jī)器指令(也就是匯編代碼)九、信號(Signals)信號是一種軟中斷,是一種處理異步事件的方法。一般來說,操作系統(tǒng)都支持許多信號。尤其是UNIX,比較重要應(yīng)用程序一般都會(huì)處理信號。UNIX定義了許多信號,比如SIGINT表示中斷字符信號,也就是Ctrl+C的信號,SIGBUS表示硬件故障的信號;SIGCHLD表示子進(jìn)程狀態(tài)改變信號;SIGKILL表示終止程序運(yùn)行的信號,等等。信號量編程是UNIX下非常重要的一種技術(shù)。GDB有能力在你調(diào)試程序的時(shí)候處理任何一種信號,你可以告訴GDB需要處理哪一種信號。你可以要求GDB收到你所指定的信號時(shí),馬上停住正在運(yùn)行的程序,以供你進(jìn)行調(diào)試。你可以用GDB的handle命令來完成這一功能。handle在GDB中定義一個(gè)信號處理。信號可以以SIG開頭或不以SIG開頭,可以用定義一個(gè)要處理信號的范圍(如:SIGIO-SIGKILL,表示處理從SIGIO信號到SIGKILL的信號,其中包括SIGIO,SIGIOT,SIGKILL三個(gè)信號),也可以使用關(guān)鍵字all來標(biāo)明要處理所有的信號。一旦被調(diào)試的程序接收到信號,運(yùn)行程序馬上會(huì)被GDB停住,以供調(diào)試。其可以是以下幾種關(guān)鍵字的一個(gè)或多個(gè)。nostop當(dāng)被調(diào)試的程序收到信號時(shí),GDB不會(huì)停住程序的運(yùn)行,但會(huì)打出消息告訴你收到這種信號。stop當(dāng)被調(diào)試的程序收到信號時(shí),GDB會(huì)停住你的程序。print當(dāng)被調(diào)試的程序收到信號時(shí),GDB會(huì)顯示出一條信息。noprint當(dāng)被調(diào)試的程序收到信號時(shí),GDB不會(huì)告訴你收到信號的信息。passnoignore當(dāng)被調(diào)試的程序收到信號時(shí),GDB不處理信號。這表示,GDB會(huì)把這個(gè)信號交給被調(diào)試程序會(huì)處理。nopassignore當(dāng)被調(diào)試的程序收到信號時(shí),GDB不會(huì)讓被調(diào)試程序來處理這個(gè)信號。infosignalsinfohandle查看有哪些信號在被GDB檢測中。十、線程(ThreadStops)如果你程序是多線程的話,你可以定義你的斷點(diǎn)是否在所有的線程上,或是在某個(gè)特定的線程。GDB很容易幫你完成這一工作。breakthreadbreakthreadif.linespec指定了斷點(diǎn)設(shè)置在的源程序的行號。threadno指定了線程的ID,注意,這個(gè)ID是GDB分配的,你可以通過“infothreads”命令來查看正在運(yùn)行程序中的線程信息。如果你不指定thread則表示你的斷點(diǎn)設(shè)在所有線程上面。你還可以為某線程指定斷點(diǎn)條件。如:(gdb)breakfrik.c:13thread28ifbartablim當(dāng)你的程序被GDB停住時(shí),所有的運(yùn)行線程都會(huì)被停住。這方便你你查看運(yùn)行程序的總體情況。而在你恢復(fù)程序運(yùn)行時(shí),所有的線程也會(huì)被恢復(fù)運(yùn)行。那怕是主進(jìn)程在被單步調(diào)試時(shí)。查看棧信息當(dāng)程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。當(dāng)你的程序調(diào)用了一個(gè)函數(shù),函數(shù)的地址,函數(shù)參數(shù),函數(shù)內(nèi)的局部變量都會(huì)被壓入“?!保⊿tack)中。你可以用GDB命令來查看當(dāng)前的棧中的信息。下面是一些查看函數(shù)調(diào)用棧信息的GDB命令:backtracebt打印當(dāng)前的函數(shù)調(diào)用棧的所有信息。如:(gdb)bt#0func(n=250)attst.c:6#10x08048524inmain(argc=1,argv=0xbffff674)attst.c:30#20x400409edin_libc_start_main()from/lib/libc.so.6從上可以看出函數(shù)的調(diào)用棧信息:_libc_start_main-main()-func()backtracebtn是一個(gè)正整數(shù),表示只打印棧頂上n層的棧信息。backtracebt-n表一個(gè)負(fù)整數(shù),表示只打印棧底下n層的棧信息。如果你要查看某一層的信息,你需要在切換當(dāng)前的棧,一般來說,程序停止時(shí),最頂層的棧就是當(dāng)前棧,如果你要查看棧下面層的詳細(xì)信息,首先要做的是切換當(dāng)前棧。framefn是一個(gè)從0開始的整數(shù),是棧中的層編號。比如:frame0,表示棧頂,frame1,表示棧的第二層。up表示向棧的上面移動(dòng)n層,可以不打n,表示向上移動(dòng)一層。down表示向棧的下面移動(dòng)n層,可以不打n,表示向下移動(dòng)一層。上面的命令,都會(huì)打印出移動(dòng)到的棧層的信息。如果你不想讓其打出信息。你可以使用這三個(gè)命令:select-frame對應(yīng)于frame命令。up-silently對應(yīng)于up命令。down-silently對應(yīng)于down命令。查看當(dāng)前棧層的信息,你可以用以下GDB命令:frame或f會(huì)打印出這些信息:棧的層編號,當(dāng)前的函數(shù)名,函數(shù)參數(shù)值,函數(shù)所在文件及行號,函數(shù)執(zhí)行到的語句。infoframeinfof這個(gè)命令會(huì)打印出更為詳細(xì)的當(dāng)前棧層的信息,只不過,大多數(shù)都是運(yùn)行時(shí)的內(nèi)內(nèi)地址。比如:函數(shù)地址,調(diào)用函數(shù)的地址,被調(diào)用函數(shù)的地址,目前的函數(shù)是由什么樣的程序語言寫成的、函數(shù)參數(shù)地址及值、局部變量的地址等等。如:(gdb)infofStacklevel0,frameat0xbffff5d4:eip=0x804845dinfunc(tst.c:6);savedeip0x8048524calledbyframeat0xbffff60csourcelanguagec.Arglistat0xbffff5d4,args:n=250Localsat0xbffff5d4,Previousframesspis0x0Savedregisters:ebpat0xbffff5d4,eipat0xbffff5d8infoargs打印出當(dāng)前函數(shù)的參數(shù)名及其值。infolocals打印出當(dāng)前函數(shù)中所有局部變量及其值。infocatch打印出當(dāng)前的函數(shù)中的異常處理信息。一、顯示源代碼GDB可以打印出所調(diào)試程序的源代碼,當(dāng)然,在程序編譯時(shí)一定要加上-g的參數(shù),把源程序信息編譯到執(zhí)行文件中。不然就看不到源程序了。當(dāng)程序停下來以后,GDB會(huì)報(bào)告程序停在了那個(gè)文件的第幾行上。你可以用list命令來打印程序的源代碼。還是來看一看查看源代碼的GDB命令吧。list顯示程序第linenum行的周圍的源程序。list顯示函數(shù)名為function的函數(shù)的源程序。list顯示當(dāng)前行后面的源程序。list-顯示當(dāng)前行前面的源程序。一、顯示源代碼GDB可以打印出所調(diào)試程序的源代碼,當(dāng)然,在程序編譯時(shí)一定要加上-g的參數(shù),把源程序信息編譯到執(zhí)行文件中。不然就看不到源程序了。當(dāng)程序停下來以后,GDB會(huì)報(bào)告程序停在了那個(gè)文件的第幾行上。你可以用list命令來打印程序的源代碼。還是來看一看查看源代碼的GDB命令吧。list顯示程序第linenum行的周圍的源程序。list顯示函數(shù)名為function的函數(shù)的源程序。list顯示當(dāng)前行后面的源程序。list-顯示當(dāng)前行前面的源程序。一般是打印當(dāng)前行的上5行和下5行,如果顯示函數(shù)是是上2行下8行,默認(rèn)是10行,當(dāng)然,你也可以定制顯示的范圍,使用下面命令可以設(shè)置一次顯示源程序的行數(shù)。setlistsize設(shè)置一次顯示源代碼的行數(shù)。showlistsize查看當(dāng)前l(fā)istsize的設(shè)置。list命令還有下面的用法:list,顯示從first行到last行之間的源代碼。list,顯示從當(dāng)前行到last行之間的源代碼。list+往后顯示源代碼。一般來說在list后面可以跟以下這們的參數(shù):行號。當(dāng)前行號的正偏移量。當(dāng)前行號的負(fù)偏移量。哪個(gè)文件的哪一行。函數(shù)名。哪個(gè)文件中的哪個(gè)函數(shù)。程序運(yùn)行時(shí)的語句在內(nèi)存中的地址。二、搜索源代碼不僅如此,GDB還提供了源代碼搜索的命令:forward-searchsearch向前面搜索。reverse-search全部搜索。其中,就是正則表達(dá)式,也主一個(gè)字符串的匹配模式,關(guān)于正則表達(dá)式,我就不在這里講了,還請各位查看相關(guān)資料。三、指定源文件的路徑某些時(shí)候,用-g編譯過后的執(zhí)行程序中只是包括了源文件的名字,沒有路徑名。GDB提供了可以讓你指定源文件的路徑的命令,以便GDB進(jìn)行搜索。directorydir加一個(gè)源文件路徑到當(dāng)前路徑的前面。如果你要指定多個(gè)路徑,UNIX下你可以使用“:”,Windows下你可以使用“;”。directory清除所有的自定義的源文件搜索路徑信息。showdirectories顯示定義了的源文件搜索路徑。四、源代碼的內(nèi)存你可以使用infoline命令來查看源代碼在內(nèi)存中的地址。infoline后面可以跟“行號”,“函數(shù)名”,“文件名:行號”,“文件名:函數(shù)名”,這個(gè)命令會(huì)打印出所指定的源碼在運(yùn)行時(shí)的內(nèi)存地址,如:(gdb)infolinetst.c:funcLine5oftst.cstartsataddress0x8048456andendsat0x804845d.還有一個(gè)命令(disassemble)你可以查看源程序的當(dāng)前執(zhí)行時(shí)的機(jī)器碼,這個(gè)命令會(huì)把目前內(nèi)存中的指令dump出來。如下面的示例表示查看函數(shù)func的匯編代碼。(gdb)disassemblefuncDumpofassemblercodeforfunctionfunc:0x8048450:push%ebp0x8048451:mov%esp,%ebp0x8048453:sub$0x18,%esp0x8048456:movl$0x0,0xfffffffc(%ebp)0x804845d:movl$0x1,0xfffffff8(%ebp)0x8048464:mov0xfffffff8(%ebp),%eax0x8048467:cmp0x8(%ebp),%eax0x804846a:jle0x80484700x804846c:jmp0x80484800x804846e:mov%esi,%esi0x8048470:mov0xfffffff8(%ebp),%eax0x8048473:add%eax,0xfffffffc(%ebp)0x8048476:incl0xfffffff8(%ebp)0x8048479:jmp0x80484640x804847b:nop0x804847c:lea0x0(%esi,1),%esi0x8048480:mov0xfffffffc(%ebp),%edx0x8048483:mov%edx,%eax0x8048485:jmp0x80484870x8048487:mov%ebp,%esp0x8048489:pop%ebp0x804848a:retEndofassemblerdump.查看運(yùn)行時(shí)數(shù)據(jù)在你調(diào)試程序時(shí),當(dāng)程序被停住時(shí),你可以使用print命令(簡寫命令為p),或是同義命令inspect來查看當(dāng)前程序的運(yùn)行數(shù)據(jù)。print命令的格式是:printprint/是表達(dá)式,是你所調(diào)試的程序的語言的表達(dá)式(GDB可以調(diào)試多種編程語言),是輸出的格式,比如,如果要把表達(dá)式按16進(jìn)制的格式輸出,那么就是/x。一、表達(dá)式print和許多GDB的命令一樣,可以接受一個(gè)表達(dá)式,GDB會(huì)根據(jù)當(dāng)前的程序運(yùn)行的數(shù)據(jù)來計(jì)算這個(gè)表達(dá)式,既然是表達(dá)式,那么就可以是當(dāng)前程序運(yùn)行中的const常量、變量、函數(shù)等內(nèi)容。可惜的是GDB不能使用你在程序中所定義的宏。表達(dá)式的語法應(yīng)該是當(dāng)前所調(diào)試的語言的語法,由于C/C+是一種大眾型的語言,所以,本文中的例子都是關(guān)于C/C+的。(而關(guān)于用GDB調(diào)試其它語言的章節(jié),我將在后面介紹)在表達(dá)式中,有幾種GDB所支持的操作符,它們可以用在任何一種語言中。是一個(gè)和數(shù)組有關(guān)的操作符,在后面會(huì)有更詳細(xì)的說明。:指定一個(gè)在文件或是一個(gè)函數(shù)中的變量。表示一個(gè)指向內(nèi)存地址的類型為type的一個(gè)對象。二、程序變量在GDB中,你可以隨時(shí)查看以下三種變量的值:1、全局變量(所有文件可見的)2、靜態(tài)全局變量(當(dāng)前文件可見的)3、局部變量(當(dāng)前Scope可見的)如果你的局部變量和全局變量發(fā)生沖突(也就是重名),一般情況下是局部變量會(huì)隱藏全局變量,也就是說,如果一個(gè)全局變量和一個(gè)函數(shù)中的局部變量同名時(shí),如果當(dāng)前停止點(diǎn)在函數(shù)中,用print顯示出的變量的值會(huì)是函數(shù)中的局部變量的值。如果此時(shí)你想查看全局變量的值時(shí),你可以使用“:”操作符:file:variablefunction:variable可以通過這種形式指定你所想查看的變量,是哪個(gè)文件中的或是哪個(gè)函數(shù)中的。例如,查看文件f2.c中的全局變量x的值:gdb)pf2.c:x當(dāng)然,“:”操作符會(huì)和C+中的發(fā)生沖突,GDB能自動(dòng)識別“:”是否C+的操作符,所以你不必?fù)?dān)心在調(diào)試C+程序時(shí)會(huì)出現(xiàn)異常。另外,需要注意的是,如果你的程序編譯時(shí)開啟了優(yōu)化選項(xiàng),那么在用GDB調(diào)試被優(yōu)化過的程序時(shí),可能會(huì)發(fā)生某些變量不能訪問,或是取值錯(cuò)誤碼的情

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論