您好,登錄后才能下訂單哦!
如何分析gdb的使用技巧,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
GDB是一個由GNU開源組織發布的、UNIX/LINUX操作系統下的、基于命令行的、功能強大的程序調試工具。
在實際應用中,有兩種調試方法:在線調試和離線調試。
離線調試適用于開發測試環境,可以自由啟停進程,設置斷點;在線調試一般用于現場問題分析,不能隨便啟停進程,對于技術要求較高。
若想執行gdb調試,在Makefile文件中需要增加編譯調試選項-g,例如:
gdb dup_file.c –o dum_file_elf –g –lpthread
說明:-g選項的作用是在可執行文件(ELF)中加入源代碼的相關信息,比如ELF中第幾條機器指令對應源代碼的行數。但不是把整個源文件嵌入到可執行文件中,所以在調試時必須保證gdb能找到源文件。
-g完整格式是-glevel,其中,level中指定了調試信息中包含了調試信息的多少,默認的是2,level=1最少,level=3最多。
例如:
readelf -S helloWorld|grep debug
注:helloWorld為文件名,如果沒有任何debug信息,則不能被調試。
下面的情況也是不可調試的:
file helloWorld
helloWorld: (省略前面內容) stripped
注:如果最后是stripped,則說明該文件的符號表信息和調試信息已被去除,不能使用gdb調試。但是not stripped的情況并不能說明能夠被調試。
在開發中可以將源碼和可執行文件拷貝到某一目錄下,使用gdb啟動進程進行調試,也可以不拷貝源碼和可執行文件,使用NFS掛載到編譯環境執行調試;在現場環境中使用ps獲取進程的pid,然后gdb –p pid執行在線調試。
離線調試:
gdb 進程名
gdb –tui 進程名
在線調試:
ps –A | grep 進程名
gdb –p pid/gdb attach pid
說明:使用-tui參數可以將調試窗口分為兩部分:上面是源碼,下面是調試信息,使用Ctrl+n/Ctrl+p或者方向鍵進行翻頁。
帶參數調試:
1、啟動的時候帶上參數
gdb --args xxx 參數
2、啟動之后 run 帶上參數
# gdb xxx
(gdb)run 參數
3、啟動之后 set args 設置參數
# gdb xxx
(gdb)set args 參數
core文件調試
當程序core dump時,可能會產生core文件,它能夠很大程序幫助我們定位問題。但前提是系統沒有限制core文件的產生。可以使用命令limit -c查看:
$ ulimit -c
如果結果是0,即便程序core dump了也不會有core文件留下。我們需要讓core文件能夠產生:
ulimit -c unlimied #表示不限制core文件大小
ulimit -c 10 #設置最大大小,單位為塊,一塊默認為512字節
上面兩種方式可選其一。第一種無限制,第二種指定最大產生的大小。
針對生成core文件進行調試,可以采用在線加載和離線加載的方式,如下:
gdb 可執行文件 core文件
注:有時候使用p打印調試信息不完整或者不便于閱讀,可以使用set print elelent 0和setprint pretty on設置。
handle命令
handle SIGUSR1 nostop noprint
handle SIGUSR2 nostop noprint
handle SIGPIPE nostop noprint
handle SIGALARM nostop
handle SIGHUP nostop
handle SIGTERM nostop noprint
注:設置GDB調試時對信號的相關動作。
打斷點還是比較有技巧的,雖然有很多打斷點的方法,但是實際調試中一般就使用以下幾種:
函數打斷點:b 函數名
某一行打斷點:b 源文件:行號
條件斷點:
break 斷點 if 條件
continue 斷點編號(執行一次表示設定,再次執行表示取消)
continue 斷點編號 條件
注:條件斷點非常有用,實際調試中往往需要調試特定場景下函數調用關系,此時就需要設置斷點觸發的條件。
查看斷點:info breakpoint/info break/info b
刪除斷點:delete 斷點號/delete(刪除所有斷點)
禁用/開啟斷點:disable/enable breakpoint
ignore:
斷點條件的一個特殊用法是,程序只有在到達斷點一定次數之后才會停止,此時可以使用指令:
ignore 斷點編號 次數
ignore 2 10觸發斷點10次后才會停止,每次觸發斷點count自動減1
說明:打完斷點是不是執行continue就可以等待著運行到斷點了呢?不一定,有時候斷點處代碼的執行需要外部出發,比如web發送特定消息后才可以觸發執行,如果一直等待沒有消息出發永遠執行不到斷點處,此時就需要結合自己的業務邏輯,手動設置出發條件。
執行程序的方法有兩種:一種是從main函數開始執行逐步分析,一種是執行到斷點處。
重新運行:r/run
繼續執行:c/continue
單步執行:n/next/next N(執行N次next)
單步進入:step(遇到函數進入函數內部,退出函數時使用finish)
結束函數:finish
強制返回:return(忽略當前未執行的部分,強制返回)
(gbd) backstrace/bt
有時候跳轉的次數太多,不知道具體調用的層級關系了,可以使用bt查看堆棧,該命令會產生一張列表,包含著運行過程和相關的參數。
設置變量:set 變量=表達式
在調試的時候,有時候需要設置一些假數據查看對應輸出,比如根據布爾值查看流程執行情況,此時就需要在執行到指定位置時手動設置一下數據的取值。
監控變量:
watch 變量 (數值改變時暫停運行)
awatch <表達式> (被訪問或改變時暫停運行)
rwatch <表達式> (被訪問時暫停運行)
有時候我們需要觀察一個變量的變化過程,比如一個全局變量如何初始化,如何調用的,這就需要使用watch監控變量。
變量類型:
ptype var 變量類型
whatis var 顯示一個變量var的類型
打印變量/表達式:
打印變量:p 變量
打印字符/表達式:p “%s”,字符/表達式
格式化輸出:p/格式控制符 打印內容
說明:
gdb可支持的變量顯示格式有:
x:按16進制格式顯示變量
d:按10進制格式顯示變量
u:按16進制格式顯示無符號整型
o:按8進制格式顯示變量
t:按2進制格式顯示變量
c:按字符格式顯示變量
f:按浮點數格式顯示變量
也可以使用x(Examination)來打印需要顯示的字符信息,格式如下:
x/格式 地址
格式(可選)一般是NFU:
1、N表示重復次數(表示顯示內存的長度,也就是說從當前向后顯示幾個地址的內容)
2、F表示顯示格式
3、U表示單位(b:字節,h:半字[2字節],w:字[4字節,默認],g:雙字[8字節])。表示多少個字節作為一個值取出來,如果不指定的話,GDB默認是1個byte,當我們指定了字節長度后,GDB會從指定內存的地址開始,讀取指定字節,并把其作為一個值取出來。
參數u可使用下面字符代替:
b:表示單字節
h:表示雙字節
w:表示四字節
g:表示八字節
disassemble
可以使用反匯編的指令disassemble去探究究竟在函數中發生了哪些操作,具體如下:
1、disassemble
2、disassemble 程序計數器
3、disassemble 開始地址 結束地址
格式1表示反匯編當前整個函數,格式2表示反匯編計數器所在函數的整個函數,格式3表示反匯編從開始地址到結束地址的部分。
call
強制調用函數:call 表達式
q/quit
在執行到斷點后,采用q/quit指令退出。
detach-on-fork
該屬性決定了gdb是同時調試父子進程,還是在fork了子進程之后,將子進程分離出去。
on:子進程(或者父進程,取決于gdb在初始時,要調試的進程,也就是follow-fork-mode的值)
off:同時調試父子進程,一個進程處于被調試的狀態,而另一個則被gdb掛起
設置:set detach-on-fork on/off
follow-fork-mode
該屬性決定了gdb在進程調用fork之后的行為。
set follow-fork-mode parent:默認情況下,在調用fork之后,gdb選擇跟隨(也就是調試)父進程,而子進程則在處于運行的狀態(此時父進程處于阻塞的狀態)。
set follow-fork-mode child:fork之后gdb選擇調試子進程,而父進程處于運行的狀態。
查看當前調試的進程:info inferiors
查看線程:info threads
注:輸出信息前面有“*”表示調試的當前線程(一般thread切換線程后查看)。
有的程序會在運行過程中主線程創建多個子線程,所以前后執行info threads顯示的線程數是會動態變化的。
查看所有線程堆棧:thread apply all bt
查看指定線程堆棧:thread apply thread1 thread2... bt
切換線程:thread N
注:通過打印counter,可以看到多個線程都是在運行的,如果想要讓其他線程處于停止狀態,只有當前調試的線程執行,可以采用set scheduler-locking on。
阻塞其他線程,僅調試當前線程工作:
set scheduler-locking [on|off|step]
運行指定線程并允許其他線程并行執行:
thread apply N command
關于如何分析gdb的使用技巧問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。