8#include "../Private/Helpers.h"
9#include "../Private/Offsets.h"
34 operator T*() {
return _sym; }
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)
50 std::ifstream f{path};
52 throw std::runtime_error(
"Failed to open pdb file");
54 IDiaDataSource* data_source;
55 IDiaSession* dia_session;
62 catch (
const std::runtime_error&)
64 Log::GetLog()->error(
"Failed to load data from pdb file ");
77 Cleanup(symbol, dia_session, data_source);
79 Log::GetLog()->info(
"Successfully read information from PDB\n");
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;
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)
163 if (str_name.empty())
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)
184 if (sym->get_symTag(&sym_tag_type) != S_OK)
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;
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)
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;
257 IDiaSymbol* symbol_child;
264 if (symbol->get_symTag(&sym_tag) != S_OK)
274 if (SUCCEEDED(symbol->findChildren(SymTagNull,
nullptr, nsNone, &enum_children)))
276 while (SUCCEEDED(enum_children->Next(1, &symbol_child, &celt)) && celt == 1)
280 DumpType(sym_child, structure, indent + 2);
292 if (symbol->get_locationType(&loc_type) != S_OK)
295 if (loc_type != LocIsThisRel && loc_type != LocIsBitField)
299 if (symbol->get_type(&
type) != S_OK)
306 if (symbol->get_offset(&offset) != S_OK)
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);
360 symbol->get_symIndexId(&
id);
367 if (symbol !=
nullptr)
369 if (session !=
nullptr)
371 if (source !=
nullptr)
void DumpType(IDiaSymbol *, const std::string &, int) const
std::unordered_set< uint32_t > visited_
std::unordered_map< std::string, BitField > * bitfields_dump_
void DumpFunctions(IDiaSymbol *)
static void LoadDataFromPdb(const std::wstring &, IDiaDataSource **, IDiaSession **, IDiaSymbol **)
std::unordered_map< std::string, intptr_t > * offsets_dump_
static uint32_t GetSymbolId(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 *)
static void Cleanup(IDiaSymbol *, IDiaSession *, IDiaDataSource *)
static std::string GetSymbolNameString(IDiaSymbol *)
static std::shared_ptr< spdlog::logger > & GetLog()
std::string ReplaceString(std::string subject, const std::string &search, const std::string &replace)
const ASN1_OBJECT int type