日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
5個鮮為人知GNU調(diào)試器(GDB)技巧

了解如何使用 gdb 的一些鮮為人知的功能來檢查和修復(fù)代碼。

成都創(chuàng)新互聯(lián)公司是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來公司不斷探索創(chuàng)新,始終堅持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過去的十余年時間我們累計服務(wù)了上千家以及全國政企客戶,如航空箱等企業(yè)單位,完善的項目管理流程,嚴(yán)格把控項目進(jìn)度與質(zhì)量監(jiān)控加上過硬的技術(shù)實力獲得客戶的一致贊美。

GNU 調(diào)試器(gdb)是一種寶貴的工具,可用于在開發(fā)程序時檢查正在運(yùn)行的進(jìn)程并解決問題。

你可以在特定位置(按函數(shù)名稱、行號等)設(shè)置斷點、啟用和禁用這些斷點、顯示和更改變量值,并執(zhí)行所有調(diào)試器希望執(zhí)行的所有標(biāo)準(zhǔn)操作。但是它還有許多其它你可能沒有嘗試過的功能。這里有五個你可以嘗試一下。

條件斷點

設(shè)置斷點是學(xué)習(xí)使用 GNU 調(diào)試器的第一步。程序在達(dá)到斷點時停止,你可以運(yùn)行 gdb 的命令對其進(jìn)行檢查或更改變量,然后再允許該程序繼續(xù)運(yùn)行。

例如,你可能知道一個經(jīng)常調(diào)用的函數(shù)有時會崩潰,但僅當(dāng)它獲得某個參數(shù)值時才會崩潰。你可以在該函數(shù)的開始處設(shè)置一個斷點并運(yùn)行程序。每次碰到該斷點時都會顯示函數(shù)參數(shù),并且如果未提供觸發(fā)崩潰的參數(shù)值,則可以繼續(xù)操作,直到再次調(diào)用該函數(shù)為止。當(dāng)這個惹了麻煩的參數(shù)觸發(fā)崩潰時,你可以單步執(zhí)行代碼以查看問題所在。

 
 
 
  1. (gdb) break sometimes_crashes
  2. Breakpoint 1 at 0x40110e: file prog.c, line 5.
  3. (gdb) run
  4. [...]
  5. Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
  6. 5 fprintf(stderr,
  7. (gdb) continue
  8. Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:5
  9. 5 fprintf(stderr,
  10. (gdb) continue

為了使此方法更具可重復(fù)性,你可以在你感興趣的特定調(diào)用之前計算該函數(shù)被調(diào)用的次數(shù),并在該斷點處設(shè)置一個計數(shù)器(例如,continue 30 以使其在接下來的 29 次到達(dá)該斷點時忽略它)。

但是斷點真正強(qiáng)大的地方在于它們在運(yùn)行時評估表達(dá)式的能力,這使你可以自動化這種測試。

 
 
 
  1. break [LOCATION] if CONDITION
  2.  
  3. (gdb) break sometimes_crashes if !f
  4. Breakpoint 1 at 0x401132: file prog.c, line 5.
  5. (gdb) run
  6. [...]
  7. Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:5
  8. 5 fprintf(stderr,
  9. (gdb)

條件斷點使你不必讓 gdb 每次調(diào)用該函數(shù)時都去問你要做什么,而是讓條件斷點僅在特定表達(dá)式的值為 true 時才使 gdb 停止在該位置。如果執(zhí)行到達(dá)條件斷點的位置,但表達(dá)式的計算結(jié)果為 false,調(diào)試器會自動使程序繼續(xù)運(yùn)行,而無需詢問用戶該怎么做。

斷點命令

GNU 調(diào)試器中斷點的一個甚至更復(fù)雜的功能是能夠編寫對到達(dá)斷點的響應(yīng)的腳本。斷點命令使你可以編寫一系列 GNU 調(diào)試器命令,以在到達(dá)該斷點時運(yùn)行。

我們可以使用它來規(guī)避在 sometimes_crashes 函數(shù)中我們已知的錯誤,并在它提供空指針時使其無害地從該函數(shù)返回。

我們可以使用 silent 作為第一行,以更好地控制輸出。否則,每次命中斷點時,即使在運(yùn)行斷點命令之前,也會顯示堆棧幀。

 
 
 
  1. (gdb) break sometimes_crashes
  2. Breakpoint 1 at 0x401132: file prog.c, line 5.
  3. (gdb) commands 1
  4. Type commands for breakpoint(s) 1, one per line.
  5. End with a line saying just "end".
  6. >silent
  7. >if !f
  8. >frame
  9. >printf "Skipping call\n"
  10. >return 0
  11. >continue
  12. >end
  13. >printf "Continuing\n"
  14. >continue
  15. >end
  16. (gdb) run
  17. Starting program: /home/twaugh/Documents/GDB/prog
  18. warning: Loadable section ".note.gnu.property" outside of ELF segments
  19. Continuing
  20. Continuing
  21. Continuing
  22. #0 sometimes_crashes (f=0x0) at prog.c:5
  23. 5 fprintf(stderr,
  24. Skipping call
  25. [Inferior 1 (process 9373) exited normally]
  26. (gdb)

轉(zhuǎn)儲二進(jìn)制內(nèi)存

GNU 調(diào)試器內(nèi)置支持使用 x 命令以各種格式檢查內(nèi)存,包括八進(jìn)制、十六進(jìn)制等。但是我喜歡并排看到兩種格式:左側(cè)為十六進(jìn)制字節(jié),右側(cè)為相同字節(jié)表示的 ASCII 字符。

當(dāng)我想逐字節(jié)查看文件的內(nèi)容時,經(jīng)常使用 hexdump -Chexdump 來自 util-linux 軟件包)。這是 gdbx 命令顯示的十六進(jìn)制字節(jié):

 
 
 
  1. (gdb) x/33xb mydata
  2. 0x404040 : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x01
  3. 0x404048 : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x72
  4. 0x404050 : 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x63
  5. 0x404058 : 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x05
  6. 0x404060 : 0x00

如果你想讓 gdbhexdump 一樣顯示內(nèi)存怎么辦?這是可以的,實際上,你可以將這種方法用于你喜歡的任何格式。

通過使用 dump 命令以將字節(jié)存儲在文件中,結(jié)合 shell 命令以在文件上運(yùn)行 hexdump 以及define 命令,我們可以創(chuàng)建自己的新的 hexdump 命令來使用 hexdump 顯示內(nèi)存內(nèi)容。

 
 
 
  1. (gdb) define hexdump
  2. Type commands for definition of "hexdump".
  3. End with a line saying just "end".
  4. >dump binary memory /tmp/dump.bin $arg0 $arg0+$arg1
  5. >shell hexdump -C /tmp/dump.bin
  6. >end

這些命令甚至可以放在 ~/.gdbinit 文件中,以永久定義 hexdump 命令。以下是它運(yùn)行的例子:

 
 
 
  1. (gdb) hexdump mydata sizeof(mydata)
  2. 00000000 02 01 00 02 00 00 00 01 01 47 00 12 61 74 74 72 |.........G..attr|
  3. 00000010 69 62 75 74 65 73 2d 63 68 61 72 73 65 75 00 05 |ibutes-charseu..|
  4. 00000020 00 |.|
  5. 00000021

行內(nèi)反匯編

有時你想更多地了解導(dǎo)致崩潰的原因,而源代碼還不夠。你想查看在 CPU 指令級別發(fā)生了什么。

disassemble 命令可讓你查看實現(xiàn)函數(shù)的 CPU 指令。但是有時輸出可能很難跟蹤。通常,我想查看與該函數(shù)源代碼的特定部分相對應(yīng)的指令。為此,請使用 /s 修飾符在反匯編中包括源代碼行。

 
 
 
  1. (gdb) disassemble/s main
  2. Dump of assembler code for function main:
  3. prog.c:
  4. 11 {
  5. 0x0000000000401158 <+0>: push %rbp
  6. 0x0000000000401159 <+1>: mov %rsp,%rbp
  7. 0x000000000040115c <+4>: sub $0x10,%rsp
  8.  
  9. 12 int n = 0;
  10. 0x0000000000401160 <+8>: movl $0x0,-0x4(%rbp)
  11.  
  12. 13 sometimes_crashes(&n);
  13. 0x0000000000401167 <+15>: lea -0x4(%rbp),%rax
  14. 0x000000000040116b <+19>: mov %rax,%rdi
  15. 0x000000000040116e <+22>: callq 0x401126
  16. [...snipped...]

這里,用 info 寄存器查看所有 CPU 寄存器的當(dāng)前值,以及用如 stepi 這樣命令一次執(zhí)行一條指令,可以使你對程序有了更詳細(xì)的了解。

反向調(diào)試

有時,你希望自己可以逆轉(zhuǎn)時間。想象一下,你已經(jīng)達(dá)到了變量的監(jiān)視點。監(jiān)視點像是一個斷點,但不是在程序中的某個位置設(shè)置,而是在表達(dá)式上設(shè)置(使用 watch 命令)。每當(dāng)表達(dá)式的值更改時,執(zhí)行就會停止,并且調(diào)試器將獲得控制權(quán)。

想象一下你已經(jīng)達(dá)到了這個監(jiān)視點,并且由該變量使用的內(nèi)存已更改了值。事實證明,這可能是由更早發(fā)生的事情引起的。例如,內(nèi)存已釋放,現(xiàn)在正在重新使用。但是它是何時何地被釋放的呢?

GNU 調(diào)試器甚至可以解決此問題,因為你可以反向運(yùn)行程序!

它通過在每個步驟中仔細(xì)記錄程序的狀態(tài)來實現(xiàn)此目的,以便可以恢復(fù)以前記錄的狀態(tài),從而產(chǎn)生時間倒流的錯覺。

要啟用此狀態(tài)記錄,請使用 target record-full 命令。然后,你可以使用一些聽起來不太可行的命令,例如:

  • reverse-step,倒退到上一個源代碼行
  • *reverse-next,它倒退到上一個源代碼行,向后跳過函數(shù)調(diào)用
  • reverse-finish,倒退到當(dāng)前函數(shù)即將被調(diào)用的時刻
  • reverse-continue,它返回到程序中的先前狀態(tài),該狀態(tài)將(現(xiàn)在)觸發(fā)斷點(或其他導(dǎo)致斷點停止的狀態(tài))

這是運(yùn)行中的反向調(diào)試的示例:

 
 
 
  1. (gdb) b main
  2. Breakpoint 1 at 0x401160: file prog.c, line 12.
  3. (gdb) r
  4. Starting program: /home/twaugh/Documents/GDB/prog
  5. [...]
  6.  
  7. Breakpoint 1, main () at prog.c:12
  8. 12 int n = 0;
  9. (gdb) target record-full
  10. (gdb) c
  11. Continuing.
  12.  
  13. Program received signal SIGSEGV, Segmentation fault.
  14. 0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:7
  15. 7 return *f;
  16. (gdb) reverse-finish
  17. Run back to call of #0 0x0000000000401154 in sometimes_crashes (f=0x0)
  18. at prog.c:7
  19. 0x0000000000401190 in main () at prog.c:16
  20. 16 sometimes_crashes(0);

這些只是 GNU 調(diào)試器可以做的一些有用的事情。還有更多有待發(fā)現(xiàn)。


本文標(biāo)題:5個鮮為人知GNU調(diào)試器(GDB)技巧
標(biāo)題來源:http://www.5511xx.com/article/dhogdjd.html