《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 可編程邏輯 > 其他 > Linux教學(xué)——終端調(diào)試哪家強(qiáng)?

Linux教學(xué)——終端調(diào)試哪家強(qiáng)?

2022-10-26
作者:嵌入式與Linux那些事
來源:電子技術(shù)應(yīng)用專欄作家 嵌入式與Linux那些事
關(guān)鍵詞: 終端調(diào)試 VIM GDB

  無數(shù)次被問道:你在終端下怎么調(diào)試更高效?或者怎么在 Vim 里調(diào)試?好吧,今天統(tǒng)一回答下,我從來不在 vim 里調(diào)試,因?yàn)樗€不成熟。那除了命令行 GDB 裸奔以外,終端下還有沒有更高效的方法?能夠讓我事半功倍?

  當(dāng)然有,選擇恰當(dāng)?shù)墓ぞ吆头椒?,?GDB 調(diào)試效率成倍的提升并沒有任何問題。當(dāng)然,前提條件是你至少會(huì)在使用最原始的 GDB。

  裸奔狀態(tài):原始的 GDB 命令行

  穿上各種衣服前,至少得先學(xué)會(huì)裸奔,找份簡(jiǎn)單的 GDB cheat sheet 對(duì)照一下:

  微信截圖_20221026151855.png

  生產(chǎn)環(huán)境中出現(xiàn)崩潰時(shí),因線上服務(wù)器一般沒有開發(fā)環(huán)境,也無配套源代碼,所以程序崩潰后,如果你懶得把 core 文件拖回到開發(fā)機(jī)檢查,可以先在線上服務(wù)器先簡(jiǎn)單gdb看一下。

  GDB命令密密麻麻,常用的也就表格上那幾條,比如進(jìn)去以后第一步先用 bt 查看一下調(diào)用棧,info local查看一下本地變量,再配合 up/down 在整個(gè)調(diào)用棧的不同層次之間上下移動(dòng)一下,檢查各處局部變量的值,print 一下某個(gè)表達(dá)式,即便沒代碼,看下符號(hào)和反匯編,一般也能調(diào)試個(gè)七七八八。

  碰到復(fù)雜點(diǎn)的 BUG,必須配合源代碼了,那你得把 core 文件拉到開發(fā)環(huán)境中,再用 gdb 對(duì)照源代碼調(diào)試,配合 list [行號(hào)] 指令查看當(dāng)前運(yùn)行的源代碼,再配合其他方法進(jìn)行調(diào)試。

  那么這時(shí)候,如果調(diào)試復(fù)雜度繼續(xù)上升,你需要不斷的斷點(diǎn),每次 next / step 單步完后你都需要 list 一下前后源代碼,或者用 disassemble [函數(shù)名/地址] 查看一下指令的話,不少人會(huì)感覺到抓狂,這時(shí)我們需要給裸奔的 GDB 穿條內(nèi)褲了。

  穿上內(nèi)褲的 GDB - TUI

  這是 gdb 自帶的文本界面,使用 gdb -tui 命令啟動(dòng),比如:

  gdb -tui hello

  即可打開我們的文本界面:

  微信截圖_20221026151923.png

  上方是源代碼窗口,下面是 gdb 終端,窗口管理快捷鍵模仿 emacs,使用 c-x o 進(jìn)行窗口切換,如果你還想查看指令窗口,可以輸入:layout split

  微信截圖_20221026152016.png

  然后你單步的時(shí)候上面的源代碼窗口會(huì)跟著滾動(dòng),比之前不停的 list 方便不少吧,要看前后源代碼可以繼續(xù) c-x o 切換窗口后上下滾動(dòng)。

  有時(shí)候你 up/down 切換了棧幀后,上面的代碼也許來不及更新,那么你用 update 指令,讓上面的代碼窗口定位到你最新的執(zhí)行位置,有時(shí)也需要 CTRL-L 重繪下整個(gè)界面。

  在 gdb 自帶的 tui 模式中,你不但可以隨時(shí)查看代碼/指令,還可以查看寄存器。好吧,其實(shí) gdb再簡(jiǎn)陋,本身還是配套了一條內(nèi)褲的,只是很多人忘記拿出來穿了。

  穿上內(nèi)衣:gdbinit

  如果上述文本 TUI的信息不夠豐富的話,也許你會(huì)對(duì) .gdbinit 感興趣,~/.gdbinit 是一個(gè) gdb配置腳本,可以設(shè)定一些由 python 編寫的插件,比如 peda:

  微信截圖_20221026152033.png

  在 ~/.gdbinit 上面配置了 peda 后,可以看到命令提示符就從 (gdb) 變成了 gdb-peda$ 。每敲一個(gè)單步命令,peda 都會(huì)顯示出無比豐富的信息,你還可以配置添加更多,配合高亮,你可以得到一個(gè)加強(qiáng)版的命令行。

  不過這個(gè)我用的并不多,因?yàn)樗鼤?huì)影響 TUI 模式的界面,我不喜歡在我的 gdb 里搞太多亂七八糟的東西。同時(shí),當(dāng)我們的調(diào)試需求繼續(xù)變得更加復(fù)雜,你要不停的斷點(diǎn),頻繁的單步,這些傳統(tǒng)命令行里不停的輸入各種指令顯然已經(jīng)讓我們疲憊不堪了,能否直接在界面上查看源代碼并且直接在代碼上快捷鍵斷點(diǎn),快捷鍵單步呢?

  可以啊,試試 cgdb。

  穿上外套的 GDB:cgdb

  CGDB 類似 gdb tui 分為終端窗口和代碼窗口:

  微信截圖_20221026152113.png

  上面的代碼窗口稱為 cgdb mode, 下面的 gdb 窗口稱為 gdb mode,調(diào)試就是不停的在兩種模式間切換,按鍵模仿 vim,按 ESC 切換回 cgdb 模式,按 i 切換到 gdb 模式。

  這看起來和 TUI gdb 差不多?。砍苏Z法高亮外它比 gdb tui 高效在哪里呢?答案是:大部分操作皆可在 cgdb mode 下(即源代碼窗口)用快捷鍵操作。

  方向鍵 或者 hjkl 移動(dòng)光標(biāo),page-down/up 或 c-f / c-b 前后翻頁,按 o鍵會(huì)列出當(dāng)前可執(zhí)行文件的源代碼列表,可以切換查看其他相關(guān)代碼文件,按 / 或者 ?可以進(jìn)行文檔搜索。

  上面這些快捷鍵基本和 vim 對(duì)應(yīng),能讓你方便的瀏覽源代碼,同時(shí)在代碼窗口可以用空格鍵來切換斷點(diǎn),還有其他一些快捷鍵:

  F5 - Send a run command to GDB.

  F6 - Send a continue command to GDB.

  F7 - Send a finish command to GDB.

  F8 - Send a next command to GDB.

  F10 - Send a step command to GDB.

  更多快捷鍵見【這里】,這下單步和斷點(diǎn)比原來輕松多啦,你基本可以呆在源代碼窗口里不出來,大部分時(shí)候不用再到 gdb 命令行里一條條 next/step 的輸入了。

  編輯一下 ~/.cgdb/cgdbrc ,簡(jiǎn)單調(diào)教下使用更方便:

微信截圖_20221026152140.png

  這里大概設(shè)置了搜索大小寫不敏感,tab 大小,分屏方式(默認(rèn)改為左右分屏),搜索高亮,以及加了一個(gè) F9 的快捷鍵,用于跳出循環(huán)(默認(rèn)沒有這個(gè)快捷鍵):

  微信截圖_20221026152153.png

  現(xiàn)在大家都是寬屏顯示器了,默認(rèn)改成左右分屏(要 cgdb 7.0才支持)舒服不少。

  cgdb 還有更多功能,比如沒有源文件時(shí)可以查看匯編,或者交叉查看源代碼和匯編,設(shè)置 mark 等等,具體見它的官方文檔吧。

  這個(gè)小工具能將你從大量 gdb 命令行中解脫出來,配置文件還可以讓你按喜好綁定各種命令到快捷鍵上。

  穿戴整齊:Emacs GDB

  CGDB 雖然大部分操作可以用快捷鍵進(jìn)行,但是仍然有不少時(shí)候需要切換回右邊的 gdb mode 中去敲命令,比如當(dāng)你需要每單步一次就用 info local 查看一下局部變量或者 print 一下某個(gè)全局變量的值的時(shí)候,頻繁的左右切換會(huì)讓你疲于奔命。

  所有在調(diào)試一些相對(duì)復(fù)雜的問題時(shí),上面這些工具 hold 不住了,作用平時(shí) Vim 寫代碼的人,我也從不拒絕用 emacs 的 gdb mode 來調(diào)試一些復(fù)雜問題,毫無疑問 emacs 是目前終端下最強(qiáng)的 GDB 前端。

  從來沒用過 emacs 都沒關(guān)系,只要安裝一個(gè) emacs 記得下面幾條命令就可以調(diào)試了:

  切換文件:c-x c-f (先按 ctrl_x 再按 ctrl_f),輸入文件名時(shí)可以用 tab 補(bǔ)全

  移動(dòng)光標(biāo):方向鍵,或者 c-f, c-b, c-p, c-n;翻頁 pgup/down 或者 c-v / m-v

  切換緩存:c-x b 切換當(dāng)前窗口里的緩存,c-x c-b 打開新窗口切換緩存。

  窗口操作:c-x o 窗口切換,c-x 2 / c-x 3 上下/左右分屏,c-x 0 / c-x 1 關(guān)閉 / 獨(dú)占

  輸入命令:m-x (按 ALT_x)輸入命令可以用 tab 補(bǔ)全,c-g 退出命令輸入。

  當(dāng)然,別忘記退出命令是 c-x c-c,這就夠了,首先我們啟動(dòng) emacs:

  微信截圖_20221026152302.png

  按下 m-x (alt+x),提示輸入命令(如果終端軟件 alt 鍵不靈,那可以設(shè)置一下終端軟件,或者一秒內(nèi)先按 ESC,再按 x鍵,在 xterm 終端下是等價(jià)的),鍵入 “gdb”敲回車:

  微信截圖_20221026152316.png

  下面會(huì)問你怎么運(yùn)行g(shù)db,輸入gdb的 shell 啟動(dòng)命令行回車后開始 gdb 模式:

  微信截圖_20221026152330.png

  看到這里也許你會(huì)問,這和直接命令行 gdb 有區(qū)別么?別急,繼續(xù) m-x 輸入命令:

  微信截圖_20221026152349.png

  馬上滿足你:

  微信截圖_20221026152416.png

  左上是 GDB 終端,從上到下分別是:GDB終端,本地變量監(jiān)控,源代碼,程序輸出,棧幀,斷點(diǎn)列表。

  當(dāng)然你可以接著在 gdb 終端里輸入你想要的指令,但大部分時(shí)候我們會(huì)在源代碼窗口工作,使用 c-x o 將窗口定位到源代碼窗口,使用下面命令或者對(duì)應(yīng)快捷鍵進(jìn)行操作:

  微信截圖_20221026152445.png

  這些 gud- 開頭的命令都是 emacs gdb-mode 下通用調(diào)試器的操作命令,他們和 gdb 命令一一對(duì)應(yīng),可以用 m-x 輸入這些命令,還可以直接用快捷鍵操作。

  如果你想把某個(gè)窗口替換成反匯編或者寄存器的監(jiān)控,那么可以用 m-x 輸入:

  微信截圖_20221026152825.png

  那么其中一個(gè)窗口就會(huì)被切換成反匯編窗口:

  微信截圖_20221026152839.png

  左上角的 gdb 終端被切換成反匯編窗口了,看完后記得 c-x b 切換回 gdb 控制臺(tái),如果你要避免某個(gè)窗口被切換走可以搜索 emacs 的 dedicated window。再者,我們可以自己用窗口管理快捷鍵按照我們的喜好拆分布局:

  微信截圖_20221026152858.png

  比如重新拆分了一下,把 gdb 終端挪到右邊,輸出窗口下面,把原來顯示 gdb 終端的地方顯示為反匯編?;旧夏阍?IDE 上見得到的調(diào)試手段,在 emacs 中都可以操作,并且 emacs 還可以在 Windows 下用 gdb 調(diào)試 mingw 的程序。

  那么也許你會(huì)抱怨 emacs 下操作是在太麻煩了,沒關(guān)系,稍微調(diào)教一下即可。

  調(diào)教 emacs gdb-mode

  打開 ~/.emacs (windows下是 ~/_emacs)文件,輸入如下內(nèi)容:

  微信截圖_20221026152918.png

  解釋一下,最上面設(shè)定了 ALT + 方向鍵就可以在窗口中跳轉(zhuǎn),如果你終端 alt+方向不靈的話可以改成 C-left, C-right 等用 ctrl + 方向鍵移動(dòng)窗口,后面設(shè)定了一些常用命令的快捷。

  最后設(shè)置了默認(rèn)打開 gdb-many-windows,最好增加下面一段,允許鼠標(biāo)操作:

  微信截圖_20221026152943.png

  這下 xterm 下你可以自用的用鼠標(biāo)點(diǎn)擊切換窗口,點(diǎn)擊按鈕,用滾輪上下查看源代碼了:

  微信截圖_20221026153000.png

  這下自由多了,ALT+方向或者鼠標(biāo)點(diǎn)擊,直接窗口跳轉(zhuǎn),并且用下面的命令操作:

  F5 - 運(yùn)行,Shift + F5 - 繼續(xù)

  F7/F8 代碼級(jí)單步, 以及 Shift-F7/F8 指令級(jí)單步

  F9 - 設(shè)置斷點(diǎn),Shift-F9 刪除斷點(diǎn)

  F10 - 跳出循環(huán),Shift-F10 跳出函數(shù)

  F4 - 移動(dòng)到上一個(gè)調(diào)用棧幀,Shift-F4移動(dòng)到下一個(gè)

  右上角的本地變量窗口上面有兩個(gè)按鈕,可以鼠標(biāo)點(diǎn)擊切換顯示本地變量還是寄存器。右下角的也有兩個(gè)按鈕切換顯示斷點(diǎn)還是線程。最上面綠色部分的按鈕也可以直接鼠標(biāo)點(diǎn)擊。

  終于比我們最初的版本好用多了,如果你喜歡折騰的話,你還可以定制 gdb-many-windows 的初始格局,比如更復(fù)雜的:

  微信截圖_20221026153021.png

  徹底滿足你各種復(fù)雜的調(diào)試需求,這里不展開了,有興趣見【這篇文章】。

  最后每次調(diào)試時(shí)打開 emacs, m-x輸入 gdb 再鍵入文件名很麻煩?我們調(diào)教一下 .bashrc:

微信截圖_20221026153038.png

  就能自動(dòng)打開 emacs 并且切換到 gdb-mode 下面,展開我們的多窗口,開始調(diào)試了,是不是很愉快?

  我平時(shí)調(diào)試沒環(huán)境會(huì)先使用 gdb-tui 先看看,有環(huán)境或者問題復(fù)雜了我會(huì)打開 emacs 來調(diào)試。后來

  @zpan

  給我介紹了 cgdb 以后,gdb-tui 就退役了,無環(huán)境先用 cgdb 看個(gè)大概,碰到復(fù)雜問題打開 emacs,經(jīng)過一番調(diào)教,十分順手。

  讓 GDB 變得更性感一些

  其實(shí)到 emacs 已經(jīng)差不多了,但如果你實(shí)在記不住這有限的幾個(gè)快捷鍵或者 gdb 命令,那么還可以嘗試一下 gdbgui:

微信截圖_20221026153104.png

  就會(huì)監(jiān)聽本地 5000 端口,這時(shí)我們可以用瀏覽器打開服務(wù)器上的地址完全用鼠標(biāo)進(jìn)行調(diào)試。

  中間是程序代碼,下面是 GDB終端,上面可以切換源代碼,可以控制運(yùn)行/繼續(xù)/單步等。右邊可以實(shí)時(shí)查看:本地變量,調(diào)用棧幀,內(nèi)存地址,斷點(diǎn),線程 等等。

 微信截圖_20221026153127.png

  還能可視化查詢數(shù)據(jù)結(jié)構(gòu):

 微信截圖_20221026153144.png

  鼠標(biāo)點(diǎn)擊代碼左邊就可以設(shè)置/刪除斷點(diǎn),點(diǎn)擊上面的按鈕就能切換顯示匯編代碼?;旧习?GDB的主要功能都用可視化的方式,現(xiàn)代的網(wǎng)頁界面展示在你的面前,不需要記住任何快捷鍵,鼠標(biāo)點(diǎn)點(diǎn)點(diǎn)就可以了。

  同時(shí),這個(gè) gdbgui 還支持 Windows 下的 gdb 調(diào)試。目前 gdbgui 還在活躍的開發(fā)中,作為最漂亮的 gdb 前端,相信它會(huì)越來越強(qiáng)大。

  回顧一下

  好了我們經(jīng)歷了從最開始 gdb 的命令行裸奔狀態(tài)到終端下最完善的調(diào)試環(huán)境 emacs gdb-mode,再到性感的 gdbgui。GDB 的好處就在于對(duì)內(nèi)可以引入各種插件,對(duì)外可以提供各種接口,自己做好調(diào)試的事情,前端界面可以完全交給其他程序來主導(dǎo),不管是本地還是遠(yuǎn)程,所以才會(huì)有了各種各樣豐富的 GDB Front End,還有各種遠(yuǎn)程 GDB 工具。

  它不會(huì)限制你說你只能這樣調(diào)試,或者你只有唯一的一種 UI可以操作,所以 GDB 的組合方式千千萬萬,用不著一談 GDB 就覺得只有原始的敲命令一種用法,對(duì)吧?上面么多用法,隨便選兩樣,花不了半小時(shí),即可讓你終端下的調(diào)試工作加快不少。


 更多信息可以來這里獲取==>>電子技術(shù)應(yīng)用-AET<<

微信圖片_20210517164139.jpg

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請(qǐng)及時(shí)通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。