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

s1mba發表於2015-01-23

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

相關文章