筆記:gdb debug指令概要



1. b/break設定中斷點

1.1 針對function名稱設定中斷點b func_name

gdb內可以用TAB的auto completion,預設最多顯示200筆資料
(gdb) b avpriv_mpegts
avpriv_mpegts_parse_close   avpriv_mpegts_parse_open    avpriv_mpegts_parse_packet

(gdb) b avpriv_mpegts_parse_packet
Breakpoint 1 at 0x749540: file libavformat/mpegts.c, line 3369.

1.2 針對特定source code行數設定中斷點b file_name:line_num

(gdb) b libavformat/mpegts.c:3163
Breakpoint 2 at 0x7451a7: file libavformat/mpegts.c, line 3163.

1.3 針對目前source code設定中斷點b line_num

(gdb) b 300
Breakpoint 2 at 0x4971a7: file fftools/ffprobe.c, line 300.

如果你還沒有執行程式,b 300的意思是設定main程式所在檔案的第300行
例如ffprobe的main程式在fftools/ffprobe.c, 就會設定在ffprobe.c的300行

1.4 針對當前位置設定中斷點 b

(gdb) b

1.5 顯示中斷點i b/info break

(gdb) i b
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000749540 in avpriv_mpegts_parse_packet at libavformat/mpegts.c:3369
2       breakpoint     keep y   0x00000000007451a7 in mpegts_read_header at libavformat/mpegts.c:3163

1.6 關閉/啟用中斷點disable/enable breakponts

關閉第二個中斷點
(gdb) disable b 2
(gdb) i b
Num     Type           Disp Enb Address            What
2       breakpoint     keep n   0x00000000007424f0 in mpegts_probe at libavformat/mpegts.c:2997
4       breakpoint     keep y   0x0000000000496750 in main at fftools/ffprobe.c:3584
  breakpoint already hit 1 time

啟用所有中斷點
(gdb) enable b
(gdb) i b
Num     Type           Disp Enb Address            What
2       breakpoint     keep n   0x00000000007424f0 in mpegts_probe at libavformat/mpegts.c:2997
4       breakpoint     keep y   0x0000000000496750 in main at fftools/ffprobe.c:3584
  breakpoint already hit 1 time

1.7 儲存/載入中斷點save breakpoints/source

(gdb) save breakpoints bps.saved
將使用過的中斷點儲存到指定檔案名稱

1.7.1 切換儲存/載入目錄
(gdb) pwd
Working directory /main/ffmpeg.

(gdb) cd ../
Working directory /main.

1.8 刪除中斷點d/delete

刪除所有(gdb) d

刪除特定中斷點,以info break上的Num為準(gdb) d 1

2. 執行程式

2.1 開始執行程式r/run

(gdb) r
Starting program: ffmpeg/ffprobe_g -i /content/movie.ts
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
ffprobe version N-96259-g481f4380fb Copyright (c) 2007-2020 the FFmpeg developers
 ...

如果你已經執行程式,會顯示是否重新執行
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n)

2.1.1 執行程式帶入新參數
(gdb) r -i /content/new_movie.ts
就會使用後面的參數執行程式

注意:有帶入過參數後,再使用r會一直沿用新的參數, 要清除需要用set args清除參數

2.1.2 設定新參數
(gdb) set args -i /content/new_movie.ts
只設定新參數

2.1.3 清除參數
(gdb) set args
清除參數執

2.1.4 顯示目前參數
(gdb) show args

注意:這裡不是用i args顯示內容,要顯示函數參數才是,因為set指令對應的顯示功能是show

2.2 繼續執行c/continue

當程式中斷後要讓程式繼續執行,需使用此功能(gdb) c
Breakpoint 2, mpegts_probe (p=0x7fffffffd400) at libavformat/mpegts.c:2997
2997  #define CHECK_COUNT 10

2.3 停止程式kill

(gdb) kill
會詢問是否確定將程式停止

3. 顯示source code

3.1 顯示執行位置的檔案及行號i li/info line

(gdb) i li
Line 2997 of "libavformat/mpegts.c" starts at address 0x7424f0 and ends at 0x7424f2 .

3.2 顯示執行位置的對應source code, l/line

顯示source code預設是上下5行
(gdb) l
2992      const int size = p->buf_size;
...
3001          return 0;

如果再次使用line會得到再下面的10行,如下所示
(gdb) l
3002
3003      for (i = 0; i3004          int left = FFMIN(check_count - i, CHECK_BLOCK);
...
3010          maxscore = FFMAX(maxscore, score);
3011      }


使用l -可往上10行
使用l 100可顯示100行附近
使用l 100, 150可顯示100到150行內容

3.3 顯示執行位置的source code檔案相關訊息i source


(gdb) i source
Current source file is libavformat/mpegts.c
Compilation directory is ffmpeg
Located in ffmpeg/libavformat/mpegts.c
Contains 3415 lines.
Source language is c.
Producer is GNU C 4.8.5 -mtune=generic -march=x86-64 -g -O3 -std=c11 -fomit-frame-pointer -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -fstack-protector.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.


這裡可以看到編譯該程式碼時使用的參數,主要是gcc的debug資料要保留才可以顯示出來

4. 單步執行及呼叫堆疊

關於stack frame參考:http://kirste.userpage.fu-berlin.de/chemnet/use/info/gdb/gdb_7.html

4.1 往下一行執行n/next

不會進入函數。又稱為往下一"行"(Step over),而不是往下一"步"執行(Step into)
(gdb) n

3002

使用n 100可往下執行100行,其實這結果是很難預測的,可能會跑到函數結束,或是遭遇例外,使用後會需要用到info line或frame確認目前執行位置。

(gdb) i li
Line 196 of "libavformat/format.c" starts at address 0x6d1d81
   and ends at 0x6d1d90 .

4.2 往下一步執行s/step

(gdb) s
相較於n,s就是往下一步執行,如果是函數,就會跳進去該函數執行。

如果要跳回來原本位置,可以用up或是finish執行到函數結束

4.3 呼叫堆疊

4.3.1 所有呼叫堆疊bt/backtrace,i s/info stack,frames
除了bt外,我們也可以用i s/info stack,f/frames顯示目前呼叫堆疊

(gdb) bt
#0  av_probe_input_format3 (pd=pd@entry=0x7fffffffd8b0, is_opened=is_opened@entry=1, score_ret=score_ret@entry=0x7fffffffd8a8)
    at libavformat/format.c:196
#1  0x00000000006d225e in av_probe_input_format2 (score_max=, is_opened=1, pd=0x7fffffffd8b0)
    at libavformat/format.c:208
#2  av_probe_input_buffer2 (pb=0x227fa40, fmt=0x227f208, filename=filename@entry=0x7fffffffe064 "/content/movie.ts",
    logctx=logctx@entry=0x227f200, offset=offset@entry=0, max_probe_size=1048576) at libavformat/format.c:280
...

4.3.2 當前或指定堆疊s/stack,frame/frame 0

(gdb) s
parse_loglevel (argc=argc@entry=3, argv=argv@entry=0x7fffffffdc08, options=options@entry=0x119d200 )
    at fftools/cmdutils.c:507
507 {

(gdb) frame 
#0  parse_loglevel (argc=argc@entry=3, argv=argv@entry=0x7fffffffdc08, options=options@entry=0x119d200 )
    at fftools/cmdutils.c:507
507 {

如果只想看特定堆疊,可以用frame 堆疊號碼來指定

4.3.3 呼叫堆疊資訊i f/info frame

(gdb) i f
Stack level 0, frame at 0xbe8a3570:
 pc = 0xb2656f4c in nanosleep; saved pc = 0xb263b8fc
 called by frame at 0xbe8a3598
 Arglist at 0xbe8a3570, args: 
 Locals at 0xbe8a3570, Previous frame's sp is 0xbe8a3570

4.3.4 往上/下一層堆疊up/down
(gdb) up
用這個指令,通常後面會搭配next執行下一行

(gdb) down

4.4 執行到函數結束fi/finish

(gdb) finish
Run till exit from #0  mpegts_probe (p=0x7fffffffd810) at libavformat/mpegts.c:2997
av_probe_input_format3 (pd=pd@entry=0x7fffffffd8b0, is_opened=is_opened@entry=1, score_ret=score_ret@entry=0x7fffffffd8a8)
    at libavformat/format.c:166
166             if (score)
Value returned is $1 = 50

5. 印出變數內容

5.1 顯示特定p/print var_name

(gdb) print sumscore
$7 = 0
(gdb) print dvhs_score
$8 =

上面可以看到$7,$8,這些都是臨時變數,也可以再印出一次, 使用 $ 來取用最後產生的臨時變數,使用 $$ 來取用上一個產生的臨時變數。

引用自:https://blog.csdn.net/u012927281/article/details/50546787
使用gdb過程中出現value optimized out,上述情況是由於gcc在編譯過程中默認使用-O2優化選項。以上情況在循環語句中經常出現,對於希望進行單步跟蹤調試時,應使用-O0選項。
5.1.1 花式印出變數

(gdb) p &var            印出變數var的位址
(gdb) p *var             印出變數var取址後的值
(gdb) p/x var            以 16 進位列印變數var內容
(gdb) p/u var            以 unsigned 10 進位列印變數var內容
(gdb) p/d var            以 signed 10 進位列印變數var內容
(gdb) p/t var             以 2 進位列印變數var內容
(gdb) p (var=value)  設變數var的值為value

5.1.2 印出陣列

(gdb) p array[10]          印出陣列變數array第11個元素內容
(gdb) p array[1]@5      從陣列變數array第2個元素開始印出5個內容

5.1.3 印出資料

(gdb) whatis var                 印出變數var資料型別
(gdb) ptype var                  印出變數var的struct

參考:
http://www.study-area.org/cyril/opentools/opentools/x1253.html

5.2 印出local變數

(gdb) i locals 
maxscore = 0
i =
...

5.3 印出register

(gdb) i reg
rax            0x7424f0 7611632
rbx            0x18878c0  25721024
...

5.4 印出函數的參數

(gdb) i args 
argc = 3
argv = 0x7fffffffdc08
options = 0x119d200

6. 多執行緒操作

參考:https://sourceware.org/gdb/current/onlinedocs/gdb/Threads.html

6.1 印出執行緒狀態

(gdb) i threads 
  Id   Target Id         Frame 
* 1    Thread 0x7ffff7f2e8c0 (LWP 13571) "ffprobe_g" mpegts_probe (p=0x7fffffffd810) at libavformat/mpegts.c:2997

6.2 切換到執行緒

(gdb) thread 1

6.3 綜合操作

如何查卡在哪個thread上面, 請參考

print mutax變數看屬性__owner去對照找出該thread

7. 多Process操作

參考:
https://sourceware.org/gdb/onlinedocs/gdb/Inferiors-and-Programs.html
https://sourceware.org/gdb/onlinedocs/gdb/Forks.html

7.1 顯示Process資訊

顯示所有Process(gdb) i inferiors

顯示目前Process
(gdb) i inferior

7.2 結束特定Process
(gdb) kill inferior 1

7.3 自動切換新Process

自動切換到新Process
(gdb) set follow-exec-mode new

8. gdb其他東西

因為比較少用所以就先放這

8.1 display持續顯示變數內容,這樣就不用一直打指令顯示

8.2 catchpint抓exception,syscall,fork,signal等等
https://sourceware.org/gdb/onlinedocs/gdb/Set-Catchpoints.html

8.3 使用command bt-num可以在gdb寫一些指令指定在中斷點發生時要做的事情, 例如列印變數之類的, 類似巨集

8.4 使用shell執行指令

8.5 結合python自動化使用,和一些gdb技巧
https://jaredcjr.blogspot.com/2016/08/gdbdebug.html



留言