在呼叫棧中挖掘異常指標

2021-06-13 07:05:32 字數 4548 閱讀 6637

大家也許經常盯著呼叫棧,尋找捕捉到的異常以及在**發生的異常。

childebp retaddr  args to child

030c21d0 76df3448 00000000 030c6138 76db6b0d ntdll!dbgbreakpoint

030c21dc 76db6b0d 030c2204 77b8d585 030c220c ole32!peekmessageexceptionfilter+0x42

030c21e4 77b8d585 030c220c 00000000 030c220c ole32!cclimodalloop::mypeekmessage+0x41

030c220c 77f36992 030c25d0 030c6128 030c22e8 msvcrt!_except_handler3+0x61

030c2230 77f36964 030c25d0 030c6128 030c22e8 ntdll!executehandler2+0x26

030c22d8 77f36884 030c1000 030c22e8 00010007 ntdll!executehandler+0x24

030c25b8 77f6e0dd 030c25d0 00000000 00000000 ntdll!rtlraiseexception+0x3d

030c262c 77d3c239 77d4a4b6 77d3e2c5 030c3767 ntdll!rtldeactivateactivationcontextunsafefast+0x233

030c2630 77d4a4b6 77d3e2c5 030c3767 030c26a0 user32!usercallwinproccheckwow+0x167

030c2634 77d3e2c5 030c3767 030c26a0 77d4a46f user32!_nlg_return2

030c265c 77d3e288 030c57b4 ffffffff 030c2688 user32!__local_unwind2+0x70

030c2688 77f36992 030c26f8 030c57b4 030c27a4 user32!_except_handler3+0xd5

030c26ac 77f36964 030c26f8 030c57b4 030c27a4 ntdll!executehandler2+0x26

030c2a74 77b8d36d 030c6128 77b8d36d 00000000 ntdll!executehandler+0x24

030c2a9c 77b8d59d 030c6128 030c2ac0 00000000 msvcrt!__global_unwind2+0x18

030c2ac0 77f36992 030c2ba4 030c6128 030c2bc0 msvcrt!_except_handler3+0x75

030c2ae4 77f36964 030c2ba4 030c6128 030c2bc0 ntdll!executehandler2+0x26

030c2b8c 77f36796 030c1000 030c2bc0 030c2ba4 ntdll!executehandler+0x24

030c2b8c 77b7aa54 030c1000 030c2bc0 030c2ba4 ntdll!kiuserexceptiondispatcher+0xe

030c3300 77b7b4dc 030c3324 7715b1b4 00000000 msvcrt!_woutput_l+0x18

這裡可以看到,peekmessageexceptionfilter函式捕捉到了乙個異常。那是什麼異常?首先,異常過濾函式會被傳入乙個exception_pointers結果作為引數。

typedef struct _exception_pointers  exception_pointers, *pexception_pointers;

現在,我們看一下peekmessageexceptionfilter的引數:

030c21dc 76db6b0d 030c2204 77b8d585 030c220c ole32!peekmessageexceptionfilter+0x42

0:0000> dd 030c2204 l2

030c2204 030c25d0 030c22e8

-------- --------

.exr     .cxr

第乙個值是exceptionrecord的指標,第二個值是contextrecord的指標。你可以通過輸入命令.exr 030c25d0檢視異常資訊,還可以通過.cxr 030c22e8檢視異常的上下文內容(比如,異常發生時在執行什麼指令)。這兩個值也作為executehandler2函式的第一和第三個引數出現。

(譯註:.cxr實際上會執行切換上下文的操作。)

現在就用.exr 030c25d0看一下異常資訊,異常**是c015000f,正好是status_sxs_early_deactivation。切換到發生異常的上下文,呼叫棧顯示如下:

childebp retaddr

030c262c 77d3c239 77d4a4b6 77d3e2c5 030c3767 ntdll!rtldeactivateactivationcontextunsafefast+0x233

030c2630 77d4a4b6 77d3e2c5 030c3767 030c26a0 user32!usercallwinproccheckwow+0x167

030c2634 77d3e2c5 030c3767 030c26a0 77d4a46f user32!_nlg_return2

030c265c 77d3e288 030c57b4 ffffffff 030c2688 user32!__local_unwind2+0x70

030c2688 77f36992 030c26f8 030c57b4 030c27a4 user32!_except_handler3+0xd5

030c26ac 77f36964 030c26f8 030c57b4 030c27a4 ntdll!executehandler2+0x26

030c2a74 77b8d36d 030c6128 77b8d36d 00000000 ntdll!executehandler+0x24

030c2a9c 77b8d59d 030c6128 030c2ac0 00000000 msvcrt!__global_unwind2+0x18

030c2ac0 77f36992 030c2ba4 030c6128 030c2bc0 msvcrt!_except_handler3+0x75

030c2ae4 77f36964 030c2ba4 030c6128 030c2bc0 ntdll!executehandler2+0x26

030c2b8c 77f36796 030c1000 030c2bc0 030c2ba4 ntdll!executehandler+0x24

030c2b8c 77b7aa54 030c1000 030c2bc0 030c2ba4 ntdll!kiuserexceptiondispatcher+0xe

030c3300 77b7b4dc 030c3324 7715b1b4 00000000 msvcrt!_woutput_l+0x18

哇,在處理乙個異常的時候又發生了另外乙個異常。(碰巧這次在原來的呼叫棧裡一眼就能看出來,但是通常情況下,找到後面的異常可能沒那麼容易。)

拿這個異常重複一次上面的練習:

0:000> .exr 030c2ba4

exceptionaddress: 77b7aa54 (msvcrt!_woutput_l+0x00000018)

exceptioncode: c00000fd (stack overflow)

exceptionflags: 00000000

numberparameters: 2

parameter[0]: 00000001

parameter[1]: 030c2e88

0:000> .cxr 030c2bc0

eax=030c33b0 ebx=00000000 ecx=0000005c edx=00000000 esi=030c33c4 edi=030c33c4

eip=77b7aa54 esp=030c2e8c ebp=030c3300 iopl=0 nv up ei pl nz na pe nc

cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202

msvcrt!_woutput_l+0x18:

001b:77b7aa54 53 push ebx

哈哈,原來sxs異常是由堆疊溢位引起的。在這個上下文裡,你可以使用「k」命令檢視是如何引發這個結果的。

這個bug是由於錯誤的遞迴導致的棧溢位引發的。當時執行緒正在為呼叫乙個com物件,等待它返回。而這個時候又收到了乙個新的請求。問題的細節在這裡並不重要;本文的目的就是展示如何在呼叫棧上挖掘異常指標,從中了解引發問題的win32異常的資訊。

你知道嗎?你可以在異常中解退呼叫棧

原文作者 bill horst 解退乙個異常堆疊的能力是visual basic.net 2005的乙個新引進的特性。當調式器觸發了乙個異常,你可以解退這個堆疊以便於使用 編輯器修復這個異常並繼續調式 修改後的 這個異常輔助使用者介面有乙個 enable editing 選項,這個選項可以在當前so...

你知道嗎?你可以在異常中解退呼叫棧

原文作者 bill horst 解退乙個異常堆疊的能力是visual basic.net 2005的乙個新引進的特性。當調式器觸發了乙個異常,你可以解退這個堆疊以便於使用 編輯器修復這個異常並繼續調式 修改後的 這個異常輔助使用者介面有乙個 enable editing 選項,這個選項可以在當前so...

std thread 中的異常會丟失呼叫棧

金慶的專欄 2019.9 主函式中的異常生成core檔案能看到呼叫棧,但是 std thread 子執行緒中的異常生成 core 檔案的呼叫棧如下 program received signal sigabrt,aborted.switching to thread 0x7f18f00ab700 l...