StackWalk64在Windows上 - 获取符号名 [英] StackWalk64 on Windows - Get symbol name
问题描述
好吧,对SO在一天的第二个问题。看起来像Windows程序设计让我很开心......:•
Alright, second question on SO in one day. Looks like Windows programming makes me happy... : S
目前,我正在试图让一个Win32可执行程序的函数调用堆栈。
I'm currently trying to get the function call stack on a Win32 executable.
今天上午,我也问了这个问题:
This morning, I've also asked a question about this:
现在,我是pretty确保 StackWalk64
功能对于这个关键。
我读过关于如何使用它,以及在MS文档一些文章。
Now, I'm pretty sure that the StackWalk64
function is the key for this.
I've read some articles on how to use it, as well as the MS documentation.
这其实在我的测试程序显示的帧,所以它还挺工作...
It actually displays frames on my test program, so it kinda work...
问题是我无法从堆栈信息检索符号的名称。
The problem is that I'm not able to retrieve the symbol name from the stack informations.
我使用了 SymGetSymFromAddr64
功能对于这一点,与 UnDecorateSymbolName
。但是我只拿到垃圾字符。
I'm using the SymGetSymFromAddr64
function for this, with UnDecorateSymbolName
. But I only get junk characters.
下面是我的code。希望这不是令人眼花缭乱的,因为我不习惯到Windows编程:
Here's my code. Hope its not to messy, as I'm not used to Windows programming:
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;
}
}
}
实际的输出是:
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
似乎不可思议堆栈地址始终为0的方式...任何帮助AP preciated:)
Seems weird that the stack address is always 0 by the way... Any help appreciated : )
谢谢大家!
修改
我在寻找一个普通的C解决方案,无需第三方库...
I'm looking for a plain C solution, without third party libraries...
推荐答案
您已设置 symbol.MaxNameLength
255,但你在分配符号的堆栈 IMAGEHLP_SYMBOL64符号;
。该类型定义为:
You have set symbol.MaxNameLength
to 255, but you allocated "symbol" on the stack with IMAGEHLP_SYMBOL64 symbol;
. That type is defined as:
typedef struct _IMAGEHLP_SYMBOL64 {
DWORD SizeOfStruct;
DWORD64 Address;
DWORD Size;
DWORD Flags;
DWORD MaxNameLength;
TCHAR Name[1];
} IMAGEHLP_SYMBOL64;
注意Name字段只有在默认情况下一个字符。如果要存储更大的名称,你需要做的是这样的:
Notice that the Name field only has one character by default. If you want to store bigger names, you need to do something like:
const int MaxNameLen = 255;
IMAGEHLP_SYMBOL64* pSymbol =
malloc(sizeof(IMAGEHLP_SYMBOL64)+MaxNameLen*sizeof(TCHAR));
pSymbol->MaxNameLength = MaxNameLen;
另外, SymGetSymFromAddr64()
很可能覆盖内存。这里是的结构帮助页面说(重点添加):
Otherwise, SymGetSymFromAddr64()
is likely to overwrite memory. Here is what the help page for the structure says (emphasis added):
MaxNameLength :最大长度
字符串的名称成员都可以
包含在字符,不包括
空终止符。
因为符号名称可以在变化
长度,该数据结构是
调用方分配 的。该成员
使用这样的文库知道多少
内存可用于通过使用
符号的名称。
MaxNameLength: The maximum length of the string that the Name member can contain, in characters, not including the null-terminating character. Because symbol names can vary in length, this data structure is allocated by the caller. This member is used so the library knows how much memory is available for use by the symbol name.
这篇关于StackWalk64在Windows上 - 获取符号名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!