2011-02-01 184 views
7

我試圖呼叫SymLoadModuleEx從PDB文件中加載符號,然後使用SymFromAddr查找來自該PDB的符號。然而,我不知道要傳遞什麼參數BaseOfDllDllSize - 文檔明確指出,加載PDB文件時,這些參數不能爲0,並且實際上嘗試傳遞0導致它與ERROR_INVALID_PARAMETER如何使用SymLoadModuleEx加載PDB文件?

這裏是我的代碼如下所示:

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

你如何找出BaseOfDllDllSize到加載PDB文件時傳遞?所討論的PDB文件是不同程序可執行文件(不是DLL)的符號文件,並且只是爲了爭論,假設您無權訪問生成PDB的原始EXE。

另外,是否有更好的方法來查找PDB文件中給定地址對應的符號?

回答

8

dbghelp.dll和Sym*這裏的方法只是對Debug Interface Access(DIA)API的封裝。 DIA是基於COM的,並且濫用了它的一些接口(看起來好像一切都是IDiaSymbol),但它比dbghelp提供的靈活得多。

具體而言,加載一個已知PDB和查找基於地址符號,可以執行以下操作:

  1. CoCreate的一個DIA數據源(參見「實施例」一節here)。
  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下使用。

3

看看SymLoadPdb.cpp示例here

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(市民:結構ssl_config __cdecl SERVERCONFIG :: getSSLConfig(無效)__ptr64)

這裏的RVA是00447B60 [EIP - 處理量地址] 該段是0001 的偏移00446B60

0

我沒有permitions發表評論,所以會爲此在單獨的答案。

  1. 是的,DbgHelp是DIA的一個包裝,只是靜態lib。 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位置相同),所以解決方案我們無法在envs這裏VS未安裝(但你仍然可以嘗試通過ActivateActCtx使用msdia120.dll私人集會指向它,但還需要部署的依賴關係,如果他們現在)
  3. DBGHELP緊湊,並建議與您的應用程序分發傳抄微軟。 See "The redistribution policies for these included DLLs were specifically designed to make it as easy as possible for people to include these files in their own packages and release"

  4. 我沒有找到如何使用DIA接口下載PDB文件的方式。 Sym API允許這樣做。它將調用委託給SymSrv.dll。

所以原來的問題仍然存在。