Search code examples
cwinapipdb-filesdbghelp

How do you use SymLoadModuleEx to load a PDB file?


I'm trying to call SymLoadModuleEx to load the symbols from a PDB file and then use SymFromAddr to look up symbols from that PDB. However, I can't figure out what to pass for the parameters BaseOfDll and DllSize -- the documentation explicitly says that when loading a PDB file, these parameters can't be 0, and indeed attempting to pass 0 results in it failing with ERROR_INVALID_PARAMETER.

Here's what my code looks like:

SymSetOptions(SYMOPT_LOAD_LINES);
HANDLE hprocess = GetCurrentProcess();
if (!SymInitialize(hprocess, NULL, FALSE))
    die("SymInitialize");

if(SymLoadModuleEx(hprocess, NULL, "full path to some PDB file.pdb", NULL,
                   0,  // What to pass here?
                   0,  // What to pass here?
                   NULL, 0) == 0)
{
    die("SymLoadModuleEx");
}

How do you figure out what BaseOfDll and DllSize to pass in when loading a PDB file? The PDB file in question is the symbol file for a different program executable (not a DLL), and just for the sake of argument, assume that you don't have access to the original EXE from which the PDB was generated.

Alternatively, is there a better method of looking up the symbols corresponding to a given address from a PDB file?


Solution

  • dbghelp.dll and the Sym* methods here make use of the Debug Interface Access (DIA) SDK.1
    DIA itself is COM-based and much more flexible than what DbgHelp offers.

    Specifically, to load a known PDB and lookup a symbol based on an address, you can do the following:

    1. CoCreate a DIA data source (see the "Example" section here).
    2. Use IDiaDataSource::loadDataFromPdb to load a specific PDB (DLL size and base address are not needed).
    3. Use IDiaDataSource::openSession to get the IDiaSession for your data source.
    4. Depending on if you have an absolute virtual address (VA) or relative virtual address (RVA), you can use findSymbolByVA or findSymbolByRVA, respectively, to get the IDiaSymbol associated with that address.
    5. Finally, you can use IDiaSymbol::get_name to get the function name containing the address you specified.

    None of this requires the original image; only the PDB is required. Assuming you're using Visual Studio, the headers and libraries for DIA are available under (for example):
    C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK.