Mac*_*ade 10 c windows stack backtrace
好的,关于SO的第二个问题在一天之内.看起来像Windows编程让我开心......:S
我正在尝试在Win32可执行文件上获取函数调用堆栈.
今天早上,我也问了一个问题:
现在,我很确定该StackWalk64功能是关键.我已经阅读了一些关于如何使用它的文章,以及MS文档.
它实际上在我的测试程序中显示帧,所以它有点工作......
问题是我无法从堆栈信息中检索符号名称.
我正在使用这个SymGetSymFromAddr64功能UnDecorateSymbolName.但我只得到垃圾人物.
这是我的代码.希望它不要乱,因为我不熟悉Windows编程:
void printStack( void )
{
BOOL result;
HANDLE process;
HANDLE thread;
CONTEXT context;
STACKFRAME64 stack;
ULONG frame;
IMAGEHLP_SYMBOL64 symbol;
DWORD64 displacement;
char name[ 256 ];
RtlCaptureContext( &context );
memset( &stack, 0, sizeof( STACKFRAME64 ) );
process = GetCurrentProcess();
thread = GetCurrentThread();
displacement = 0;
stack.AddrPC.Offset = context.Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
for( frame = 0; ; frame++ )
{
result = StackWalk64
(
IMAGE_FILE_MACHINE_I386,
process,
thread,
&stack,
&context,
NULL,
SymFunctionTableAccess64,
SymGetModuleBase64,
NULL
);
symbol.SizeOfStruct = sizeof( IMAGEHLP_SYMBOL64 );
symbol.MaxNameLength = 255;
SymGetSymFromAddr64( process, ( ULONG64 )stack.AddrPC.Offset, &displacement, &symbol );
UnDecorateSymbolName( symbol.Name, ( PSTR )name, 256, UNDNAME_COMPLETE );
printf
(
"Frame %lu:\n"
" Symbol name: %s\n"
" PC address: 0x%08LX\n"
" Stack address: 0x%08LX\n"
" Frame address: 0x%08LX\n"
"\n",
frame,
symbol.Name,
( ULONG64 )stack.AddrPC.Offset,
( ULONG64 )stack.AddrStack.Offset,
( ULONG64 )stack.AddrFrame.Offset
);
if( !result )
{
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
实际输出是:
Frame 0:
Symbol name: ????????????
PC address: 0x00BA2763
Stack address: 0x00000000
Frame address: 0x0031F7E8
Frame 1:
Symbol name: ?????????????
PC address: 0x00BB4FFF
Stack address: 0x00000000
Frame address: 0x0031F940
Frame 2:
Symbol name: ?????????????
PC address: 0x00BB4E2F
Stack address: 0x00000000
Frame address: 0x0031F990
Frame 3:
Symbol name: ?????????????
PC address: 0x75BE3677
Stack address: 0x00000000
Frame address: 0x0031F998
Frame 4:
Symbol name: ?????????????
PC address: 0x770F9D72
Stack address: 0x00000000
Frame address: 0x0031F9A4
Frame 5:
Symbol name: ?????????????
PC address: 0x770F9D45
Stack address: 0x00000000
Frame address: 0x0031F9E4
Frame 6:
Symbol name: ?????????????
PC address: 0x770F9D45
Stack address: 0x00000000
Frame address: 0x0031F9E4
Run Code Online (Sandbox Code Playgroud)
看起来很奇怪堆栈地址总是0 ...任何帮助赞赏:)
谢谢大家!
编辑
我正在寻找一个简单的C解决方案,没有第三方库......
您已设置symbol.MaxNameLength为255,但您在堆栈上分配了"符号" IMAGEHLP_SYMBOL64 symbol;.该类型定义为:
typedef struct _IMAGEHLP_SYMBOL64 {
DWORD SizeOfStruct;
DWORD64 Address;
DWORD Size;
DWORD Flags;
DWORD MaxNameLength;
TCHAR Name[1];
} IMAGEHLP_SYMBOL64;
Run Code Online (Sandbox Code Playgroud)
请注意,Name字段默认只有一个字符.如果要存储更大的名称,则需要执行以下操作:
const int MaxNameLen = 255;
IMAGEHLP_SYMBOL64* pSymbol =
malloc(sizeof(IMAGEHLP_SYMBOL64)+MaxNameLen*sizeof(TCHAR));
pSymbol->MaxNameLength = MaxNameLen;
Run Code Online (Sandbox Code Playgroud)
否则,SymGetSymFromAddr64()很可能会覆盖内存.以下是该结构的帮助页面(强调添加):
MaxNameLength:Name成员可以包含的字符串的最大长度(以字符为单位),不包括以null结尾的字符.由于符号名称的长度可能不同,因此该数据结构 由调用者分配.使用此成员,以便库知道符号名称可以使用多少内存.