gdb 調試高級命令

1. gdb 運行初始化命令 -x usercmd

    在.gdbinit 初始化命令中, 可以用#(同bash 註釋符合)來註釋

    可以用source <cmd file> 在啓動gdb 後運行gdb 命令文件

    可以用file <loading file> 在啓動gdb 後再加載文件

2. gdb 傳遞命令行 參數
a. run <args>
b. set args <args>
可用 show args 查看

3. gdb 中宏的操作
默認編譯的時候,調試過程是看不見宏的值的。編譯時候需要給選項。-g3
gcc  -g3 -o test.c  test
gdb test
察看宏(macro)命令: p macroname(...) 
就像察看一個普通變量一樣。如果只想看宏的展開形勢,就用如下命令:
macro expand macroname(...) 查看展開形式

還可以用info macro macroname 查看宏定義。

 

4. gdb 臨時斷點: tbreak

5. gdb 設置顯示選項 .
例如 set print pretty

打印結構變量類型. ptype struct 類型名

----------------------------------------
6.  讓GDB記錄輸出信息到文件
----------------------------------------
(gdb) set logging on    -> 打開記錄功能。
(gdb) set logging off -> 關閉記錄功能。
(gdb) show logging -> 顯示記錄功能中每個選項的設置。
Future logs will be written to gdb.txt.   ---> 表示log 沒有打開
Currently logging to "gdb.txt".    --> 表示log 已經打開

----------------------------------------

7. gdb 調試運行的進程

gdb -p <進程號>

或者:

gdb

attach <進程號>

----------------------------------------

下面不常用的功能,供瞭解
set logging file <file name> -> 改變記錄文件,默認記錄文件是gdb.txt。
set logging overwrite [on|off] -> 默認這個項目是關閉,
也就是以添加的形式將記錄信息寫入文件,這樣之前文件中的信息不會被覆蓋掉。
注意:如果設置這個選項的時候記錄功能已經打開,需要關閉記錄功能再重新打開才能起作用。
set logging redirect [on|off] -> 設置輸出信息只記錄到文件不作顯示。
默認這個項目是關閉的,GDB將輸出信息到終端和記錄文件。如果打開這個項目,GDB將只輸出信息到記錄文件。
注意:如果設置這個選項的時候記錄功能已經打開,需要關閉記錄功能再重新打開才能起作用。
注意:記錄功能只能記錄GDB的輸出信息,被調試程序的輸出信息仍然會輸出到終端。

---------------------------------------
7. 爲什麼沒有core文件生成呢?

---------------------------------------
有時候程序down了, 但是core文件卻沒有生成.
core文件的生成跟你當前系統的環境設置有關係, 可以用下面的語句設置一下, 然後再運行程序便生成了core文件.
ulimit -c unlimited
gdb a.out core

----------------------------------------
8. gdb加載內核模塊符號信息:
add-symbol-file <MODULE_FILE> ADDR

例:

root@ubuntu:/home/hjj/software/uxfs_now/kern# cat debug
set remotebaud 115200
target remote /dev/ttyS1
add-symbol-file uxfs.ko 0xe0886000 -s .exit.text 0xe0888404

-------------------------------------------------
附錄:gdb  常用調試命令
-------------------------------------------------
(gdb) l :(字母l)列出源碼
(gdb) b n :在第n行處設置斷點
(gdb) b func:在函數func()的入口處設置斷點

(gdb) 條件斷點:條件可以是任何合法的c 表達式。 例如 b n if val1==val2

          當已經設置了斷點,可以用condition 命令對斷點號添加條件, 例: condition 2 val1==val2 , 注意,沒有if 單詞

          當對變量的改變更感興趣時,可以用watch 命令

 (gdb) info break: 查看斷點信息
(gdb) r:運行程序
(gdb) n:單步執行
(gdb) s:單步調試如果有函數調用,則進入函數;與命令n不同,n是不進入調用的函數的
(gdb) c:繼續運行
(gdb) p 變量 :打印變量的值     也能夠修改變量的值(用 = 賦值) // 打印寄存器值。 p $eax

(gdb) x/nfu <addr> 顯示內存  // n爲個數,f 爲格式,u爲每單元長度
(gdb) bt:查看函數堆棧
(gdb) finish:退出函數

(gdb) display <var> 每次中斷或單步都顯示你關心的變量

(gdb)undisplay <編號>
(gdb) shell 命令行:執行shell命令行
(gdb) set args 參數:指定運行時的參數
(gdb) show args:查看設置好的參數
(gdb)info program: 來查看程序的是否在運行,進程號,被暫停的原因。 // 打印寄存器數組, info reg,  簡寫 i reg
(gdb)clear 行號n:清除第n行的斷點
(gdb)delete 斷點號n:刪除第n個斷點
(gdb)disable 斷點號n:暫停第n個斷點
(gdb)enable 斷點號n:開啓第n個斷點

 

----------------------------------------
gdb 條件調試
----------------------------------------
“break ... if cond" 命令
例: b fun() if i==20

ignore bnum count
watch var    // 此時監測var的變化

----------------------------------------
gdb 多線程調試
----------------------------------------
info threads
thread ID 來切換
set scheduler-locking off|on|step 估計實際使用過多線程調試的人都可以發現,
在使用step或者continue命令調試當前被調試線程的時候,其他線程也是同時執行的,
怎麼只讓被調試程序執行呢?通過這個命令就可以實現這個需求。
off 不鎖定任何線程,也就是所有線程都執行,這是默認值。
on 只有當前被調試程序會執行。
設置 on 之後, step 在單步的時候, 只有當前線程會執行。
next過一個函數的情況(熟悉情況的人可能知道,這其實是一個設置斷點然後continue的行爲)。

1.gdb有個很友好的調式界面,就是layout方式調試,可以讓你邊調試變查看源碼,
但是layout方式有時候有點bug,不過基本上還可以使用,
可以用ctrl+x和ctrl+a 來切換。可能layout會造成控制檯花屏,使用ctrl+L清屏。


----------------------------------------
 GDB堆棧跟蹤的方法
----------------------------------------
程序“調用堆棧”是當前函數之前的所有已調用函數的列表(包括當前函數)。每個函數及其變量都被分配了一個“幀”,
最近調用的函數在 0 號幀中(“底部”幀)。要打印堆棧,發出命令 'bt'('backtrace' [回溯] 的縮寫):
(gdb) bt
#0  0x80483ea in wib (no1=8, no2=8) at eg1.c:7
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at eg1.c:21
此結果顯示了在 main() 的第 21 行中調用了函數 wib()(只要使用 'list 21' 就能證實這一點),而且 wib() 在 0 號幀中,
main() 在 1 號幀中。由於 wib() 在 0 號幀中,那麼它就是執行程序時發生算術錯誤的函數。
實際上,發出 'info locals' 命令時,gdb 會打印出當前幀中的局部變量,缺省情況下,這個幀中的函數就是被中斷的函數(0 號幀)。
可以使用命令 'frame' 打印當前幀。要查看 main 函數(在 1 號幀中)中的變量,可以發出 'frame 1' 切換到 1 號幀,
然後發出 'info locals' 命令:
(gdb) frame 1
#1  0x8048435 in main (argc=1, argv=0xbffff9c4) at eg1.c:21
21          result = wib(value, div);
(gdb) info locals
value = 8
div = 8
result = 4
i = 2
total = 6
   
此信息顯示了在第三次執行 "for" 循環時(i 等於 2)發生了錯誤,此時 "value" 等於 "div"。
可以通過如上所示在 'frame' 命令中明確指定號碼,或者使用 'up' 命令在堆棧中上移以及 'down' 命令在堆棧中下移來切換幀。
要獲取有關幀的進一步信息,如它的地址和程序語言,可以使用命令 'info frame'。
gdb 堆棧命令可以在程序執行期間使用,也可以在 core 文件中使用,因此對於複雜的程序,可以在程序運行時跟蹤它是如何轉到函數的。
 查看棧信息
當程序被停住了,你需要做的第一件事就是查看程序是在哪裏停住的。 當你的程序調用了一個函數,
函數的地址,函數參數,函數內的局部變量都會被壓入“棧”(Stack)中。你可以用GDB命令來查看當前的棧中的信息。
下面是一些查看函數調用棧信息的GDB命令:
    Backtrace,bt 打印當前的函數調用棧的所有信息。如:        
        (gdb) bt
        #0 func (n=250) at tst.c:6
        #1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
        #2 0x400409ed in __libc_start_main () from /lib/libc.so.6        
從上可以看出函數的調用棧信息:__libc_start_main --> main() --> func()    
    backtrace <n>, bt <n> n是一個正整數,表示只打印棧頂上n層的棧信息。
    backtrace <-n> ,bt <-n> -n表一個負整數,表示只打印棧底下n層的棧信息。        
如果你要查看某一層的信息,你需要在切換當前的棧,一般來說,程序停止時,最頂層的棧就是當前棧,如果你要查看棧下面層的詳細信息,首先要做的是切換當前棧。
frame <n>,f <n> n是一個從0開始的整數,是棧中的層編號。比如:frame 0,表示棧頂,frame 1,表示棧的第二層。
   up <n>         表示向棧的上面移動n層,可以不打n,表示向上移動一層。
down <n> 表示向棧的下面移動n層,可以不打n,表示向下移動一層。
上面的命令,都會打印出移動到的棧層的信息。如果你不想讓其打出信息。你可以使用這三個命令:
     select-frame <n> 對應於 frame 命令。
      up-silently <n> 對應於 up 命令。
      down-silently <n> 對應於 down 命令。
查看當前棧層的信息,你可以用以下GDB命令:
frame 或 f       會打印出這些信息:棧的層編號,當前的函數名,函數參數值,函數所在文件及行號,函數執行到的語句。
info frame,info f 這個命令會打印出更爲詳細的當前棧層的信息,只不過,大多數都是運行時的內內地址。比如:函數地址,調用函數的地址,被調用函數的地址,目前的函數是由什麼樣的程序語言寫成的、函數參數地址及值、局部變量的地址等等。如:
       (gdb) info f
       Stack level 0, frame at 0xbffff5d4:
         eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
         called by frame at 0xbffff60c
         source language c.
         Arglist at 0xbffff5d4, args: n=250
         Locals at 0xbffff5d4, Previous frame's sp is 0x0
         Saved registers:
         ebp at 0xbffff5d4, eip at 0xbffff5d8              
     info args      打印出當前函數的參數名及其值。     
     info locals     打印出當前函數中所有局部變量及其值。        
     info catch      打印出當前的函數中的異常處理信息。


gdb 跟蹤遠程調試命令交互過程
"set debug remote 1" 將顯示gdb 遠程調試的過程。

gdb 內存斷點設置。
rwatch, watch, awatch 分別代表讀,寫,讀寫內存斷點,用的是硬件斷點。

------------------------------------------------------------------
gdbtui  gdb 圖形化接口。方便調試
啓動gdb, 按ctrl-x cta-a 也可進入tui 模式
------------------------------------------------------------------

 help layout
     layout src
     layout asm
     layout split

 help winheight
     winheight src +5
     winheight src -4

help focus
    focus cmd
    focus src
    focus next
簡記爲
    fs next
    fs src
    fs cmd

--------------------------------------------------------------------------------
help info
Generic command for showing things about the program being debugged.
關於被調試程序的一些信息
help show
Generic command for showing things about the debugger
關於debugger狀態的一些信息
--------------------------------------------------------------------------------

常用命令:

set args

file

source

set logging overwrite on
set logging on
set print pretty
show logging
set pagination off   // 不要出現 Type <return> to continue 的提示信息
info functions
info variables

list

list [函數名稱]

 

與調試控制相關的命令

 

  • continue    繼續運行程序直到下一個斷點(類似於VS裏的F5)
  • next        逐過程步進,不會進入子函數(類似VS裏的F10)
  • step        逐語句步進,會進入子函數(類似VS裏的F11)
  • until        運行至當前語句塊結束
  • finish  運行至函數結束並跳出,並打印函數的返回值(類似VS的Shift+F11)

 

 

 

s : step in

fin: step out, 跳出函數

until 行號。 可用於跳出循環,加快了調試速度。

 

----------------------------------------
gdb 調試跟蹤多進程程序
----------------------------------------
gdb只能跟蹤一個進程(默認是跟蹤父進程),而不能同時跟蹤多個進程,
可以設置gdb跟蹤父進程還是子進程, 命令如下:
set follow-fork-mode parent 跟蹤父進程, 默認
set follow-fork-mode child  跟蹤子進程

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章