SymFromAddr 在 AMD 计算机上失败,并显示错误消息“尝试访问无效地址”

问题描述 投票:0回答:1
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;
}

我需要从 EXCEPTION_POINTER 获取未处理异常的调用堆栈。 它在 Windows Intel 机器 x86 和 x64 架构上正常工作,但我在 AMD 机器上遇到了一些问题,并显示错误消息“尝试访问无效地址”。欢迎任何解决此问题的帮助。

x86-64 unhandled-exception crash-dumps amd-processor printstacktrace
1个回答
0
投票

Intel 或 AMD 处理器不是问题。 对于 X86 架构,StackWalk 需要 IMAGE_FILE_MACHINE_I386,对于 X64 架构,它需要 IMAGE_FILE_MACHINE_AMD64。这很重要,您已经正确完成了这一点。

您还需要有 .pdb 文件来检索调用堆栈。确保您在测试应用程序的 AMD 计算机中拥有它。

© www.soinside.com 2019 - 2024. All rights reserved.