Stack Walk with DIA SDK
2007-03-26 21:05 atempcode 阅读(2663) 评论(0) 编辑 收藏 举报DIA SDK (Debug Interface Access SDK) 是微软随Visual Studio发布的一套解析PDB的SDK. 如何用它分析PDB文件, MS有一个sample程序叫DIA2dump, 在x:\Program Files\Microsoft Visual Studio 8\DIA SDK\Samples\DIA2Dump\目录下. 这个sample没有涉及到的是Stack Walk, 微软这方面的文档也很少. 理论上自己写一个Stack walk应该也可以, 但是考虑到各种call convention, 32bit/64-bit, 本地变量, 还有FPO, oh my, 还是老老实实用DIA的实现吧, 一套code, 32位, 64位通用.
跟stack walk有关的两个interfaces是IDiaStackWalker和IDiaStackWalkHelper. 先讲IDiaStackWalker. 跟x86平台有关的只有一个function:
HRESULT getEnumFrames( IDiaStackWalkHelper* pHelper, IDiaEnumStackFrames** ppEnum );
就这麽简单. CoCreate一个实例:
IDiaStackWalker* pStackWalker;
HRESULT hr = CoCreateInstance(CLSID_DiaStackWalker,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiaStackWalker,
(void**) &pStackWalker);
一个call就可以得到IDiaEnumStackFrames*, enum里的每个stack frame也是唾手可得. 它的奥妙全在IDiaStackWalkHelper里了.
IDiaStackWalkHelper这个interface全部要用户来实现. 一堆接口函数.
get_registerValue和put_registerValue是和register有关. 想要stack walk, 一些寄存器象esp, ebp的值是必须要知道;
searchForReturnAddress和searchForReturnAddressStart以我的经验可以不实现, 直接返回E_NOTIMPL就可以了;
readMemory必须实现. DIA会用这个函数去读stack里的内容, code section的内容, 以及一些特殊寄存器的值所指向的内存.
剩下的都可以在DIA的其他接口和函数来实现了:
frameForVA:
IDiaSession::getEnumTables HRESULT getEnumTables ( IDiaEnumTables** ppEnumTables ); IDiaEnumFrameData::frameByVA HRESULT frameByVA( ULONGLONG virtualAddress, IDiaFrameData** frame );
symbolForVA:
IDiaSession::findSymbolByVA HRESULT findSymbolByVA ( ULONGLONG va, SymTagEnum symtag, IDiaSymbol** ppSymbol );
imageForVA:
IDiaSession::get_loadAddress HRESULT get_loadAddress ( ULONGLONG* pRetVal );
pdataForVA:
我们debugger的目标程序中没有exception handle, 所以偷个懒, 返回E_NOTIMPL, 呵呵.