gdb查看空指針 linux_5 個鮮為人知 GNU 調試器(GDB)技巧

695b1fe287ab2d716487bacef20d29e0.png

了解如何使用 gdb 的一些鮮為人知的功能來檢查和修復代碼。-- Tim Waugh(作者)

GNU 調試器 (gdb)是一種寶貴的工具,可用于在開發程序時檢查正在運行的進程并解決問題。

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

條件斷點

設置斷點是學習使用 GNU 調試器的第一步。程序在達到斷點時停止,你可以運行 gdb 的命令對其進行檢查或更改變量,然后再允許該程序繼續運行。

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

(gdb) break sometimes_crashesBreakpoint 1 at 0x40110e: file prog.c, line 5.(gdb) run[...]Breakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:55 fprintf(stderr,(gdb) continueBreakpoint 1, sometimes_crashes (f=0x7fffffffd1bc) at prog.c:55 fprintf(stderr,(gdb) continue

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

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

break [LOCATION] if CONDITION(gdb) break sometimes_crashes if !fBreakpoint 1 at 0x401132: file prog.c, line 5.(gdb) run[...]Breakpoint 1, sometimes_crashes (f=0x0) at prog.c:55 fprintf(stderr,(gdb)

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

斷點命令

GNU 調試器中斷點的一個甚至更復雜的功能是能夠編寫對到達斷點的響應的腳本。斷點命令使你可以編寫一系列 GNU 調試器命令,以在到達該斷點時運行。

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

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

(gdb) break sometimes_crashesBreakpoint 1 at 0x401132: file prog.c, line 5.(gdb) commands 1Type commands for breakpoint(s) 1, one per line.End with a line saying just "end".>silent>if !f >frame >printf "Skipping call" >return 0 >continue >end>printf "Continuing">continue>end(gdb) runStarting program: /home/twaugh/Documents/GDB/progwarning: Loadable section ".note.gnu.property" outside of ELF segmentsContinuingContinuingContinuing#0 sometimes_crashes (f=0x0) at prog.c:55 fprintf(stderr,Skipping call[Inferior 1 (process 9373) exited normally](gdb)

轉儲二進制內存

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

當我想逐字節查看文件的內容時,經常使用 hexdump -C(hexdump 來自 util-linux 軟件包)。這是 gdb 的 x 命令顯示的十六進制字節:

(gdb) x/33xb mydata0x404040  : 0x02 0x01 0x00 0x02 0x00 0x00 0x00 0x010x404048  : 0x01 0x47 0x00 0x12 0x61 0x74 0x74 0x720x404050 : 0x69 0x62 0x75 0x74 0x65 0x73 0x2d 0x630x404058 : 0x68 0x61 0x72 0x73 0x65 0x75 0x00 0x050x404060 : 0x00

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

通過使用 dump 命令以將字節存儲在文件中,結合 shell 命令以在文件上運行 hexdump 以及define 命令,我們可以創建自己的新的 hexdump 命令來使用 hexdump 顯示內存內容。

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

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

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

行內反匯編

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

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

(gdb) disassemble/s mainDump of assembler code for function main:prog.c:11 { 0x0000000000401158 : push %rbp 0x0000000000401159 : mov %rsp,%rbp 0x000000000040115c : sub $0x10,%rsp12 int n = 0; 0x0000000000401160 : movl $0x0,-0x4(%rbp)13 sometimes_crashes(&n); 0x0000000000401167 : lea -0x4(%rbp),%rax 0x000000000040116b : mov %rax,%rdi 0x000000000040116e : callq 0x401126 [...snipped...]

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

反向調試

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

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

GNU 調試器甚至可以解決此問題,因為你可以反向運行程序!

它通過在每個步驟中仔細記錄程序的狀態來實現此目的,以便可以恢復以前記錄的狀態,從而產生時間倒流的錯覺。

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

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

這是運行中的反向調試的示例:

(gdb) b mainBreakpoint 1 at 0x401160: file prog.c, line 12.(gdb) rStarting program: /home/twaugh/Documents/GDB/prog[...]Breakpoint 1, main () at prog.c:1212 int n = 0;(gdb) target record-full(gdb) cContinuing.Program received signal SIGSEGV, Segmentation fault.0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:77 return *f;(gdb) reverse-finishRun back to call of #0 0x0000000000401154 in sometimes_crashes (f=0x0) at prog.c:70x0000000000401190 in main () at prog.c:1616 sometimes_crashes(0);

這些只是 GNU 調試器可以做的一些有用的事情。還有更多有待發現。你最喜歡 gdb 的哪個隱藏的、鮮為人知或令人吃驚的功能?請在評論中分享。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/270725.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/270725.shtml
英文地址,請注明出處:http://en.pswp.cn/news/270725.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

盤點三個JavaScript案例——實現限時秒殺、定時跳轉、改變盒子大小

前言 今天來給大家盤點三個JavaScript案例,分別是實現限時秒殺、定時跳轉、改變盒子大小案例,一起來看看吧! 一、實現限時秒殺案例 1.在淘寶網中,商家為了促銷經常搞一些活動,例如限時秒殺是常見的一種活動&#xff0c…

安裝SQL提示重啟電腦失敗,解決辦法

1. 打開注冊表, 找到HKEY_LOCAL_MACHINE-->software-->Microsof-->MSSQLServer...統統刪掉 2.HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager目錄,在右側找到PendingFileRenameOperations。刪除。 重啟電腦,…

華為的鴻蒙系統是海思_死心了!華為鴻蒙系統首款終端確認,不是手機

歡迎點擊上面ZAKER關注5 月底谷歌宣布斷供華為。隨后,華為 " 秘密 " 研發 7 年的自主產權操作系統鴻蒙被公之于眾。隨著關于鴻蒙系統的消息越來越多,如鴻蒙系統 2012 年便開始規劃、鴻蒙系統在多個國家注冊商標等。人們除了佩服華為的未雨綢繆…

網絡知識:寬帶下載網速是30MB/s,經過路由器后僅10MB/s,看完你就懂了

問題:寬帶下載網速本是30MB/s,經過路由器后速度僅10MB/s,這是為什么? 寬帶下載測速可以到30MB/s,說明外線和光貓還有電腦是沒有問題的。目前家庭的組網基本都是光纖入戶了,你的測速瓶頸既然不在光貓&#…

手機投屏到電腦的5種方式,你學到了嗎

今天小編給大家分享5種手機投屏到電腦的方式,希望對大家能有幫助! 方法一: 1、我們可以通過Win10自帶的投影功能,將我們的手機和電腦連接同一個無線網絡。 2、接下來我們就在電腦開始菜單欄里找到設置選項打開。 3、我們進入之后找…

poj 3728 Catch That Cow ([kuangbin帶你飛]專題一 簡單搜索)

題目大意:題目鏈接 就是給你N,K,每次有三種慚怍1,-1,*2,,問多少次操作能到K 解題思路,搜索直接算,。,,,哎,啥時候這種垃圾…

不攔截指定路徑_控制層訪問攔截

在控制層進行訪問攔截也是我們在項目中常會遇到的需求,例如:項目中要求系統登錄操作有時間限制--12306購票時間的限制等.對于這類需求我們一般有幾種選擇:過濾器FilterAOPSpringMVC攔截器...本文我們主要說一下SpringMVC攔截器的實現原理Spring MVC的攔截器是基于回調機制,可以…

電腦知識:Win10系統把系統盤的軟件移到D盤的簡單方法

??作者主頁:IT技術分享社區 ??作者簡介:大家好,我是IT技術分享社區的博主,從事C#、Java開發九年,對數據庫、C#、Java、前端、運維、電腦技巧等經驗豐富。 ??個人榮譽: 數據庫領域優質創作者🏆&#x…

RuntimeException和Exception區別

Exception :受檢查的異常,這種異常是強制我們catch或throw的異常。你遇到這種異常必須進行catch或throw,如果不處理,編譯器會報錯。比如:IOException。 RuntimeException:運行時異常,這種異常我…

語言高精度算法階乘_JavaScript中的算法(附10道面試常見算法題解決方法和思路)...

https://juejin.im/post/6844903811505455118Introduction面試過程通常從最初的電話面試開始,然后是現場面試,檢查編程技能和文化契合度。幾乎毫無例外,最終的決定因素是還是編碼能力。通常上,不僅僅要求能得到正確的答案&#xf…

硬件:LCD和LED相關知識介紹

目錄 一、LCD簡介 二、LED簡介 三、LED和 LCD的區別 四、LED和 LCD顯示器的區別 一、LCD簡介 LCD是液晶顯示屏(Liquid Crystal)Display的全稱,主要有TFT、UFB、TFD、STN等幾種類型的液晶顯示屏無法定位程序輸入點于動態鏈接庫上。 筆記本液晶屏最常用的是TFT。 TFT…

Swagger+AutoRest 生成web api客戶端(.Net)

簡介 對于.net來說,用web api來構建服務是一個不錯的選擇,都是http請求,調用簡單,但是如果真的要在程序中調用,則還有些工作要做,比如我們需要手寫httpClient調用,并映射Model, 如果…

抽象方法和抽象類

抽象方法: 1、從上面的例子中我們可以看到抽象方法跟普通方法是有區別的,它沒有自己的主體(沒有{}包起來的 業務邏輯),跟接口中的方法有點類似。所以我們沒法直接調用抽象方法 2、抽象方法不能用private修飾&#xf…

adb logcat 保存_保存的logcat在Android設備上的文本文件

I had found some crashes while running the application in android device, which is not showing in emulator. So i need to save the Logcat in a text file in my devices memory or SD card. Could you please suggest me good method to do this?解決方案adb shell l…

電腦技巧:六款Mac電腦上值得推薦的看圖軟件

??作者主頁:IT技術分享社區 ??作者簡介:大家好,我是IT技術分享社區的博主,從事C#、Java開發九年,對數據庫、C#、Java、前端、運維、電腦技巧等經驗豐富。 ??個人榮譽: 數據庫領域優質創作者🏆&#x…

C#用Zlib壓縮或解壓縮字節數組

/// <summary>/// 復制流/// </summary>/// <param name"input">原始流</param>/// <param name"output">目標流</param>public static void CopyStream(System.IO.Stream input, System.IO.Stream output){byte[] bu…

Git的smart Checkout\force checkout\Don‘t Checkout的區別

我們在develop分支修改了代碼,但是沒有commit,所以在切換到其他分支的時候回彈出這個窗口. smart checkout就會把沖突的這部分內容帶到目的分支&#xff08;如果你沒有點進窗口的那些文件處理沖突的話&#xff09; force checkout就不會把沖突的這部分內容帶到目的分支 dont ch…

軟件:推薦5款職場人必備的效率神器APP

目錄 1.番茄TO DO&#xff08;支持Android、ios端下載&#xff09; 2.塊時間 &#xff08;支持Android、ios端下載&#xff09; 3.滴答清單&#xff08;支持Android、ios端、PC端下載&#xff09; 4.Eventai&#xff08;僅ios端下載&#xff09; 5.Ihour&#xff08;支持Androi…