Как использовать SymLoadModuleEx для загрузки файла PDB?

Я пытаюсь дозвониться 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");
}

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

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

4 ответов


dbghelp.dll и Sym* методы здесь использовать Доступ К Интерфейсу Отладки (DIA) SDK.1
Сам DIA основан на COM и гораздо более гибок, чем то, что предлагает DbgHelp.

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

  1. создание источника данных DIA (см. раздел "пример"здесь).
  2. использовать IDiaDataSource::loadDataFromPdb для загрузки определенного PDB (размер DLL и базовый адрес не требуются).
  3. использовать IDiaDataSource::openSession для получения IDiaSession для источника данных.
  4. в зависимости от того, есть ли у вас абсолютный виртуальный адрес (VA) или относительный виртуальный адрес (RVA), вы можете использовать findSymbolByVA или findSymbolByRVA, соответственно, чтобы получить IDiaSymbol связанный с этим адресом.
  5. и, наконец, может использовать IDiaSymbol::get_name чтобы получить имя функции, содержащее указанный Вами адрес.

ни для чего из этого не требуется исходное изображение; требуется только PDB. Предполагая, что вы используете Visual Studio, заголовки и библиотеки для DIA доступны в разделе (например):
C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK.


посмотрите на SymLoadPdb.образец СРР здесь.


образец 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


У меня нет разрешений для комментариев, поэтому я сделаю это в отдельном ответе.

  1. Да, DbgHelp-это обертка вокруг DIA, только с точки зрения статической lib. DIA статически соединено в DbgHelp.файл DLL. DbgHelp напрямую вызывает реализацию com class factory (IClassFactory) Dia в обход 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. см. " политики перераспределения для этих включенных библиотек DLL были специально разработаны, чтобы сделать это проще как это возможно для людей, чтобы включить эти файлы в свои пакеты и отпустите"

  4. Я не нашел способ загрузки файлов PDB с помощью интерфейсов DIA. Sym API позволяет это. он делегирует вызовы SymSrv.файл DLL.

таким образом, оригинальный вопрос по-прежнему актуален.