Windbg檢視呼叫堆疊 k

2021-08-10 23:01:29 字數 3226 閱讀 3542

無論是分析程式崩潰原因,還是解決程式hang問題,我們最常檢視的就是程式呼叫堆疊。學會windbg呼叫堆疊命令,以及理解堆疊中的各個引數的意義就顯得至關重要。

上圖就是乙個典型的windbg堆疊,如果不理解childebp、retaddr、args to child等引數意義,以及它們之間的來龍去脈,除錯工作將很難進行下去。

函式的引數傳遞有二種方式:堆疊方式、暫存器方式。如果是堆疊方式傳遞的,就需要定義引數在堆疊中的傳遞順序,並約定函式被呼叫之後,由誰來平衡堆疊;如果是暫存器方式傳遞的,就需要確定引數存放在哪個暫存器中。每一種方式都有其優缺點,而且與使用的程式語言有關係,不存在哪種方式好與壞。

如visual studio中的c++工程,可以c++ --> 高階 --> 呼叫約定中進行設定:

常用的呼叫約定型別有__cdecl、stdcall、pascal、fastcall。除了fastcall可以支援以暫存器的方式來傳遞函式引數外,其他的都是通過堆疊的方式來傳遞函式引數的。

堆疊是一種「後進先出」的資料結構,esp暫存器始終指向棧頂。棧中資料位址從底部到頂部依次減小,也就是說,棧底對應高位址,棧頂對應低位址。

呼叫函式時,呼叫者依次把引數壓棧,然後呼叫函式,函式被呼叫之後,在堆疊中取得引數資料。函式呼叫結束以後,堆疊需要恢復到函式呼叫之前的樣子,具體由呼叫者來恢復還是由函式自身來恢復,根據不同的呼叫約定型別採用不同的方式。

約定型別

__cdecl

stdcall

pascal

fastcall

引數傳遞順序

從右到左

從右到左

從左到右

使用暫存器

平衡堆疊者

呼叫者函式自身

函式自身

函式自身

cdcel是c/c++/mfc程式預設的呼叫約定。

stdcall是win32中絕大多數 api函式的約定方式,也有少部分使用cdcel約定方式,如wsprintf等。

在windows c/c++開發中常用的就是__cdecl和stdcall這2種呼叫約定。

假設呼叫函式int add(int a, int b), 按照不同的呼叫約定來呼叫它。從呼叫者的視角來看,其彙編**分別表示如下:

__cdecl

push b     ;引數按從右到左傳遞

push a

call

addadd

esp, 8

;呼叫者在函式外部平衡堆疊

stdcall

push b     ;引數按從右到左傳遞

push a

call

add;函式自己內部平衡堆疊

在函式呼叫過程中,引數入棧的過程:

上圖中,ebp和函式返回位址都是位址,在32位程式中位址佔4個位元組。在函式的一次呼叫過程中ebp是不會變化的,函式呼叫完之後會將ebp恢復為暫存在堆疊中的原ebp值。所以,通過ebp可以獲取函式各個引數的值:

引數a = ebp + 0x8

引數b = ebp + 0xc

[~thread] k[b|p|p|v] [c] [n] [f] [l] [m] [framecount] [~thread] k[b|p|p|v] [c] [n] [f] [l] [m] = baseptr [framecount] [~thread] k[b|p|p|v] [c] [n] [f] [l] [m] = baseptr stackptr instructionptr [~thread] kd [wordcount]

引數:

thread  指定顯示哪個執行緒的呼叫堆疊。如果省略該引數,則顯示當前執行緒的呼叫堆疊。*顯示所有執行緒的呼叫堆疊。

b  顯示每個函式的前3個引數。

p  顯示每個函式的所有引數。引數列表包括每個引數的型別、名稱、值。

如上圖,可以看到函式的每個引數的型別,名稱,值。但是這個需要有對應的符號檔案(pdb),沒有應用程式的符號檔案只能顯示系統api的引數資訊。

p  類似p。不同之處在於,每個引數顯示在單獨的行上面。

n  顯示呼叫堆疊中每幀的序號(一般稱棧幀,如棧幀3)。

framecount  指定顯示呼叫堆疊的幀數,即呼叫堆疊的深度。預設為16進製制格式。預設幀數為0x14=20

呼叫堆疊顯示出來之後,如果想知道呼叫某幀時的相關資訊,可以使用.frame來切換指定幀,然後就可以使用如dv命令顯示區域性變數等。

.frame

[/c]

[/r]

[framenumber]

/c

/r  顯示執行該幀時暫存器的值。

framenumber  指定要切換到的幀號。

kbn顯示堆疊資訊:

棧幀12:

呼叫add函式,引數1=00000001,引數2=000000002,ebp=0015fc0c

根據圖1得知,函式返回位址=ebp+4,我們使用dw命令來驗證。

參考:

《軟體除錯》張銀奎 著

《格蠹彙編》張銀奎 著

《加密與解密》第三版 段剛編著

怎麼刪除?

gdb 檢視函式呼叫堆疊(frame概念)

1,使用bt backtrace 命令檢視當前堆疊 gdb bt 0 muduo poller poll this 0x62e010,timeoutms 10000,activechannels 0x7fffffffe3c0 at poller.cc 31 1 0x0000000000403f60 ...

windbg 檢視函式位址

有時候需要檢視函式位址,官方位址 示例 x d f lec teacher c 以下命令將查詢 mymodule 中包含字串 spin 的所有符號。0 000 x mymodule spin 以下命令快速查詢 mymodule 中的 downloadminor 和 downloadmajor 符號。...

WinDbg 檢視函式的引數

檢視函式 funnewwlxloggedoutsas 的引數kd kb childebp retaddrargs to child 0006edc8 7c9859f2 00000000 c00000050006f0d0 ntdll dbgbreakpoint 0006ee08 7c986101 00...