contributed by < hsuedw
>
用一個最簡單的 C 程式來學習如何用 GDB 檢視程式執行期間的記憶體內容。
在 C 語言中,變數被用來代表一塊記憶體空間,這塊記憶體空間可以用來儲存資料,表示數值。這塊記憶體空間就是 C99 Standard 中所謂的 object。
C99 Standard 3.14
object
region of data storage in the execution environment, the contents of which can represent values
一個變數有兩個重要的數字:
$ gcc test.c -g -o test
$ gdb ./test
:
(gdb) l
1 int main()
2 {
3 int i = 1234;
4 return 0;
5 }
(gdb) b 4
Breakpoint 1 at 0x1138: file test.c, line 4.
(gdb) r
Starting program: /home/edward/workspace/linux_2022/gdb/test
Breakpoint 1, main () at test.c:4
4 return 0;
(gdb) p &i
$1 = (int *) 0x7fffffffe23c
(gdb) p sizeof(i)
$2 = 4
如上面實驗步驟所示, 0x7fffffffe23c
就是變數 i
的記憶體位址, 4
就是變數 i
(型別為 int
) 所佔用的記憶體區塊大小。
接下來用 x
指令檢視變數 i
所佔用的記憶體空間中的數值。
參考資料: x command
在這個範例中,用 x
指令檢視記憶體內容時,指定印出格式為 4
個 byte ,且顯示為十六進位 ( x
)。
因為我用的電腦是 Intel x86_64 CPU ,採用 little endian 表示資料,所以由 0x7fffffffe23c
起算 4 個 byte 應到著看。正確的資料應為 0x00 0x00 0x04 0xd2
。而十六進位 0x4d2
就是十進位的 1234
。
在執行 gdb
追蹤程式碼的運作時,可加入 -tui
選項。即使是在命令列模式下, gdb
也可以呈現圖形化介面。
gdb
提示訊息下執行 r
(或 run
)命令時,同時指定要傳給被追蹤程式的參數就可以了。
可以用 break
指令 (或簡寫為 b
) 加上 breakpoint 的位置來設定。
breakpoint 的位置可以是
可以用 i b
這個指令列出目前所有的 breakpoint 。
可以用 i b
指令列出所有的 breakpoint 後,再用 disable
指令加上 breakpoint 的編號暫時讓指定的 breakpoint 失效。
事後可以再用 enable
指令加上 breakpoint 的編號來恢復 breakpoint 的功能。
可以用 i b
指令列出所有的 breakpoint 後,再用 clear
指令加上 breakpoint 的位置來刪除指定的 breakpoint。
n
或 next
指令以 statement 為單位,可以依序單步執行目前函式中的每一個 statement。s
或 step
指令可以進入此函式進行追蹤。i locals
或 p 變數名稱
觀察變數的內容。next x
與 step x
可以指定往下走 x
條 statement。advance
指令可以指定接下來要直接執行到程式的哪一個位置。有點像快轉。不需要一步步地做單步執行。
info locals
命令info locals
命令可以列出目前所有區域變數的內容。
print 變數名稱
print 變數名稱
可以顯示指定變數的內容。
display
命令除了 i locals
與 p 變數名稱
外,還可以用 display
命令設定想要觀察的變數。
每做一次 next
,那些被 display
設定為要觀察的變數的內容就會被自動顯示出來。如下面這個範例中的變數 i
。要注意的是,在 GDB 提示符號 (gdb)
後的 statement 是下一個要執行的 statement。
watch
命令watch
命令可以設定想要觀測的變數。只要該變數的的內容有發生變化, GDB 就會把該變數改變前與改變後的內容印出來。
假設追蹤下列程式碼。
編譯原始碼 (gcc test.c -g -o test
) 後,啟動 gdb
進行追蹤。
print
指令修改變數內容可以用 print 變數名稱 = 新內容
修改變數的內容。
set
指令修改變數內容set
指令有兩種用法
set variable 變數名稱 = 新內容
set (變數名稱 = 新內容)
backtrace
或 bt
指令可以顯示目前函式呼叫堆疊的狀況。
其他關於堆疊的功能可用 help stack
得到說明