gdb调试器(三)
? ? ? ? File/file 裝入想要調(diào)試的可執(zhí)行文件???? run(r) 執(zhí)行當(dāng)前被調(diào)試的程序? ? ?kill(k) 終止正在調(diào)試的程序???? ??quit(q) ?退出gdb? ?shell 使用戶不離開gdb就可以執(zhí)行Linux的shell命令? ? ? ? ? ? ? ? ? backtrace(bt) 回溯跟蹤(當(dāng)對代碼進(jìn)行調(diào)試時(shí),run后出現(xiàn)錯(cuò)誤,則可以使用bt命令查出詳細(xì)的錯(cuò)誤信息? ? ? ? ?frame n? 定位到發(fā)生錯(cuò)誤的代碼段,n為backtrace命令的輸出結(jié)果中的行號(hào)(位于行首)。? ?
(1)?設(shè)置斷點(diǎn)(break) ?
break <function>? ????????在進(jìn)入指定函數(shù)時(shí)被停住。C++可以使用class::function或function<type,type>格式來指定函數(shù)名。 //在該處停止(斷點(diǎn)),該處不執(zhí)行,下同
break <linenum> 在指定行號(hào)停住
break filename:linenum?? 在源文件filename的linenum行處停止
break filename:function?? 在源文件filename的function函數(shù)的入口處停止
break??? 沒有參數(shù),表示在下一條指令處停止
break *address 在程序運(yùn)行的內(nèi)存地址處停止
break與step結(jié)合使用時(shí),step(s)確認(rèn)后,執(zhí)行上一次顯示的未執(zhí)行命令,并且顯示出將要執(zhí)行的下一行程序。使用單步調(diào)試命令step來跟蹤程序,它一次只執(zhí)行程序中的一行代碼。
info break(i b)??命令? 可以顯示所有斷點(diǎn)的信息
(2)?查看運(yùn)行時(shí)的數(shù)據(jù)
在調(diào)試程序的過程中,需要查看程序中某些表達(dá)式或變量的值,以判斷程序運(yùn)行是否正確。
- ? ? ? ? print命令(p)
在調(diào)試程序時(shí),當(dāng)程序被停住時(shí)(如在斷點(diǎn)處),可以使用print(p)命令或其同義命令inspect來查看當(dāng)前程序的運(yùn)行數(shù)據(jù)。
print <expr>? //輸出表達(dá)式的值
print /<f> <expr>? //按某種格式輸出表達(dá)式的值,如/x 則為16進(jìn)制
(gdb) print n1
$1 = 4
(gdb) inspect n1
$2 = 4
(gdb) print n1
$3 = 4
(gdb) print n2
$4 = 5
(gdb) print $2
$5 = 4???? //$2的值
(gdb) print $?? //$5的值
$6 = 4
(gdb) print $ $? //$5的值? ? 注意之間沒有空格? 這是防止CSDN編輯器轉(zhuǎn)義而加上的空格
$7 = 4
(gdb) print $ $6 //$4的值
$8 = 5
每一個(gè)print都會(huì)被gdb記錄下來,并且會(huì)以$1、$2、$3······這樣的方式為每一個(gè)print命令編號(hào)。于是,可以使用這個(gè)編號(hào)訪問以前的表達(dá)式。
另外要注意print命令的表達(dá)式中兩個(gè)具有特殊意義的符號(hào):$、$ $。print $表示顯示當(dāng)前序號(hào)的前一個(gè)序號(hào)的值;$ $表示給定序號(hào)的前兩個(gè)序號(hào),如果未給定序號(hào),則默認(rèn)當(dāng)前序號(hào)為給定序號(hào)。
另外,info local命令可以顯示當(dāng)前本地的所有變量的值。
print命令的功能除了打印表達(dá)式或變量的值以外,還有對變量進(jìn)行賦值和打印內(nèi)存中某個(gè)變量開始的一段區(qū)域的內(nèi)容。
- ? ? ? ? gdb的數(shù)據(jù)輸出格式
x 十六進(jìn)制格式???? d 十進(jìn)制格式?? u 十六進(jìn)制格式無符號(hào)整型
o 八進(jìn)制格式?????? t 二進(jìn)制格式??? a 十六進(jìn)制格式(等價(jià)x)
c ?ASCII字符格式???? f 浮點(diǎn)數(shù)格式???? s字符串格式?? i指令地址(指令文件)
p /x n1? ? //以十六進(jìn)制格式顯示n1的值
- ? ? ? ? 自動(dòng)顯示命令display
當(dāng)程序停住時(shí),或單步跟蹤時(shí),這些變量會(huì)自動(dòng)顯示。
display <expr>??????? display /<f> <expr>???
display /<f> <addr>? addr表示內(nèi)存地址
display /i $pc? $pc為gdb的環(huán)境變量,表示指令的地址,/i則表示輸出格式為機(jī)器指令碼,也就是匯編。該句指令表示,當(dāng)程序停下后,就會(huì)出現(xiàn)源代碼和機(jī)器指令碼相對應(yīng)的情形。 即輸出當(dāng)前指令的地址(程序運(yùn)行到當(dāng)前處),以機(jī)器指令碼的格式輸出,從而出現(xiàn)源代碼和機(jī)器指令碼(匯編代碼)相對應(yīng)的情形。
- ? ? ? ? 查看內(nèi)存examine(x)
examine(簡寫為x)指令可以查看內(nèi)存地址中的值,格式:
x /<n/f/u> <addr>
n、f、u為可選的參數(shù),可以獨(dú)立使用,也可以聯(lián)合使用。
n為一個(gè)正整數(shù),表示顯示內(nèi)存的長度,即從當(dāng)前地址向后顯示幾個(gè)地址的內(nèi)容。
f表示顯示的格式(即地址所指內(nèi)容以什么樣的格式顯示出),s為字符串,如果所指的內(nèi)容為指令地址,則為i。
u表示從當(dāng)前地址往后請求的字節(jié)數(shù),如果不指定則默認(rèn)為4個(gè)Bytes。u參數(shù)可以用下面的字符代替:b表示單字節(jié),h表示雙字節(jié),w表示四字節(jié),g表示八字節(jié)。
<addr>表示一個(gè)內(nèi)存地址
x /4uh 0x48723? // 從內(nèi)存地址0x48723讀取內(nèi)容,h表示以雙字節(jié)為1個(gè)單位,4表示4個(gè)單位,u表示按16進(jìn)制顯示。
- ? ? ? ? gdb的環(huán)境變量
可以在gdb的調(diào)試環(huán)境中定義自己的變量,用來保存一些調(diào)試程序中的運(yùn)行數(shù)據(jù)。set命令用于定義gdb的環(huán)境變量,gdb的環(huán)境變量與Linux一樣,都是以$起始。
set $foo=*object_ptr
第一次使用環(huán)境變量時(shí),需要?jiǎng)?chuàng)建這個(gè)變量(set),以后使用直接對其賦值即可,環(huán)境變量沒有類型,可以給環(huán)境變量定義任意的類型,包括結(jié)構(gòu)體和數(shù)組。
在gdb的調(diào)試過程中,show convenience 命令用于查看當(dāng)前設(shè)置的所有環(huán)境變量
- ? ? ? ? 查看寄存器
在調(diào)試程序的過程中,有時(shí)需要查看某些寄存器中的值。寄存器存放了程序運(yùn)行時(shí)的數(shù)據(jù),比如程序當(dāng)前運(yùn)行時(shí)的指令地址(IP),程序的當(dāng)前堆棧地址(SP)等。可以使用info命令來查看寄存器中的值。
info registers //查看寄存器的情況(不包括浮點(diǎn)寄存器)
info all-registers //查看所有寄存器的情況(包括浮點(diǎn)寄存器)
info registers<name1,name2,······>? //查看指定寄存器的情況(name表示寄存器名)
也可以使用print命令來訪問寄存器的情況,只需要在寄存器名字前加一個(gè)$就可以了,如:print $ip。
- ? ? ? ? 查看源程序list(l)
在程序的調(diào)試過程中,有時(shí)需要查看源程序的內(nèi)容,以及源代碼在內(nèi)存中的情況。用list命令可以顯示程序的源代碼。
list linenum 顯示程序第linenum行周圍的源程序
list filename:linenum? 顯示某個(gè).c文件中的第linenum行周圍的源程序(對于多個(gè)源文件的編譯)
list function 顯示函數(shù)名為function的函數(shù)的源程序
list filename:function
list 顯示當(dāng)前行后面的源程序
list - 顯示當(dāng)前行前面的源程序
list first,last 顯示從first行到last行之間的源代碼
list ,last 顯示從當(dāng)前行到last行之間的源代碼
可以使用info line命令來查看源代碼在內(nèi)存中的地址,info line命令后面也可以跟行號(hào)、函數(shù)名、文件名:行號(hào)、文件名:函數(shù)名等,從而顯示指定的源代碼在內(nèi)存中的地址。如要顯示zsx.c源文件中calculate( )函數(shù)在內(nèi)存中的地址:
info line zsx.c:calculate?
(3) 改變程序的執(zhí)行
修改變量的值。print命令還可以修改被調(diào)試程序中運(yùn)行時(shí)的變量值。如:
print x=9
跳轉(zhuǎn)執(zhí)行。可以修改程序的執(zhí)行順序,讓程序執(zhí)行隨意跳躍。
jump <linespec>? <linespec>可以是文件的行號(hào),可以是file:linenum格式,表示下一條運(yùn)行語句從哪里開始。
jump <address>? <address>是代碼行的內(nèi)存地址
注意jump命令不會(huì)改變當(dāng)前的程序棧中的內(nèi)容。
程序運(yùn)行時(shí),有一個(gè)寄存器用于保存當(dāng)前代碼所在的內(nèi)存地址,所以jump命令也就是改變了這個(gè)寄存器中的值。可以使用set $pc來更改跳轉(zhuǎn)執(zhí)行的地址:set $pc=0x485。
(4) 具體事例
15?????????? for (i = 0; i < len; ++i)
(gdb) b 15 if i==5
Breakpoint 1 at 0x4008d3: file ../src/main.c, line 15.
(gdb) b 27
Breakpoint 2 at 0x400936: file ../src/main.c, line 27.
(gdb) i b
Num? ???Type?????????? Disp Enb? ? ? ? ? ? ? ?Address? ? ? ? ? ? ? ? ? ? ? What
1?????? breakpoint???? keep y? ? ? ? 0x00000000004008d3? in main at ../src/main.c:15
? ? ? ? ? ? ? ? ? ? ? ? ? stop only if i==5
2?????? breakpoint???? keep y? ? ? ? 0x0000000000400936? in main at ../src/main.c:27
//斷點(diǎn)編號(hào)(id) 斷點(diǎn)類型??? 斷點(diǎn)是否可用(y表示可用,n表示不可用) 斷點(diǎn)地址? 斷點(diǎn)的詳細(xì)信息
(5) 總結(jié)(重點(diǎn)內(nèi)容)
運(yùn)行程序:start(開始運(yùn)行,只執(zhí)行一步就停住);run(開始運(yùn)行,在斷點(diǎn)處停住);continue(c)繼續(xù)運(yùn)行,到下一個(gè)斷點(diǎn)處停止,step(s)單步執(zhí)行,進(jìn)入函數(shù)內(nèi)部;next(n)單步執(zhí)行,不進(jìn)入函數(shù)內(nèi)部;u跳出循環(huán)體,執(zhí)行循環(huán)體后面的第一個(gè)語句。
set var i=10? //將變量i的值設(shè)為10,比如在一個(gè)循環(huán)體中,i為控制變量,當(dāng)單步執(zhí)行時(shí),i依次增加,如果想讓變量i循環(huán)到10時(shí),才停住,則可以:set var i = 10。
gdb調(diào)試:
????????????? 1. 啟動(dòng)gdb
??????????????????????????? start -- 只執(zhí)行一步
?????????????????????????????????? n -- next
?????????????????????????????????? s -- step(單步) -- 可以進(jìn)入到函數(shù)體內(nèi)部
?????????????????????????????????? c - continue -- 直接停在斷點(diǎn)的位置
????????????? 2. 查看代碼:
??????????????????????????? l -- list
??????????????????????????? l 10(或者函數(shù)名)
??????????????????????????? l filename:行號(hào)(或者函數(shù)名)
????????????? 3. 設(shè)置斷點(diǎn):
??????????????????????????? 設(shè)置當(dāng)前文件斷點(diǎn):
?????????????????????????????????? b -- break
?????????????????????????????????? b 10(或函數(shù)名)
??????????????????????????? 設(shè)置指定文件斷點(diǎn):
??????????????????????????? ??? b fileName:行號(hào)(或函數(shù)名)
??????????????????????????? 設(shè)置條件斷點(diǎn):
?????????????????????????????????? b 10 if value==19
??????????????????????????? 刪除斷點(diǎn):
?????????????????????????????????? d 斷點(diǎn)編號(hào)
??????????????????????????? ??? 獲取編號(hào):i b
????????????? 4. 查看設(shè)置的斷點(diǎn)
??????????????????? info break?? i b
????????????? 5. 開始 執(zhí)行g(shù)db調(diào)試
??????????????????????????? 執(zhí)行一步操作: ?start
?????????????????????????????????? 繼續(xù)執(zhí)行:? n s
??????????????????????????? 執(zhí)行多步, 直接停在斷點(diǎn)處:? continue
????????????? 5. 單步調(diào)試
??????????????????????????? 進(jìn)入函數(shù)體內(nèi)部: s
?????????????????????????????????? 從函數(shù)體內(nèi)部跳出: finish(如果在循環(huán)處有斷點(diǎn), 需要將斷點(diǎn)刪掉)
??????????????????????????? 不進(jìn)入函數(shù)體內(nèi)部:n
??????????????????????????? 退出當(dāng)前循環(huán): u //該退出是指,直接一次性執(zhí)行完該循環(huán)體
????????????? 6. 查看變量的值: p -- print
????????????? 7. 查看變量的類型: ptype 變量名
????????????? 8. 設(shè)置變量的值:? set var 變量名 = 賦值? //注意,同理,不是硬性的
????????????? 9. 設(shè)置追蹤變量
??????????????????????????? display
??????????????????????????? 取消追蹤變量
??????????????????????????? undisplay 編號(hào)
??????????????????????????? 獲取編號(hào): info display
????????????? 10. 退出gdb調(diào)試
?????????????????????????????????? quit
?
總結(jié)
- 上一篇: 输卵管堵塞手术费是多少
- 下一篇: makefile文件的书写规则(make