x86-64unhandled-exceptioncrash-dumpsamd-processorprintstacktrace

SymFromAddr fails on AMD Machine with the error message "Attempt to access Invalid address"


struct StackFrame
{
    DWORD64 address;
    std::string name;
    std::string module;
    std::string filename;
    int line_number;
};

std::vector<StackFrame> GetStackTrace(CONTEXT context)
{
    DWORD  machine = IMAGE_FILE_MACHINE_I386;
    HANDLE process = GetCurrentProcess();
    HANDLE thread  = GetCurrentThread();

    STACKFRAME64 frame   = {};
    IMAGEHLP_LINE64* line = nullptr;
    DWORD disp;

    SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
    if (SymInitialize(process, NULL, TRUE) == FALSE)
    {
        return std::vector<StackFrame>(); 
    }

    #ifdef _M_IX86
        machine                 = IMAGE_FILE_MACHINE_I386;
        frame.AddrPC.Offset     = context.Eip;
        frame.AddrPC.Mode       = AddrModeFlat;
        frame.AddrFrame.Offset  = context.Ebp;
        frame.AddrFrame.Mode    = AddrModeFlat;
        frame.AddrStack.Offset  = context.Esp;
        frame.AddrStack.Mode    = AddrModeFlat;
    #elif _M_X64
        machine                 = IMAGE_FILE_MACHINE_AMD64;
        frame.AddrPC.Offset     = context.Rip;
        frame.AddrPC.Mode       = AddrModeFlat;
        frame.AddrFrame.Offset  = context.Rsp;
        frame.AddrFrame.Mode    = AddrModeFlat;
        frame.AddrStack.Offset  = context.Rsp;
        frame.AddrStack.Mode    = AddrModeFlat;
    #elif _M_IA64
        machine                 = IMAGE_FILE_MACHINE_IA64;
        frame.AddrPC.Offset     = context.StIIP;
        frame.AddrPC.Mode       = AddrModeFlat;
        frame.AddrFrame.Offset  = context.IntSp;
        frame.AddrFrame.Mode    = AddrModeFlat;
        frame.AddrBStore.Offset = context.RsBSP;
        frame.AddrBStore.Mode   = AddrModeFlat;
        frame.AddrStack.Offset  = context.IntSp;
        frame.AddrStack.Mode    = AddrModeFlat;
    #else
    #error "This platform is not supported."
    #endif

    std::vector<StackFrame> frames;
    while (StackWalk64(machine, process, thread, &frame, &context , NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
    {
        StackFrame f;
        f.address = frame.AddrPC.Offset;

        DWORD64 moduleBase = SymGetModuleBase64(process, frame.AddrPC.Offset);

        char moduelBuff[MAX_PATH];            
        if (moduleBase && GetModuleFileNameA((HINSTANCE)moduleBase, moduelBuff, MAX_PATH))
        {
            f.module = moduelBuff;
        }
        else
        {
            f.module = "Unknown Module";
        }

        DWORD64 offset = 0;
        char symbolBuff[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];   
        PSYMBOL_INFO symbol = (PSYMBOL_INFO)symbolBuff;

        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
        symbol->MaxNameLen   = MAX_SYM_NAME;

        if (SymFromAddr(process, frame.AddrPC.Offset, &offset, symbol))
        {
            f.name = symbol->Name;
            
            SymSetOptions(SYMOPT_LOAD_LINES);

            line = (IMAGEHLP_LINE64*)malloc(sizeof(IMAGEHLP_LINE64));
            line->SizeOfStruct = sizeof(IMAGEHLP_LINE64);

            if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &disp, line))
            {
                f.filename = line->FileName;
                f.line_number = line->LineNumber;
            }
            else
            {
                std::cout << "Error occured in SymGetLineFromAddr64 : Reason :: " << std::system_category().message(GetLastError()) << " \n";
            }

            free(line);
        }
        else
        {
            DWORD error = GetLastError();
            std::cout << "SymFromAddr Failed. Err Reason : " << std::system_category().message(error)<< " \n";

            f.name = "Unknown Function";
        }

        frames.push_back(f);
    }

    SymCleanup(process);

    return frames;
}

I need to get the callstack of the unhandled exception from the EXCEPTION_POINTER. It working properly on Windows Intel Machine x86 and x64 architectures but I encounter issues specifically on AMD machines with the error message "Attempt to access invalid address". Any Help in addressing this issue would be welcomed.


Solution

  • Intel or AMD processor is not the issue. For X86 architecture, StackWalk needs IMAGE_FILE_MACHINE_I386 and for X64 architecture, it needs IMAGE_FILE_MACHINE_AMD64. This is important and You have done that correctly.

    You also need to have the .pdb file to retrieve the Call stack. Make sure You have it in the AMD machine in which you tested your application.