2011-02-01 10 views
7

Я пытаюсь вызвать SymLoadModuleEx для загрузки символов из файла PDB, а затем использовать SymFromAddr для поиска символов из этого PDB. Однако я не могу понять, что передать параметрам BaseOfDll и DllSize - в документации явно указано, что при загрузке файла 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"); 
} 

Как вы выяснить, что BaseOfDll и DllSize пройти в при загрузке PDB файла? Файл PDB, о котором идет речь, является файлом символа для другого исполняемого файла программы (а не библиотеки DLL) и только ради аргумента, предположим, что у вас нет доступа к исходному EXE, из которого был создан PDB.

В качестве альтернативы, есть ли лучший способ поиска символов, соответствующих данному адресу из файла PDB?

ответ

8

dbghelp.dll и методы Sym* - это всего лишь обертка вокруг API Debug Interface Access (DIA). DIA работает на основе COM и злоупотребляет некоторыми его интерфейсами (кажется, что все это IDiaSymbol), но он намного более гибкий, чем предлагает dbghelp.

В частности, для загрузки известного PDB и поиск символа на основе адрес, вы можете сделать следующее:

  1. CoCreate источник диафильтрация данные (смотрите раздел «Пример» here).
  2. Используйте IDiaDataSource::loadDataFromPdb для загрузки определенного PDB (размер DLL и базовый адрес не нужны).
  3. Используйте IDiaDataSource::openSession, чтобы получить IDiaSession для вашего источника данных.
  4. В зависимости от того, имеете ли вы абсолютный виртуальный адрес (ВА) или относительный виртуальный адрес (RVA), вы можете использовать findSymbolByVA или findSymbolByRVA, соответственно, чтобы получить связанный с этим адрес 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)

Здесь ООА является 00447B60 [EIP - Процесс загрузки Адрес] Сегмент 0001 смещение 00446B60

0

у меня нет позволения комментировать, так будет делать это в отдельный ответ.

  1. Да, DbgHelp является оберткой вокруг DIA, только с точки зрения статической библиотеки. DIA статически связана с DbgHelp.dll. DbgHelp напрямую вызывает реализацию DIA-класса COM (IClassFactory) в обход COM. Я говорю о версии 6.1.7601.17514. Таким образом, DbgHelp.dll является автономным (в сочетании с symcrv.dll и srcsrv.dll)
  2. Объекты Dia COM поставляются с Visual Studio (такое же место с dbgeng.dll), поэтому решение не работает на envs, где VS (но вы все еще можете попытаться использовать msdia120.dll как частную сборку, указывающую на нее через ActivateActCtx, но также необходимо развернуть зависимости, если они присутствуют)
  3. DbgHelp является компактным и рекомендуется распространять личные копии с вашим приложением Microsoft. 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. Я не нашел способ загрузки файлов PDB с использованием интерфейсов DIA. Sym API позволяет это. он делегирует вызовы на SymSrv.dll.

Так что первоначальный вопрос по-прежнему актуальный.