gdb
命令
通用命令
📖GDB Reference 🔗偵錯程式 GDB 常用功能
-
x
/ [Length][Format: t o d x f a c s] [Address expression b-8 h-16 w-32 g-64\ ] 📎GDB Command Reference : x -
p
/t-2 o-8 d-10 x-16 f-loat a-ddress c-har s-tring [var]- ⚠️ 要注意區分,x 是掃描記憶體,因此後面跟的直接是記憶體地址, 而 p 是輸出變數的值,因此後面想跟地址的話,需要取其內容,即加上
*
- 關於
*
,很多命令地址前面都要加星號,因為不加星號的一個地址,是被當成函式來看待的
- ⚠️ 要注意區分,x 是掃描記憶體,因此後面跟的直接是記憶體地址, 而 p 是輸出變數的值,因此後面想跟地址的話,需要取其內容,即加上
-
s n
:C 語言級別的單步執行;si ni
彙編級別的單步執行 -
i [line] / [locals] / [vtbl] / [args] / [checkpoints] / [breakpoints]
-
info line [line] / [function] / [*addr]
:顯示原始碼對應的記憶體中的起始結束地址 -
info vtbl [objs]
:直接檢視物件的虛擬函式表(也可以型別轉換的形式列印出來,參考C++類的記憶體分配,基本思想就是:物件的第一塊記憶體放的就是虛表,虛表是一個函式指標陣列,因此可以先將物件地址轉換為指向指標的指標,然後對其取內容,就得到了虛表指標。把這個值轉換為指向指標的指標,即得虛表)
-
-
set print array-indexes on
:列印陣列的時候顯示 index -
set disassemble next-line on
,disassemble
-
set [args] / [register] / [*address] = [val]
:設定引數、暫存器值、記憶體處值 -
jump [*address]
:跳轉到指定地址處執行,return [val]
:直接返回。都可以改變程式走向。 -
shell [cmd]
:執行 shell 命令 -
rbreak [regex]
:在所有滿足正規表示式的函式處打斷點
多程序/執行緒除錯
gdb [pid]
:除錯正在執行的程序,或者進去後attch [pip]
例子
- 列印棧內容(你打陣列肯定也行):不妨設 $rsp 中存放的是 0x1234
p $rsp => (void*)0x1234
x/10dw $rsp
或x/10dw 0x1234
,即用x
命令直接把棧那一塊記憶體掃描出來p *(int (*)[10])0x1234
把棧頂地址型別轉換為一個指向陣列的指標,然後 print 這個陣列 val 的值(所以要加*
),即棧的內容p (int [10])*0x1234
把棧頂的內容直接變成一個陣列,然後輸出p *0x1234@6
注意@
的用法,其左邊必須是你想檢視記憶體處的值,可以直接輸出後面的六個變數
類似的p *argv@argc
,也是先取內容轉換為變數,再輸出- 總結一下,用 x 就是直接掃描記憶體了,簡單粗暴;用 p 則是要把你想看的記憶體區域轉化成一個變數,一個 val,不管是 int 還是 int 陣列,不管是怎麼型別轉換,反正基本思想是把記憶體當成一個變數進行輸出。最好還是用 x ,因為效果一樣,用 p 你還需要先得到 rsp 裡面的值
- 檢視虛表 略
- 運用 core 檔案:
gdb debug core
進入之後,disassemble
,可以看到=>
指向的就是執行出錯的地方