如何手工展開函式棧來定位問題

2021-09-20 23:21:32 字數 2044 閱讀 6266

部落格:blog.focus-linux.net     linuxfocus.blog.chinaunix.net

當程式crash的時候,我們可以通過coredump檔案,來定位問題。比如使用bt命令可以完整的展開函式的呼叫棧。但是有些時候,部分棧的資料可能被損壞,導致gdb無法直接顯示函式的呼叫棧。那麼這時就需要我們手工展開函式棧。

關於x86的函式呼叫棧的示意圖基本如下圖所示:

關於引數的壓棧順序,上圖為cdecl方式,這個可以通過編譯選項修改。gcc預設使用cdecl。

下面看一下例子:

#include 

#include 

static int test(

int a,

int b,

int c)

int main()

編譯:gcc -g -wall test.c

進入test,檢視函式呼叫棧:

breakpoint 1, test (a=1, b=2, c=3) at test.c:7

7 return a+b+c;

missing separate debuginfos, use: debuginfo-install glibc-2.11-2.i686

(gdb) bt

#0 test (a=1, b=2, c=3) at test.c:7

#1 0x08048412 in main (

) at test.c:16

那麼現在檢視一下暫存器:

eax 0x1 1

ecx 0x2c0187d8 738297816

edx 0x1 1

ebx 0x73fff4 7602164

esp 0xbffff048 0xbffff048

ebp 0xbffff048 0xbffff048

esi 0x0 0

edi 0x0 0

eip 0x80483c7 0x80483c7 

eflags 0x286 [ pf sf if

]cs 0x73 115

ss 0x7b 123

ds 0x7b 123

es 0x7b 123

fs 0x0 0

gs 0x33 51

得到ebp的位址為0xbffff048,現在檢查這個位址的記憶體

(gdb) x /8x 0xbffff048

0xbffff048: 0xbffff078 0x08048412 0x00000001 0x00000002

0xbffff058: 0x00000003 0x0073fff4 0x00000001 0x00000002

下面分析一下這些記憶體的內容:

1. 0xbffff078:為test的呼叫者,即main函式的bp位址;bp位址即為該函式的棧頂指標。

2. 0x08048412:為test的返回位址,與前面的bt的輸出相符;

3. 後面的0x00000001,0x00000002,0x00000003,為傳給test的三個引數,且引數順序為由右向左壓棧——注意這個順序是可以通過改變編譯引數改變的。

回到main中,驗證一下bp暫存器的內容:

0x08048412 in main (

) at test.c:16

16 int d = test(a, b, c)

;value returned is $2 = 6

(gdb) info registers

eax 0x6 6

ecx 0x39ff7a48 973044296

edx 0x1 1

ebx 0x73fff4 7602164

esp 0xbffff050 0xbffff050

ebp 0xbffff078 0xbffff078

可見bp的位址確實為0xbffff078,與之前的分析相符。

注:關於壓棧順序,引數的傳遞方式等等,都可以通過編譯選項來指定或者禁止的。本文的情況為gcc的預設行為。

如何用棧來管理函式呼叫

每個函式執行前都有乙個起始位置 即被呼叫的位置,存放在 cpu 的 ebp 暫存器中 當函式開始執行後,會有乙個棧頂位置 即執行到當前位置棧裡存放的臨時變數,存放在 cpu 的 ebp 暫存器中 在函式被呼叫的時候,首先將當前函式的起始位置壓住棧中,將 ebp 存放的指標指向這個位置,然後開始執行被...

函式棧幀(用彙編來剖析)

好久沒寫部落格了,學校開始實習,找了乙個極破的地方,站公交將近兩個小時,一天來回就要死了,說是實習,就是變著樣的培訓,一點實習的意思都沒有,辣雞。因為位址空間內的棧是從高位址向低位址生長的,也就是說壓棧順序靠後的反而位址比較低,棧底的位址高於棧頂的位址,下面貼上一段測試 1 include2 3 i...

如何用隨機函式rand5來構造隨機函式rand7

試一下以對話的方式寫博 如果看不到人物頭像,請重新整理頁面獲取最新的css。如果有建議或意見,歡迎到我的微博上跟帖 常規方法 echo rand7 rand7 function rand7 演算法的一些釋疑 晚些時候 gen 0,1 equal probability int rand01 retu...