5#include <Logger/Logger.h>
8#include "../Private/Helpers.h"
9#include "../Private/Offsets.h"
44 void PdbReader::
Read(
const std::wstring& path, std::unordered_map<std::string, intptr_t>* offsets_dump,
45 std::unordered_map<std::string, BitField>* bitfields_dump)
47 offsets_dump_ = offsets_dump;
48 bitfields_dump_ = bitfields_dump;
50 std::ifstream f{path};
52 throw std::runtime_error(
"Failed to open pdb file");
54 IDiaDataSource* data_source;
55 IDiaSession* dia_session;
60 LoadDataFromPdb(path, &data_source, &dia_session, &symbol);
62 catch (
const std::runtime_error&)
64 Log::GetLog()->error(
"Failed to load data from pdb file ");
68 Log::GetLog()->info(
"Dumping structures..");
71 Log::GetLog()->info(
"Dumping functions..");
72 DumpFunctions(symbol);
74 Log::GetLog()->info(
"Dumping globals..");
75 DumpGlobalVariables(symbol);
77 Cleanup(symbol, dia_session, data_source);
79 Log::GetLog()->info(
"Successfully read information from PDB\n");
82 void PdbReader::LoadDataFromPdb(
const std::wstring& path, IDiaDataSource** dia_source, IDiaSession** session,
85 const std::string current_dir = Tools::GetCurrentDir();
87 const std::string lib_path = current_dir +
"\\msdia140.dll";
88 const HMODULE h_module = LoadLibraryA(lib_path.c_str());
89 if (h_module ==
nullptr)
91 throw std::runtime_error(
"Failed to load msdia140.dll. Error code - " + std::to_string(GetLastError()));
94 const auto dll_get_class_object =
reinterpret_cast<HRESULT(WINAPI*)(REFCLSID, REFIID, LPVOID)>(GetProcAddress(
95 h_module,
"DllGetClassObject"));
96 if (dll_get_class_object ==
nullptr)
98 throw std::runtime_error(
"Can't find DllGetClassObject. Error code - " + std::to_string(GetLastError()));
101 IClassFactory* class_factory;
102 HRESULT hr = dll_get_class_object(
__uuidof(DiaSource), IID_IClassFactory, &class_factory);
105 throw std::runtime_error(
"DllGetClassObject has failed. Error code - " + std::to_string(GetLastError()));
108 hr = class_factory->CreateInstance(
nullptr,
__uuidof(IDiaDataSource),
reinterpret_cast<
void**>(dia_source));
111 class_factory->Release();
112 throw std::runtime_error(
"CreateInstance has failed. Error code - " + std::to_string(GetLastError()));
115 hr = (*dia_source)->loadDataFromPdb(path.c_str());
118 class_factory->Release();
119 throw std::runtime_error(
"loadDataFromPdb has failed. HRESULT - " + std::to_string(hr));
124 hr = (*dia_source)->openSession(session);
127 class_factory->Release();
128 throw std::runtime_error(
"openSession has failed. HRESULT - " + std::to_string(hr));
133 hr = (*session)->get_globalScope(symbol);
136 class_factory->Release();
137 throw std::runtime_error(
"get_globalScope has failed. HRESULT - " + std::to_string(hr));
140 class_factory->Release();
145 IDiaSymbol* symbol =
nullptr;
147 CComPtr<IDiaEnumSymbols> enum_symbols;
148 if (FAILED(g_symbol->findChildren(SymTagUDT,
nullptr, nsNone, &enum_symbols)))
149 throw std::runtime_error(
"Failed to find symbols");
152 while (SUCCEEDED(enum_symbols->Next(1, &symbol, &celt)) && celt == 1)
154 CComPtr<IDiaSymbol> sym(symbol);
156 const uint32_t sym_id = GetSymbolId(symbol);
157 if (visited_.find(sym_id) != visited_.end())
160 visited_.insert(sym_id);
162 std::string str_name = GetSymbolNameString(sym);
163 if (str_name.empty())
166 DumpType(sym, str_name, 0);
174 CComPtr<IDiaEnumSymbols> enum_symbols;
175 if (FAILED(g_symbol->findChildren(SymTagFunction,
nullptr, nsNone, &enum_symbols)))
176 throw std::runtime_error(
"Failed to find symbols");
179 while (SUCCEEDED(enum_symbols->Next(1, &symbol, &celt)) && celt == 1)
181 CComPtr<IDiaSymbol> sym(symbol);
184 if (sym->get_symTag(&sym_tag_type) != S_OK)
187 const uint32_t sym_id = GetSymbolId(sym);
188 if (visited_.find(sym_id) != visited_.end())
191 visited_.insert(sym_id);
193 std::string str_name = GetSymbolNameString(sym);
194 if (str_name.empty())
198 if (sym->get_addressOffset(&offset) != S_OK)
202 if (str_name.find(
'`') != std::string::npos)
206 if (str_name.find(
':') != std::string::npos)
208 const std::string new_str = ReplaceString(str_name,
"::",
".");
210 (*offsets_dump_)[new_str] = offset;
214 (*offsets_dump_)[
"Global." + str_name] = offset;
223 CComPtr<IDiaEnumSymbols> enum_symbols;
224 if (FAILED(g_symbol->findChildren(SymTagData,
nullptr, nsNone, &enum_symbols)))
225 throw std::runtime_error(
"Failed to find symbols");
228 while (SUCCEEDED(enum_symbols->Next(1, &symbol, &celt)) && celt == 1)
230 CComPtr<IDiaSymbol> sym(symbol);
232 const uint32_t sym_id = GetSymbolId(symbol);
233 if (visited_.find(sym_id) != visited_.end())
236 visited_.insert(sym_id);
238 std::string str_name = GetSymbolNameString(sym);
239 if (str_name.empty())
243 if (sym->get_symTag(&sym_tag) != S_OK)
247 if (sym->get_addressOffset(&offset) != S_OK)
250 (*offsets_dump_)[
"Global." + str_name] = offset;
256 CComPtr<IDiaEnumSymbols> enum_children;
257 IDiaSymbol* symbol_child;
264 if (symbol->get_symTag(&sym_tag) != S_OK)
270 DumpData(symbol, structure);
274 if (SUCCEEDED(symbol->findChildren(SymTagNull,
nullptr, nsNone, &enum_children)))
276 while (SUCCEEDED(enum_children->Next(1, &symbol_child, &celt)) && celt == 1)
278 CComPtr<IDiaSymbol> sym_child(symbol_child);
280 DumpType(sym_child, structure, indent + 2);
292 if (symbol->get_locationType(&loc_type) != S_OK)
295 if (loc_type != LocIsThisRel && loc_type != LocIsBitField)
298 CComPtr<IDiaSymbol> type;
299 if (symbol->get_type(&type) != S_OK)
306 if (symbol->get_offset(&offset) != S_OK)
309 std::string str_name = GetSymbolNameString(symbol);
310 if (str_name.empty())
313 if (loc_type == LocIsBitField)
316 if (symbol->get_bitPosition(&bit_position) != S_OK)
320 if (symbol->get_length(&num_bits) != S_OK)
324 if (type->get_length(&length) != S_OK)
327 const BitField bit_field{
static_cast<DWORD64>(offset), bit_position, num_bits, length};
329 (*bitfields_dump_)[structure +
"." + str_name] = bit_field;
331 else if (loc_type == LocIsThisRel)
333 (*offsets_dump_)[structure +
"." + str_name] = offset;
343 HRESULT hr = symbol->get_name(&str);
349 name = Tools::Utf8Encode(str);
360 symbol->get_symIndexId(&id);
365 void PdbReader::Cleanup(IDiaSymbol* symbol, IDiaSession* session, IDiaDataSource* source)
367 if (symbol !=
nullptr)
369 if (session !=
nullptr)
371 if (source !=
nullptr)
void DumpType(IDiaSymbol *, const std::string &, int) const
void DumpFunctions(IDiaSymbol *)
void DumpData(IDiaSymbol *, const std::string &) const
void DumpGlobalVariables(IDiaSymbol *)
void Read(const std::wstring &path, std::unordered_map< std::string, intptr_t > *offsets_dump, std::unordered_map< std::string, BitField > *bitfields_dump)
void DumpStructs(IDiaSymbol *)