10

我正在尝试调用SymLoadModuleEx以从 PDB 文件中加载符号,然后用于SymFromAddr从该 PDB 中查找符号。但是,我不知道要为参数传递什么,BaseOfDll并且DllSize文档明确指出,在加载 PDB 文件时,这些参数不能为 0,并且确实尝试传递 0 会导致它失败,并显示ERROR_INVALID_PARAMETER.

这是我的代码的样子:

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

加载 PDB 文件时如何确定要传入的内容BaseOfDll和内容?DllSize有问题的 PDB 文件是不同程序可执行文件(不是 DLL)的符号文件,只是为了论证,假设您无权访问生成 PDB 的原始 EXE。

或者,是否有更好的方法从 PDB 文件中查找与给定地址对应的符号?

4

3 回答 3

10

dbghelp.dll 和Sym*此处的方法使用调试接口访问(DIA) SDK。1
DIA 本身是基于 COM 的,并且比 DbgHelp 提供的更灵活。

具体来说,要加载已知 PDB 并根据地址查找符号,您可以执行以下操作:

  1. 共同创建 DIA 数据源(请参阅此处的“示例”部分)。
  2. 用于IDiaDataSource::loadDataFromPdb加载特定的 PDB(不需要 DLL 大小和基地址)。
  3. 用于IDiaDataSource::openSession获取IDiaSession数据源的 。
  4. 根据您是否拥有绝对虚拟地址 (VA) 或相对虚拟地址 (RVA),您可以分别使用findSymbolByVAfindSymbolByRVA来获取IDiaSymbol与该地址关联的内容。
  5. 最后,您可以使用IDiaSymbol::get_name来获取包含您指定的地址的函数名。

这些都不需要原始图像;只有 PDB 是必需的。假设您使用的是 Visual Studio,DIA 的头文件和库在(例如)下可用:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK.

于 2011-02-01T21:05:39.263 回答
0

Dia2Dump 示例非常适合我将相对虚拟地址(eip 程序加载地址)解析为 pdb 以获取未解析的函数指针。这是我尝试的方式:

    DWORD64  dwAddress = _wcstoui64(argv[i], NULL, 16);
    DWORD64 dwRVA  = dwAddress - dwLoadAddress;
    long displacement = 0;
    IDiaSymbol* pFunc = 0;
    error = (DWORD)g_pDiaSession->findSymbolByRVAEx(dwRVA, SymTagFunction, &pFunc, &displacement );

    if (!error && pFunc)
    {
        BSTR bstrName;

        if (pFunc->get_name(&bstrName) != S_OK) {
            wprintf(L"(???)\n\n");
        }

        else {
            wprintf(L"%s \n\n", bstrName);
            if (displacement)
                wprintf(L"+ 0x%x \n\n", displacement);
            else
                wprintf(L" \n\n");
            SysFreeString(bstrName);
        }
    }

例如:函数:[00447B60][0001:00446B60] ServerConfig::getSSLConfig(public: struct ssl_config __cdecl ServerConfig::getSSLConfig(void) __ptr64)

这里 RVA 是 00447B60 [ eip - Process Load Address ] 段是 0001 偏移量是 00446B60

于 2014-05-19T05:16:30.307 回答
0

我没有评论的许可,因此将在单独的答案中进行。

  1. 是的,DbgHelp 是 DIA 的包装器,仅在静态库方面。DIA 静态链接到 DbgHelp.dll。DbgHelp 绕过 COM 直接调用 Dia 的 COM 类工厂 (IClassFactory) 实现。我说的是 6.1.7601.17514 版本。所以 DbgHelp.dll 是自包含的(结合 symcrv.dll 和 srcsrv.dll)
  2. Dia COM 对象随 Visual Studio 一起提供(与 dbgeng.dll 位于同一位置),因此解决方案我们不适用于未安装 VS 的环境(但您仍然可以尝试使用 msdia120.dll 作为通过ActivateActCtx指向它的私有程序集,但是还需要部署依赖项(如果存在)
  3. DbgHelp 很紧凑,建议 Microsoft 将私有副本与您的应用程序一起分发。 请参阅“这些包含的 DLL 的重新分发策略专门设计为使人们尽可能轻松地将这些文件包含在他们自己的包中并发布”

  4. 我没有找到如何使用 DIA 接口下载 PDB 文件的方法。Sym API 允许这样做。它将调用委托给 SymSrv.dll。

所以原来的问题仍然是实际的。

于 2015-12-15T18:59:50.343 回答