dump 分析模式之 INCORRECT STACK TRACE
生活随笔
收集整理的這篇文章主要介紹了
dump 分析模式之 INCORRECT STACK TRACE
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
dump 分析模式之 INCORRECT STACK TRACE 翻譯自 MDA-Anthology Page288
?
初學(xué)者常犯的錯誤是認為 WinDbg 的 !analyze 和 kv 給出的信息是準確的. ?
WinDbg 只是一個工具, 有時候會缺少一些必要的信息來得到正確的棧信息, 因此我們需要自己明辨正確的與錯誤的棧信息. 我稱之為 Incorrect Stack Trace, 它通常有以下特征: ?
0:011> k
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
0184e434 7c830b10 0×184e5bf
0184e51c 7c81f832 ntdll!RtlGetFullPathName_Ustr+0×15b
0184e5f8 7c83b1dd ntdll!RtlpLowFragHeapAlloc+0xc6a
00099d30 00000000ntdll!RtlpLowFragHeapFree+0xa7
以上棧信息基本具備了錯誤棧信息的所有性質(zhì). 初看像是堆破壞, 因為運行時的堆分配與釋放函數(shù)出現(xiàn)在了棧中. 但如果我們再想想就會發(fā)現(xiàn) HeapFree 函數(shù)不應(yīng)調(diào)用 HeapAlloc 函數(shù), 而接下來更不應(yīng)該調(diào)用 GetFullPathName. 所以這個棧信息是無意義的. ?
那我們能怎樣呢? 檢視 raw 棧信息并構(gòu)造出真正的棧. 我們可以輕松地從 BaseThreadStart+0×34 開始遍歷所有幀直到?jīng)]有任何函數(shù)調(diào)用了或都已到棧頂. 當一個函數(shù)被調(diào)用的時候 EBP 會像下圖那樣連起來 (如果沒有被優(yōu)化掉, 對于大多數(shù)編譯成立). ?
0:011> !teb
TEB at 7ffd8000
ExceptionList: 0184ebdc
StackBase: 01850000
StackLimit: 01841000
...
0:011> dds 01841000 01850000
01841000 00000000
…
…
…
0184eef0 0184ef0c0184eef4 7615dff2 localspl!SplDriverEvent+0×21
0184eef8 00bc3e08
...
0184ef0c 0184ef300184ef10 7615f9d0
localspl!PrinterDriverEvent+0×46
0184ef14 00bc3e08
0184ef18 00000003
...
0184ef2c 00bafcc0
0184ef30 0184f3f80184ef34 7614a9b4 localspl!SplAddPrinter+0×5f3
0184ef38 00c3ec58
...
0184ff30 0184ff840184ff34 77c75286 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×3a
0184ff38 0184ff4c
0184ff3c 77c75296 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×4a
0184ff40 7c82f2fc ntdll!RtlLeaveCriticalSection
...
0184ff84 0184ff8c0184ff88 77c5778f RPCRT4!RecvLotsaCallsWrapper+0xd
0184ff8c 0184ffac0184ff90 77c5f7dd RPCRT4!BaseCachedThreadRoutine+0×9d
...
0184ffac 0184ffb80184ffb0 77c5de88 RPCRT4!ThreadStartRoutine+0×1b
0184ffb4 00088258
0184ffb80184ffec
0184ffbc 77e6608b kernel32!BaseThreadStart+0×34 接下來我們需要用指定了基址的 k 命令來顯示棧信息. 在本例中最后的有效 EBP 地址是 0184eef0. ?
0:011> k L=0184eef0
ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong.
0184eef0 7615dff2 0×184e5bf 0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21
0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46
0184f3f8 761482de localspl!SplAddPrinter+0×5f3
0184f424 74067c8f localspl!LocalAddPrinterEx+0×2e
0184f874 74067b76 SPOOLSS!AddPrinterExW+0×151
0184f890 01007e29 SPOOLSS!AddPrinterW+0×17
0184f8ac 01006ec3 spoolsv!YAddPrinter+0×75
0184f8d0 77c70f3b spoolsv!RpcAddPrinter+0×37
0184f8f8 77ce23f7 RPCRT4!Invoke+0×30
0184fcf8 77ce26ed RPCRT4!NdrStubCall2+0×299
0184fd14 77c709be RPCRT4!NdrServerCall2+0×19
0184fd48 77c7093f RPCRT4!DispatchToStubInCNoAvrf+0×38
0184fd9c 77c70865 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0×117
0184fdc0 77c734b1 RPCRT4!RPC_INTERFACE::DispatchToStub+0xa3
0184fdfc 77c71bb3 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0×42c
0184fe20 77c75458 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0×127
0184ff84 77c5778f RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×430
0184ff8c 77c5f7dd RPCRT4!RecvLotsaCallsWrapper+0xd 棧信息現(xiàn)在看起來有意義多了, 但我們?nèi)匀粵]有看到 BaseThreadStart+0×34. 默認情況下 WinDbg 只顯示一定數(shù)量的棧幀. 所以我們需要指定棧幀的數(shù)量, 比如 100: ?
0:011> k L=0184eef0 100
ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong.
0184eef0 7615dff2 0×184e5bf
0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21
0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46
...
0184ffac 77c5de88 RPCRT4!BaseCachedThreadRoutine+0×9d
0184ffb8 77e6608b RPCRT4!ThreadStartRoutine+0×1b
0184ffec 00000000 kernel32!BaseThreadStart+0×34 現(xiàn)在我們的棧信息看起來更好了. 還有一個完整的示例在 ? Manual Stack Track ? Reconstruction, 本書第 157 頁. ?
此外, incorrect stack trace 也會發(fā)生在沒有符號信息的時候. 這種情況下, 通常棧幀之間會有找不到符號的警告: ?
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
00b2f42c 091607aa mydll!foo+0×8338
00b2f4cc 7c83ab9e mydll!foo+0×8fe3
00b2f4ec 7c832d06 ntdll!RtlFindNextActivationContextSection+0×46
00b2f538 001a5574 ntdll!RtlFindActivationContextSectionString+0xe1
00b2f554 7c8302b3 0×1a5574
00b2f560 7c82f9c1 ntdll!RtlpFreeToHeapLookaside+0×22
00b2f640 7c832b7f ntdll!RtlFreeHeap+0×20e
001dd000 00080040 ntdll!LdrUnlockLoaderLock+0xad
001dd00c 0052005c 0×80040
001dd010 00470045 0×52005c
0052005c 00000000 0×470045
初學(xué)者常犯的錯誤是認為 WinDbg 的 !analyze 和 kv 給出的信息是準確的. ?
WinDbg 只是一個工具, 有時候會缺少一些必要的信息來得到正確的棧信息, 因此我們需要自己明辨正確的與錯誤的棧信息. 我稱之為 Incorrect Stack Trace, 它通常有以下特征: ?
- WinDbg給出警告: "Following frames may be wrong"
- 棧底函數(shù)不是 kernel32!BaseThreadStart (用戶模式)
- 無意義的函數(shù)調(diào)用
- 反匯編后的函數(shù)的代碼很奇怪, 或不像編譯器生成的代碼
- ChildEBP 和 RetAddr 的地址沒有意義
0:011> k
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
0184e434 7c830b10 0×184e5bf
0184e51c 7c81f832 ntdll!RtlGetFullPathName_Ustr+0×15b
0184e5f8 7c83b1dd ntdll!RtlpLowFragHeapAlloc+0xc6a
00099d30 00000000ntdll!RtlpLowFragHeapFree+0xa7
以上棧信息基本具備了錯誤棧信息的所有性質(zhì). 初看像是堆破壞, 因為運行時的堆分配與釋放函數(shù)出現(xiàn)在了棧中. 但如果我們再想想就會發(fā)現(xiàn) HeapFree 函數(shù)不應(yīng)調(diào)用 HeapAlloc 函數(shù), 而接下來更不應(yīng)該調(diào)用 GetFullPathName. 所以這個棧信息是無意義的. ?
那我們能怎樣呢? 檢視 raw 棧信息并構(gòu)造出真正的棧. 我們可以輕松地從 BaseThreadStart+0×34 開始遍歷所有幀直到?jīng)]有任何函數(shù)調(diào)用了或都已到棧頂. 當一個函數(shù)被調(diào)用的時候 EBP 會像下圖那樣連起來 (如果沒有被優(yōu)化掉, 對于大多數(shù)編譯成立). ?
0:011> !teb
TEB at 7ffd8000
ExceptionList: 0184ebdc
StackBase: 01850000
StackLimit: 01841000
...
0:011> dds 01841000 01850000
01841000 00000000
…
…
…
0184eef0 0184ef0c0184eef4 7615dff2 localspl!SplDriverEvent+0×21
0184eef8 00bc3e08
...
0184ef0c 0184ef300184ef10 7615f9d0
localspl!PrinterDriverEvent+0×46
0184ef14 00bc3e08
0184ef18 00000003
...
0184ef2c 00bafcc0
0184ef30 0184f3f80184ef34 7614a9b4 localspl!SplAddPrinter+0×5f3
0184ef38 00c3ec58
...
0184ff30 0184ff840184ff34 77c75286 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×3a
0184ff38 0184ff4c
0184ff3c 77c75296 RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×4a
0184ff40 7c82f2fc ntdll!RtlLeaveCriticalSection
...
0184ff84 0184ff8c0184ff88 77c5778f RPCRT4!RecvLotsaCallsWrapper+0xd
0184ff8c 0184ffac0184ff90 77c5f7dd RPCRT4!BaseCachedThreadRoutine+0×9d
...
0184ffac 0184ffb80184ffb0 77c5de88 RPCRT4!ThreadStartRoutine+0×1b
0184ffb4 00088258
0184ffb80184ffec
0184ffbc 77e6608b kernel32!BaseThreadStart+0×34 接下來我們需要用指定了基址的 k 命令來顯示棧信息. 在本例中最后的有效 EBP 地址是 0184eef0. ?
0:011> k L=0184eef0
ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong.
0184eef0 7615dff2 0×184e5bf 0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21
0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46
0184f3f8 761482de localspl!SplAddPrinter+0×5f3
0184f424 74067c8f localspl!LocalAddPrinterEx+0×2e
0184f874 74067b76 SPOOLSS!AddPrinterExW+0×151
0184f890 01007e29 SPOOLSS!AddPrinterW+0×17
0184f8ac 01006ec3 spoolsv!YAddPrinter+0×75
0184f8d0 77c70f3b spoolsv!RpcAddPrinter+0×37
0184f8f8 77ce23f7 RPCRT4!Invoke+0×30
0184fcf8 77ce26ed RPCRT4!NdrStubCall2+0×299
0184fd14 77c709be RPCRT4!NdrServerCall2+0×19
0184fd48 77c7093f RPCRT4!DispatchToStubInCNoAvrf+0×38
0184fd9c 77c70865 RPCRT4!RPC_INTERFACE::DispatchToStubWorker+0×117
0184fdc0 77c734b1 RPCRT4!RPC_INTERFACE::DispatchToStub+0xa3
0184fdfc 77c71bb3 RPCRT4!LRPC_SCALL::DealWithRequestMessage+0×42c
0184fe20 77c75458 RPCRT4!LRPC_ADDRESS::DealWithLRPCRequest+0×127
0184ff84 77c5778f RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0×430
0184ff8c 77c5f7dd RPCRT4!RecvLotsaCallsWrapper+0xd 棧信息現(xiàn)在看起來有意義多了, 但我們?nèi)匀粵]有看到 BaseThreadStart+0×34. 默認情況下 WinDbg 只顯示一定數(shù)量的棧幀. 所以我們需要指定棧幀的數(shù)量, 比如 100: ?
0:011> k L=0184eef0 100
ChildEBP RetAddr WARNING: Frame IP not in any known module. Following frames may be wrong.
0184eef0 7615dff2 0×184e5bf
0184ef0c 7615f9d0 localspl!SplDriverEvent+0×21
0184ef30 7614a9b4 localspl!PrinterDriverEvent+0×46
...
0184ffac 77c5de88 RPCRT4!BaseCachedThreadRoutine+0×9d
0184ffb8 77e6608b RPCRT4!ThreadStartRoutine+0×1b
0184ffec 00000000 kernel32!BaseThreadStart+0×34 現(xiàn)在我們的棧信息看起來更好了. 還有一個完整的示例在 ? Manual Stack Track ? Reconstruction, 本書第 157 頁. ?
此外, incorrect stack trace 也會發(fā)生在沒有符號信息的時候. 這種情況下, 通常棧幀之間會有找不到符號的警告: ?
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
00b2f42c 091607aa mydll!foo+0×8338
00b2f4cc 7c83ab9e mydll!foo+0×8fe3
00b2f4ec 7c832d06 ntdll!RtlFindNextActivationContextSection+0×46
00b2f538 001a5574 ntdll!RtlFindActivationContextSectionString+0xe1
00b2f554 7c8302b3 0×1a5574
00b2f560 7c82f9c1 ntdll!RtlpFreeToHeapLookaside+0×22
00b2f640 7c832b7f ntdll!RtlFreeHeap+0×20e
001dd000 00080040 ntdll!LdrUnlockLoaderLock+0xad
001dd00c 0052005c 0×80040
001dd010 00470045 0×52005c
0052005c 00000000 0×470045
總結(jié)
以上是生活随笔為你收集整理的dump 分析模式之 INCORRECT STACK TRACE的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Atitit 发帖机系列(7) 词法分析
- 下一篇: 栈溢出笔记1.6 地址问题(1)