檢視棧資訊
當程式被停住了,你需要做的第一件事就是檢視程式是在哪裡停住的。當你的程式調用了一個函數,函數的位址,函數參數,函數内的局部變量都會被壓入“棧”(Stack)中。你可以用GDB指令來檢視目前的棧中的資訊。
下面是一些檢視函數調用棧資訊的GDB指令:
backtrace
bt 列印目前的函數調用棧的所有資訊。如:
(gdb) bt
#0 func (n=250) at tst.c:6
#1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6
從上可以看出函數的調用棧資訊:__libc_start_main --> main() --> func()
backtrace <n>
bt <n> n是一個正整數,表示隻列印棧頂上n層的棧資訊。
backtrace <-n>
bt <-n> -n表一個負整數,表示隻列印棧底下n層的棧資訊。
如果你要檢視某一層的資訊,你需要在切換目前的棧,一般來說,程式停止時,最頂層的棧就是目前棧,如果你要檢視棧下面層的詳細資訊,首先要做的是切換目前棧。
frame <n>
f <n> n是一個從0開始的整數,是棧中的層編号。比如:frame 0,表示棧頂,frame 1,表示棧的第二層。
up <n> 表示向棧的上面移動n層,可以不打n,表示向上移動一層。
down <n>表示向棧的下面移動n層,可以不打n,表示向下移動一層。
上面的指令,都會列印出移動到的棧層的資訊。如果你不想讓其打出資訊。你可以使用這三個指令:
select-frame <n> 對應于 frame 指令。
up-silently <n> 對應于 up 指令。
down-silently <n> 對應于 down 指令。
檢視目前棧層的資訊,你可以用以下GDB指令:
frame 或 f 會列印出這些資訊:棧的層編号,目前的函數名,函數參數值,函數所在檔案及行号,函數執行到的語句。
info frame
info f
這個指令會列印出更為詳細的目前棧層的資訊,隻不過,大多數都是運作時的内内位址。比如:函數位址,調用函數的位址,被調用函數的位址,目前的函數是由什麼樣的程式語言寫成的、函數參數位址及值、局部變量的位址等等。如:
(gdb) info f
Stack level 0, frame at 0xbffff5d4:
eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
called by frame at 0xbffff60c
source language c.
Arglist at 0xbffff5d4, args: n=250
Locals at 0xbffff5d4, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8
info args 列印出目前函數的參數名及其值。
info locals 列印出目前函數中所有局部變量及其值。
info catch 列印出目前的函數中的異常處理資訊。