SymEnumSymbols returns ERROR_SUCCESS but fails

I am trying to list the characters from a loaded DLL. For those interested, this is part of the CPPCoverage project , and for some functionality I need symbol data.

Breakdown problem

When a process starts or loads a DLL, the characters must be listed for some new scheduled functions.

In principle, a process is created, but dbghelpused to obtain information about a symbol. Then the characters are repeated with SymEnumSymbols. There are two points when this happens:

  • When the process is running ( CREATE_PROCESS_DEBUG_EVENT)
  • When does DLL ( LOAD_DLL_DEBUG_EVENT) load

Everything works fine (2). However, characters cannot be listed during (1).

Behavior is that everything works fine, before the call SymEnumSymbols. The return value tells me about the error, but GetLastErrorreturns SUCCESS. In addition, the callback function is not called.

To make it even weirder, the challenge SymGetSymFromNamereally works.

Minimum Test Case

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
}
+4
source share
2 answers

Brr, pretty weird. I got reproductions for this in VS2017 using a simple do-nothing executable created from the Win32 Console project template. Nothing I tried can convince SymEnumSymbols () to list any characters. Then I expanded the code, also capturing the LOAD_DLL_DEBUG_EVENT notification:

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

SymInitialize(), ntdll.dll ..

: - PDB

. Microsoft PDB, VS2015. /DEBUG: FASTLINK. , , VS2015. PDB DbgHelp.dll. GetLastError() , , , " ". , api DbgHelp, SymSetContext SymLoadModuleEx.

VS2015 Project > Properties > Linker > Debug > Generate Debug Info = " (/DEBUG)".

VS2017 Project > Properties > Linker > Debug > Generate Debug Info = " , (/DEBUG: FULL)".

, , . DbgHelp.dll, Fastlink PDB. , , SDK 8.1 SDK 10, . , DevDiv Windows .

+3

@SimonMournier . , , . , /DEBUG:FastLink Visual Studio .

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

[...] Windows dbghelp.dll VS 2017 PDB/DIA, Windows SDK ( ) dbghelp.dll, PDB Fastlink. VS 2017 โ€‹โ€‹ dbghelp.dll VS, PDB fastlink.

, , Visual Studio 2015, DIA . VS2017, . , /DEBUG .

+1

Source: https://habr.com/ru/post/1680481/


All Articles