HoShiMin
2/3/2016 - 9:56 PM

Удобный парсер PDB-файлов с помощью DIA (входит в Windows Kits)

Удобный парсер 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);
};