gdb基礎命令和常用操作補充


GDB是Unix下的一個程序調試工具,類似於windows下面的VC調試器,區別在於GDB採用全命令行控制。
使用GDB需要在編譯時使用-g選項,gcc支持-g –O選項同時使用,但如果還在調試階段,儘量不要-O2,也不要刪除(strip)符號表。作用如下:
讓程序按照自己定義的要求運行,不必每次改變程序
讓程序在設置的斷點處停住,並且檢查程序的執行情況
動態改變程序的執行環境


一、啓動調試

gdb <program> 啓動程序進行調試
gdb ./bin/chat_server
gdb --args ./bin/chat_server -c conf/cache_server.conf

 在 UNIX 下用 ps 查看正在運行的程序的 PID (進程 ID), 然後用 gdb <program> PID 格式
掛接正在運行的程序。
gdb attach <pid> 調試一個已經運行服務程序
gdb ./bin/chat_server $(pgrep  chat_server)


gdb <program> core 調試程序core down時候產生的core文件 
gdb ./bin/chat_server core
可以先使用 gcore pid (tgid,主線程id)產生正在運行程序的 core 文件,然後進行調試。

Attach到後臺進程,將操作預先輸入好,避免影響程序正常運行
sudo gdb ./bin/chat_server `pgrep chat_server` <<END
b HandleAccept
c
p (char *)inet_ntoa(pstSctx->stClientAddr.sin_addr)
p ntohs(pstSctx->stClientAddr.sin_port)
quit
END

二、gdb基礎命令







三、gdb常用操作補充

1. ulimit -c unlimited; 調試core文件
bt/where/info s 顯示函數調用堆棧
up n 向調用鏈根部移動n個函數
down n 向調用鏈葉部移動n個函數
f n 選擇函數調用鏈上編號爲n的函數,0表示當前函數
info files 顯示core文件裏面的segment映射
如果core文件函數調用棧亂掉,可以參照 http://devpit.org/wiki/x86ManualBacktrace 恢復堆棧。

2. 設置觀察點
watch     <expr>  expr 值變化時,停止程序
rwatch    <expr>  expr 值被讀時,停止程序
awatch    <expr>  expr 值被讀或被寫時,停止程序
info watchpoints  查看當前觀察點信息

3.反彙編
set disassembly-flavor intel # 設置反彙編格式
disassemble可以反彙編當前函數或者指定的函數,單獨用disassemble命令是反彙編當前函數,如果disassemble命令後面跟函數名或地址則反彙編指定的函數。

4.前面講過step命令可以一行代碼一行代碼地單步調試,而這裏用到的si/ni命令可以一條指令一條指令地單步調試。
info registers可以顯示所有寄存器的當前值。在gdb中表示寄存器名時前面要加個$,例如p $esp可以打印esp寄存器的值,如esp寄存器的值是0xbff1c3f4,所以x/20 $esp命令查看內存中從0xbff1c3f4地址開始的20個32位數。

5. p 命令內存輸出格式:
• d: ⼗十進制
• u: ⼗十進制⽆無符號
• x: ⼗十六進制
• o: ⼋八進制
• t: ⼆二進制
• c:   字符
如 p/x var

6. set listsize 50 修改源代碼顯示行數; 此外還有set args 設置參數;set var 設置變量值

7.設置位置斷點,設置斷點命令b (break的簡寫)
b linenum
b function
b filename:linenum
b filename:function
b *address
b if <condition>

8. 查看當前運行信息
info b <breakpoints>  breakpoints 爲設置的斷點的標號
info args/frame/locals/line  filename:function
info line 配合disassemble使用可查看程序彙編代碼
其中info frame 顯示的當前堆棧信息比frame詳細,可以先用frame num 切換堆棧,where/info s/bt 可以查看堆棧調用鏈


9. 條件式中斷 b test if a == 10  類似 condition 4 a == 30 (4 是bk num)

10. 刪除斷點可以使用 clear和d(delete的簡寫)
clear刪除斷點, 使用方法和b命令類似
d  [breakpoints]    breakpoints 爲設置的斷點的標號

10. 啓動和查看程序
setargs 設置程序運行參數
run運行程序,使用方式如:r   <args>
List  顯示程序源代碼命令,使用show listsize 查看顯示代碼的行數

  list <function/linenum/filename:function/filename:linenum/-/+> ,-向上翻動,+向下翻動

p var/expression(filename::var/function::var),打印變量值


11. 恢復運行程序和單步調試程序
continue,繼續運行程序
next  <count> 單步跟蹤,遇到函數不進入函數
step  <count> 單步跟蹤,遇到函數會進入該函數
finish 直到函數運行完成,打印函數信息
until   在循環體內跟蹤程序,直到整個循環結束
until+行號: 運行至某行,不僅僅用來跳出循環

12. x 命令可以顯示指定地址的內存數據。
格式: x/nfu [address]
• n: 顯示內存單位 (組或者行)。
• f: 格式 (除了print 格式外,還有字符串s 和 彙編i)。
• u: 內存單位 (b: 1字節; h: 2字節; w: 4字節; g: 8字節)。
x/8w 0x0804843b # 按四字節(w)顯示 8組內存數據
x/8i 0x0804843b # 顯示8 行彙編指令

13. 進程與線程
info proc mappings # 相當於 cat /proc/{pid}/maps 查看maps內存數據
可以在 pthread_create 處設置斷點,當線程創建時會生成提示信息。[New Thread 0xb7e78b70 (LWP 2933)]
info threads # 查看所有線程列表
where # 顯示當前線程調用堆棧
thread num # 切換線程 [Switching to thread 1 (Thread 0xb7e796c0 (LWP 2932))]#0 0xb7fe2430 in __kernel_vsyscall ()

14. 其他零散

調試子進程。
(gdb) set follow-fork-mode child

臨時進入Shell執行命令,Exit返回。
(gdb) shell

調試時直接調用函數。
(gdb) call test("abc")

使用 "--tui" 參數,可以在終端窗口上部顯示一個源代碼查看窗。
$ gdb --tui hello

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

在GDB下,我們無法print宏定義,因爲宏是預編譯的。但是我們還是有辦法來調試宏,這個需要GCC的配合。在GCC編譯程序的時候,加上-ggdb3參數,這樣,你就可以調試宏了。另外,你可以使用下述的GDB的宏調試命令 來查看相關的宏。
info macro – 你可以查看這個宏在哪些文件裏被引用了,以及宏定義是什麼樣的。
macro – 你可以查看宏展開的樣子。


提示找不到源文件:
編譯程序員是否加上了-g參數以包含debug信息。
路徑是否設置正確了。使用GDB的directory命令來設置源文件的目錄。

如果要打印一個序列化過的結構體,這個序列太長的話,往往會被gdb省略掉,如:
gdb>p string
"xxxx",…"" //會有省略號出現,無法看到完整的字符串
此時可以設置:
gdb>set print elements 0
再次:
gdb>p string
"xxxx","yyyy",""//顯示完整的字符串

查看命令幫助。
(gdb) help b

最後就是退出命令。
(gdb) q

和Linux Base Shell習慣一樣,對於記不住的命令,可以在輸入前幾個字母后按Tab補全。

▪ tbreak          temporary breakpoint
▪ rbreak          reg-ex breakpoint
▪ break xxx if yyy    conditionally break at xxx if condition yyy holds
▪ commands         list of commands to be executed when a breakpoint is hit
▪ silent          special command to suppress output on breakpoint hit
▪ save breakpoints    save a list of breakpoints to a script
▪ save history       save history of executed gdb commands
▪ call            call a function in the inferior
▪ watch -l          watchpoint based on address (location)
▪ rwatch           read watchpoint
▪ info line foo.c:42   show PC for line
▪ info line * $pc     show line begin/end for current program counter
▪ thread apply all bt   backtrace for every thread
▪ dprintf           dynamic printf
▪ python:           define custom commands by inheriting from gdb.Command class
▪ python:           hook events to invoke python functions using gdb.events.stop.connect
▪ gcc’s -g and -O are orthogonal


經驗:如果某個函數的局部變量發生訪問越界,有可能並不立即產生段錯誤,而是在函數返回時產生段錯誤。

參考:
《linux c 編程一站式學習》
《C 學習筆記》 by雨痕
Give me fifteen minutes and I’ll change your view of GDB

發佈了249 篇原創文章 · 獲贊 3477 · 訪問量 173萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章