void generateStack()

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);
}