Удобный парсер PDB-файлов с помощью DIA (входит в Windows Kits)
#include "stdafx.h"
#include "DIAWrapper.h"
// Очистка ресурсов:
VOID DIAWrapper::Cleanup() {
if (pGlobalSymbol) pGlobalSymbol -> Release();
if (pDiaSession) pDiaSession -> Release();
if (pDiaDataSource) pDiaDataSource -> Release();
pGlobalSymbol = NULL;
pDiaSession = NULL;
pDiaDataSource = NULL;
dwMachineType = CV_CFL_80386;
}
// Инициализация:
VOID DIAWrapper::Initialize() {
Cleanup();
CoCreateInstance(__uuidof(DiaSource), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource), (PVOID *)&pDiaDataSource);
}
// Конструктор:
DIAWrapper::DIAWrapper() {
CoInitialize(NULL);
}
// Деструктор:
DIAWrapper::~DIAWrapper() {
Cleanup();
CoUninitialize();
}
// Загрузка PDB:
DIAWRAPPER_STATUS DIAWrapper::LoadPDB(LPWSTR PDBPath) {
Initialize();
if FAILED(pDiaDataSource->loadDataFromPdb(PDBPath)) return STATUS_FILE_NOT_FOUND;
if FAILED(pDiaDataSource->openSession(&pDiaSession)) return STATUS_OPEN_SESSION_ERROR;
if FAILED(pDiaSession->get_globalScope(&pGlobalSymbol)) return STATUS_GETTING_GLOBAL_SCOPE_ERROR;
if (pGlobalSymbol->get_machineType(&dwMachineType) == S_OK) {
switch (dwMachineType) {
case IMAGE_FILE_MACHINE_I386: dwMachineType = CV_CFL_80386 ; break;
case IMAGE_FILE_MACHINE_IA64: dwMachineType = CV_CFL_IA64 ; break;
case IMAGE_FILE_MACHINE_AMD64: dwMachineType = CV_CFL_AMD64 ; break;
}
}
return STATUS_SUCCESS;
}
// Получить корневой символ:
IDiaSymbol* DIAWrapper::GetGlobalSymbol() {
return pGlobalSymbol;
}
// Получить символ в родительском объекте:
BOOL DIAWrapper::GetSymbol(IDiaSymbol* WhereToFindSymbol, LPWSTR SymbolName, enum SymTagEnum SymbolType, enum NameSearchOptions SearchOptions, OUT IDiaSymbol** Symbol) {
BOOL Result = FALSE;
if (WhereToFindSymbol == NULL) return Result;
if (SymbolName == NULL) return Result;
if (Symbol == NULL) return Result;
// Ищем все символы, подпадающие под условие:
IDiaEnumSymbols *EnumSymbols;
if FAILED(WhereToFindSymbol->findChildren(SymbolType, SymbolName, SearchOptions, &EnumSymbols)) return Result;
// Делаем выборку одного символа:
const BYTE SymbolsCount = 1;
ULONG SymbolsFetched;
Result = SUCCEEDED(EnumSymbols->Next(SymbolsCount, Symbol, &SymbolsFetched)) && (SymbolsFetched == SymbolsCount);
EnumSymbols->Release();
return Result;
}
// Получить смещение символа в родительском объекте:
BOOL DIAWrapper::GetSymbolOffset(IDiaSymbol* Symbol, OUT PLONG SymbolOffset) {
return Symbol->get_offset(SymbolOffset) == S_OK;
}
// Получить размер символа:
BOOL DIAWrapper::GetSymbolSize(IDiaSymbol* Symbol, OUT PULONGLONG SymbolSize) {
IDiaSymbol* Type;
HRESULT Status = Symbol->get_type(&Type);
if (Status != S_OK) return FALSE;
Status = Type->get_length(SymbolSize) == S_OK;
Type->Release();
return Status;
}
// Освободить символ, полученный от GetSymbol:
VOID DIAWrapper::FreeSymbol(IDiaSymbol* Symbol) {
if (Symbol) Symbol->Release();
}
#pragma once
#include "dia2.h"
enum DIAWRAPPER_STATUS {
STATUS_SUCCESS,
STATUS_FILE_NOT_FOUND,
STATUS_OPEN_SESSION_ERROR,
STATUS_GETTING_GLOBAL_SCOPE_ERROR
};
class DIAWrapper {
private:
IDiaDataSource *pDiaDataSource = NULL;
IDiaSession *pDiaSession = NULL;
IDiaSymbol *pGlobalSymbol = NULL;
DWORD dwMachineType = CV_CFL_80386;
VOID Initialize(); // Инициализация DIA2
VOID Cleanup(); // Очистка ресурсов, освобождение символов
public:
DIAWrapper();
~DIAWrapper();
// Загрузка PDB:
DIAWRAPPER_STATUS LoadPDB(LPWSTR PDBPath);
// Получить корневой символ:
IDiaSymbol* GetGlobalSymbol();
// Получить символ в родительском объекте:
BOOL GetSymbol(IDiaSymbol* WhereToFindSymbol, LPWSTR SymbolName, enum SymTagEnum SymbolType, enum NameSearchOptions SearchOptions, OUT IDiaSymbol** Symbol);
// Получить смещение символа в родительском объекте:
BOOL GetSymbolOffset(IDiaSymbol* Symbol, OUT PLONG SymbolOffset);
// Получить размер символа:
BOOL GetSymbolSize(IDiaSymbol* Symbol, OUT PULONGLONG SymbolSize);
// Освободить символ, полученный от GetSymbol:
VOID FreeSymbol(IDiaSymbol* Symbol);
};