用GDB调试程序(四)
—————
當(dāng)程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。當(dāng)你的程序調(diào)用了一個函數(shù),函數(shù)的地址,函數(shù)參數(shù),函數(shù)內(nèi)的局部變量都會被壓入“棧”(Stack)中。你可以用GDB命令來查看當(dāng)前的棧中的信息。
下面是一些查看函數(shù)調(diào)用棧信息的GDB命令:
??? backtrace
??? bt
??????? 打印當(dāng)前的函數(shù)調(diào)用棧的所有信息。如:
???????
??????? (gdb) bt
??????? #0? func (n=250) at tst.c:6
??????? #1? 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
??????? #2? 0x400409ed in __libc_start_main () from /lib/libc.so.6
???????
??????? 從上可以看出函數(shù)的調(diào)用棧信息:__libc_start_main --> main() --> func()
???????
???
??? backtrace <n>
??? bt <n>
??????? n是一個正整數(shù),表示只打印棧頂上n層的棧信息。
??? backtrace <-n>
??? bt <-n>
??????? -n表一個負(fù)整數(shù),表示只打印棧底下n層的棧信息。
???????
如果你要查看某一層的信息,你需要在切換當(dāng)前的棧,一般來說,程序停止時,最頂層的棧就是當(dāng)前棧,如果你要查看棧下面層的詳細(xì)信息,首先要做的是切換當(dāng)前棧。
??? frame <n>
??? f <n>
??????? n是一個從0開始的整數(shù),是棧中的層編號。比如:frame 0,表示棧頂,frame 1,表示棧的第二層。
???
??? up <n>
??????? 表示向棧的上面移動n層,可以不打n,表示向上移動一層。
???????
??? down <n>
??????? 表示向棧的下面移動n層,可以不打n,表示向下移動一層。
???????
??? 上面的命令,都會打印出移動到的棧層的信息。如果你不想讓其打出信息。你可以使用這三個命令:
???
??????????? select-frame <n> 對應(yīng)于 frame 命令。
??????????? up-silently <n> 對應(yīng)于 up 命令。
??????????? down-silently <n> 對應(yīng)于 down 命令。
???
查看當(dāng)前棧層的信息,你可以用以下GDB命令:
??? frame 或 f
??????? 會打印出這些信息:棧的層編號,當(dāng)前的函數(shù)名,函數(shù)參數(shù)值,函數(shù)所在文件及行號,函數(shù)執(zhí)行到的語句。
???
??? info frame
??? info f
??????? 這個命令會打印出更為詳細(xì)的當(dāng)前棧層的信息,只不過,大多數(shù)都是運行時的內(nèi)內(nèi)地址。比如:函數(shù)地址,調(diào)用函數(shù)的地址,被調(diào)用函數(shù)的地址,目前的函數(shù)是由什么樣的程序語言寫成的、函數(shù)參數(shù)地址及值、局部變量的地址等等。如:
??????????? (gdb) info f
??????????? Stack level 0, frame at 0xbffff5d4:
???????????? eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
???????????? called by frame at 0xbffff60c
???????????? source language c.
???????????? Arglist at 0xbffff5d4, args: n=250
???????????? Locals at 0xbffff5d4, Previous frame's sp is 0x0
???????????? Saved registers:
????????????? ebp at 0xbffff5d4, eip at 0xbffff5d8
?????????????
???? info args
??????? 打印出當(dāng)前函數(shù)的參數(shù)名及其值。
????
???? info locals
??????? 打印出當(dāng)前函數(shù)中所有局部變量及其值。
???????
???? info catch
??????? 打印出當(dāng)前的函數(shù)中的異常處理信息。
???????
???????
???????
???????
查看源程序
—————
一、顯示源代碼
??? GDB 可以打印出所調(diào)試程序的源代碼,當(dāng)然,在程序編譯時一定要加上-g的參數(shù),把源程序信息編譯到執(zhí)行文件中。不然就看不到源程序了。當(dāng)程序停下來以后,GDB會報告程序停在了那個文件的第幾行上。你可以用list命令來打印程序的源代碼。還是來看一看查看源代碼的GDB命令吧。
???
??? list <linenum>
??????? 顯示程序第linenum行的周圍的源程序。
???
??? list <function>
??????? 顯示函數(shù)名為function的函數(shù)的源程序。
???????
??? list
??????? 顯示當(dāng)前行后面的源程序。
???
??? list -
??????? 顯示當(dāng)前行前面的源程序。
一般是打印當(dāng)前行的上5行和下5行,如果顯示函數(shù)是是上2行下8行,默認(rèn)是10行,當(dāng)然,你也可以定制顯示的范圍,使用下面命令可以設(shè)置一次顯示源程序的行數(shù)。
??? set listsize <count>
??????? 設(shè)置一次顯示源代碼的行數(shù)。
???????
??? show listsize
??????? 查看當(dāng)前l(fā)istsize的設(shè)置。
???????
list命令還有下面的用法:
??? list <first>, <last>
??????? 顯示從first行到last行之間的源代碼。
???
??? list , <last>
??????? 顯示從當(dāng)前行到last行之間的源代碼。
???????
??? list +
??????? 往后顯示源代碼。
???????
一般來說在list后面可以跟以下這們的參數(shù):
??? <linenum>?? 行號。
??? <+offset>?? 當(dāng)前行號的正偏移量。
??? <-offset>?? 當(dāng)前行號的負(fù)偏移量。
??? <filename:linenum>? 哪個文件的哪一行。
??? <function>? 函數(shù)名。
??? <filename:function> 哪個文件中的哪個函數(shù)。
??? <*address>? 程序運行時的語句在內(nèi)存中的地址。
???
二、搜索源代碼
不僅如此,GDB還提供了源代碼搜索的命令:
??? forward-search <regexp>
??? search <regexp>
??????? 向前面搜索。
??? reverse-search <regexp>
??????? 全部搜索。
???????
其中,<regexp>就是正則表達(dá)式,也主一個字符串的匹配模式,關(guān)于正則表達(dá)式,我就不在這里講了,還請各位查看相關(guān)資料。
三、指定源文件的路徑
某些時候,用-g編譯過后的執(zhí)行程序中只是包括了源文件的名字,沒有路徑名。GDB提供了可以讓你指定源文件的路徑的命令,以便GDB進(jìn)行搜索。
??? directory <dirname ... >
??? dir <dirname ... >
??????? 加一個源文件路徑到當(dāng)前路徑的前面。如果你要指定多個路徑,UNIX下你可以使用“:”,Windows下你可以使用“;”。
??? directory
??????? 清除所有的自定義的源文件搜索路徑信息。
???
??? show directories
??????? 顯示定義了的源文件搜索路徑。
???????
四、源代碼的內(nèi)存
你可以使用info line命令來查看源代碼在內(nèi)存中的地址。info line后面可以跟“行號”,“函數(shù)名”,“文件名:行號”,“文件名:函數(shù)名”,這個命令會打印出所指定的源碼在運行時的內(nèi)存地址,如:
??????? (gdb) info line tst.c:func
??????? Line 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <func+13>.
還有一個命令(disassemble)你可以查看源程序的當(dāng)前執(zhí)行時的機(jī)器碼,這個命令會把目前內(nèi)存中的指令dump出來。如下面的示例表示查看函數(shù)func的匯編代碼。
??????? (gdb) disassemble func
??????? Dump of assembler code for function func:
??????? 0x8048450 <func>:?????? push?? %ebp
??????? 0x8048451 <func+1>:???? mov??? %esp,%ebp
??????? 0x8048453 <func+3>:???? sub??? $0x18,%esp
??????? 0x8048456 <func+6>:???? movl?? $0x0,0xfffffffc(%ebp)
??????? 0x804845d <func+13>:??? movl?? $0x1,0xfffffff8(%ebp)
??????? 0x8048464 <func+20>:??? mov??? 0xfffffff8(%ebp),%eax
??????? 0x8048467 <func+23>:??? cmp??? 0x8(%ebp),%eax
??????? 0x804846a <func+26>:??? jle??? 0x8048470 <func+32>
??????? 0x804846c <func+28>:??? jmp??? 0x8048480 <func+48>
??????? 0x804846e <func+30>:??? mov??? %esi,%esi
??????? 0x8048470 <func+32>:??? mov??? 0xfffffff8(%ebp),%eax
??????? 0x8048473 <func+35>:??? add??? %eax,0xfffffffc(%ebp)
??????? 0x8048476 <func+38>:??? incl?? 0xfffffff8(%ebp)
??????? 0x8048479 <func+41>:??? jmp??? 0x8048464 <func+20>
??????? 0x804847b <func+43>:??? nop
??????? 0x804847c <func+44>:??? lea??? 0x0(%esi,1),%esi
??????? 0x8048480 <func+48>:??? mov??? 0xfffffffc(%ebp),%edx
??????? 0x8048483 <func+51>:??? mov??? %edx,%eax
??????? 0x8048485 <func+53>:??? jmp??? 0x8048487 <func+55>
??????? 0x8048487 <func+55>:??? mov??? %ebp,%esp
??????? 0x8048489 <func+57>:??? pop??? %ebp
??????? 0x804848a <func+58>:??? ret
??????? End of assembler dump.
出處:http://blog.csdn.net/haoel/article/details/2882
總結(jié)
以上是生活随笔為你收集整理的用GDB调试程序(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用GDB调试程序(三)
- 下一篇: 用GDB调试程序(六)