代码之家  ›  专栏  ›  技术社区  ›  atlaste

SymEnumSymbols返回ERROR\u SUCCESS,但不给出任何结果

  •  4
  • atlaste  · 技术社区  · 7 年前

    CPPCoverage project ,对于某些功能,我需要符号数据。

    问题的分解

    dbghelp 用于获取符号信息。接下来,使用 SymEnumSymbols

    1. CREATE_PROCESS_DEBUG_EVENT )
    2. 加载DLL时( LOAD_DLL_DEBUG_EVENT )

    (2)期间一切正常。但是,在(1)期间无法枚举符号。

    行为是一切正常,直到 GetLastError 返回成功。此外,不调用回调函数。

    SymGetSymFromName 实际上有效。

    static BOOL CALLBACK EnumerateSymbols(
                              PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
    {
        std::cout << "Symbol: " << pSymInfo->Name << std::endl;
        return TRUE;
    }
    
    void Test()
    {
        SymSetOptions(SYMOPT_LOAD_ANYTHING);
    
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
    
        auto str = "FullPathToSomeExeWithPDB.exe";
        auto result = CreateProcess(str, NULL, NULL, NULL, FALSE,
                                    DEBUG_PROCESS, NULL, NULL, &si, &pi);
        if (result == 0)
        {
            auto err = GetLastError();
            std::cout << "Error running process: " << err << std::endl;
            return;
        }
    
        if (!SymInitialize(pi.hProcess, NULL, FALSE))
        {
            auto err = GetLastError();
            std::cout << "Symbol initialization failed: " << err << std::endl;
            return;
        }
    
        bool first = false;
        DEBUG_EVENT debugEvent = { 0 };
        while (!first)
        {
            if (!WaitForDebugEvent(&debugEvent, INFINITE))
            {
                auto err = GetLastError();
                std::cout << "Wait for debug event failed: " << err << std::endl;
                return;
            }
            if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
            {
                auto dllBase = SymLoadModuleEx(
                    pi.hProcess,
                    debugEvent.u.CreateProcessInfo.hFile,
                    str,
                    NULL,
                    reinterpret_cast<DWORD64>(debugEvent.u.CreateProcessInfo.lpBaseOfImage),
                    0,
                    NULL,
                    0);
    
                if (!dllBase)
                {
                    auto err = GetLastError();
                    std::cout << "Loading the module failed: " << err << std::endl;
                    return;
                }
    
                if (!SymEnumSymbols(pi.hProcess, dllBase, NULL, EnumerateSymbols, nullptr))
                {
                    auto err = GetLastError();
                    std::cout << "Error: " << err << std::endl;
                }
    
                first = true;
            }
        } 
        // cleanup code is omitted
    }
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   Hans Passant    7 年前

    Brr,真是个难缠的人。我在VS2017中得到了一个用于此的复制,使用了一个从Win32控制台项目模板构建的简单的不做任何事情的目标可执行文件。我所做的任何尝试都无法说服SymEnumSymbols()枚举任何符号。接下来,我扩展了代码,还捕获了LOAD\u DLL\u DEBUG\u事件通知:

    if (debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) {
        auto base = SymLoadModule64(pi.hProcess, debugEvent.u.LoadDll.hFile, NULL, NULL, NULL, 0);
        if (!base) {
            auto err = GetLastError();
            std::cout << err << std::endl;
         }
        else {
            CloseHandle(debugEvent.u.LoadDll.hFile);
            SymEnumSymbols(pi.hProcess, base, NULL, EnumerateSymbols, nullptr);
        }
    }
    

    结论: PDB文件有问题

    这是值得的。从VS2015开始,微软一直在修补PDB文件的生成 /DEBUG:FASTLINK option

    在VS2017中使用项目>属性>链接器>调试(>);生成调试信息=“生成为共享和发布而优化的调试信息(/Debug:FULL)”。

    强调这些设置对目标项目而不是调试器项目很重要。理想情况下会有DbgHelp。dll版本,也可以从PDB的快速链接版本中读取调试信息。我找不到,SDK 8.1和SDK 10附带的软件并没有解决这个问题。DevDiv和Windows组不一起工作的另一个案例。

        2
  •  1
  •   atlaste    7 年前

    /DEBUG:FastLink 在Visual Studio中,这实际上是问题的根源。

    https://developercommunity.visualstudio.com/content/problem/4631/dia-sdk-still-doesnt-support-debugfastlink.html

    […]已通知Windows调试器团队构建新的dbghelp。带有VS 2017 PDB/DIA静态库的dll以及下一个公开版本的Windows SDK(或调试器工具包)将包含dbghelp。能够处理快速链接PDB的dll。最新的VS 2017预发布版将安装一个新的dbghelp。与fastlink PDB一起工作的VS安装目录下的dll。

    因此,简而言之,它根本无法与Visual Studio 2015配合使用,因为DIA根本不支持它。当我们升级到VS2017时,它将自动修复。此外,当链接到 /DEBUG ,一切都会好起来的。