我正在尝试为我的应用程序打印堆栈跟踪。我无法使用StackWalk64
,因为我的应用程序随optimization disabled
一起发布。对于x86
,我们使用了strace
某人在codeprex
上写的人但是我找不到与x64
类似的内容。以下是我在网上为x86
找到的代码。
#include <Windows.h>
#include <DbgHelp.h>
#include <stdio.h>
#define INVALID_FP_RET_ADDR_VALUE 0x00000000
BOOL g_fSymInit;
HANDLE g_hProcess;
BOOL DisplaySymbolDetails(DWORD dwAddress)
{
DWORD64 displacement = 0;
ULONG64 buffer[(sizeof(SYMBOL_INFO) +
MAX_SYM_NAME*sizeof(TCHAR) +
sizeof(ULONG64) - 1) /
sizeof(ULONG64)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
if (SymFromAddr(g_hProcess,dwAddress,&displacement,pSymbol))
{
// Try to get the Module details
IMAGEHLP_MODULE64 moduleinfo;
moduleinfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
if (SymGetModuleInfo64(g_hProcess,pSymbol->Address,&moduleinfo))
{
printf("%s!",moduleinfo.ModuleName);
}
else
{
printf("<ErrorModuleInfo_%d>!", GetLastError());
}
// now print the function name
if (pSymbol->MaxNameLen > 0)
{
printf("%s",pSymbol->Name);
}
else
{
printf("<Unknown_Function>");
}
}
else
{
printf(" <Unable to get symbol details_%d>", GetLastError());
}
return TRUE;
}
bool WalkTheStack()
{
DWORD _ebp = INVALID_FP_RET_ADDR_VALUE;
DWORD dwIPOfCurrentFunction = (DWORD)&WalkTheStack;
// Get the current Frame pointer
__asm
{
mov [_ebp], ebp
}
// We cannot walk the stack (yet!) without a frame pointer
if (_ebp == INVALID_FP_RET_ADDR_VALUE)
return false;
printf("CurFP\t\t\tRetAddr\n");
DWORD *pCurFP = (DWORD *)_ebp;
BOOL fFirstFP = TRUE;
while (pCurFP != INVALID_FP_RET_ADDR_VALUE)
{
// pointer arithmetic works in terms of type pointed to. Thus,
// "+1" below is equivalent of 4 bytes since we are doing DWORD
// math.
DWORD pRetAddrInCaller = (*((DWORD *)(pCurFP + 1)));
printf("%p\t\t%p ",pCurFP, (DWORD *)pRetAddrInCaller);
if (g_fSymInit)
{
if (fFirstFP)
{
fFirstFP = FALSE;
}
DisplaySymbolDetails(dwIPOfCurrentFunction);
// To get the name of the next function up the stack,
// we use the return address of the current frame
dwIPOfCurrentFunction = pRetAddrInCaller;
}
printf("\n");
if (pRetAddrInCaller == INVALID_FP_RET_ADDR_VALUE)
{
// StackWalk is over now...
break;
}
// move up the stack to our caller
DWORD pCallerFP = *((DWORD *)pCurFP);
pCurFP = (DWORD *)pCallerFP;
}
return true;
}
int main ( int argc, char **argv) {
g_fSymInit = FALSE;
g_hProcess = GetCurrentProcess();
if (!SymInitialize(g_hProcess, NULL,TRUE)) {
printf("Unable to initialize symbols!\n\n");
} else {
g_fSymInit = TRUE;
}
SymSetOptions(SYMOPT_UNDNAME|SYMOPT_INCLUDE_32BIT_MODULES|SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);
WalkTheStack();
return 0;
}
要使其在x64
答案 0 :(得分:1)
您要做的是展开堆栈。我会告诉你所涉及的一般原则,而不是修复那些丑陋的混乱。在x86和x86_64上,ebp / rsp和esp / rsp寄存器形成内存位置的隐式链接列表。每个esp / rsp指向当前堆栈帧的顶部,每个ebp / rbp指向前一个堆栈帧的底部。有了这些知识,走遍框架是相当微不足道的。