C++ SymGetLineFromAddr 有错误代码 126

C++ SymGetLineFromAddr has error code 126

我围绕一些 WINAPI 函数编写了一个包装器。但是,SymGetLineFromAddr 总是失败并出现错误 126。经过一些研究,似乎是因为 SymInitalize 没有被调用或失败。调试显示 SymInitalize 实际上并没有失败。更令人困惑的是 SymFromAddr 工作得很好。那么为什么 SymGetLineFromAddr 总是以代码 126 失败?

class debug_state
{
    // held for caching
    SYMBOL_INFO* symbol;
    IMAGEHLP_LINE* line;
    HANDLE process;
    bool is_init = false;
public:
    static constexpr int MAX_LEN = 1024;

    inline void init()
    {
        if (is_init)
            return;

        process = GetCurrentProcess();

        SymInitialize(process, NULL, TRUE);

        symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + MAX_LEN, 1);
        symbol->MaxNameLen = MAX_LEN;
        symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

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

        is_init = true;
    }

    inline SYMBOL_INFO* get_info_of(intptr_t ptr)
    {
        init();
        SymFromAddr(process, (DWORD64)(ptr), 0, symbol);
        return symbol;
    }

    inline IMAGEHLP_LINE* get_line_of(intptr_t ptr)
    {
        init();
        DWORD tmp;
        if (!SymGetLineFromAddr(process, (DWORD)(ptr), &tmp, line))
        {
            DWORD d = GetLastError();
            std::cout << d;
        }
        return line;
    }
};

SymFromAddr works perfectly fine.

之所以有效,是因为它不会截断其指针参数:

SymFromAddr(process, (DWORD64)(ptr), 0, symbol);
//                   ^^^^^^^^^ preserves 64 bits of information

对比 SymGetLineFromAddr 的调用:

SymGetLineFromAddr(process, (DWORD)(ptr), &tmp, line)
//                          ^^^^^^^ truncate to 32 bits

这只会将指针值的低 32 位传递给 API 调用。只要您将它与 32 位进程一起使用,它就可以工作。对于 64 位进程,信息的上半部分丢失了。你应该改用这个:

SymGetLineFromAddr(process, (DWORD64)(ptr), &tmp, line)