in rts/win32/veh_excn.c [260:334]
void generateStack (EXCEPTION_POINTERS* pExceptionPointers)
{
if (!RtsFlags.MiscFlags.generate_stack_trace)
return;
PCONTEXT context = pExceptionPointers->ContextRecord;
STACKFRAME64 stackFrame = {0};
DWORD machineType;
#if defined(x86_64_HOST_ARCH)
machineType = IMAGE_FILE_MACHINE_AMD64;
stackFrame.AddrPC.Offset = context->Rip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context->Rbp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context->Rsp;
stackFrame.AddrStack.Mode = AddrModeFlat;
#else
machineType = IMAGE_FILE_MACHINE_I386;
stackFrame.AddrPC.Offset = context->Eip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context->Ebp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context->Esp;
stackFrame.AddrStack.Mode = AddrModeFlat;
#endif
fprintf (stderr, "\n Attempting to reconstruct a stack trace...\n\n");
if (!SymInitialize (GetCurrentProcess (), NULL, true))
fprintf (stderr, " \nNOTE: Symbols could not be loaded. Addresses may"
" be unresolved.\n\n");
/* Maximum amount of stack frames to show. */
/* Phyx: I'm not sure if I should make this configurable or not. Would a
longer stack really be more useful? usually you only care about the top
few. */
int max_frames = 35;
fprintf (stderr, " Frame\tCode address\n");
DWORD64 lastBp = 0; /* Prevent loops with optimized stackframes. */
while (StackWalk64 (machineType, GetCurrentProcess(), GetCurrentThread(),
&stackFrame, context, NULL, SymFunctionTableAccess64,
SymGetModuleBase64, NULL) && max_frames > 0)
{
if (stackFrame.AddrPC.Offset == 0)
{
fprintf (stderr, "Null address\n");
break;
}
wchar_t buffer[1024];
uintptr_t topSp = 0;
fprintf (stderr, " * 0x%" PRIxPTR "\t%ls\n",
(uintptr_t)stackFrame.AddrFrame.Offset,
resolveSymbolAddr ((wchar_t*)&buffer, 1024,
(SymbolAddr*)(intptr_t)stackFrame.AddrPC.Offset,
&topSp));
if (lastBp >= stackFrame.AddrFrame.Offset)
{
fprintf (stderr, "Stack frame out of sequence...\n");
break;
}
lastBp = stackFrame.AddrFrame.Offset;
max_frames--;
if (max_frames ==0)
{
fprintf (stderr, "\n ... (maximum recursion depth reached.)\n");
}
}
fprintf (stderr, "\n");
fflush(stderr);
}