Refactor symbol loading/query to use a common interface.
This commit is contained in:
parent
121486a137
commit
bd173bf01e
|
|
@ -187,17 +187,18 @@ static bool getLabel(duint addr, char* label, bool noFuncOffset)
|
|||
else //no user labels
|
||||
{
|
||||
DWORD64 displacement = 0;
|
||||
|
||||
// char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(char)];
|
||||
// PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
// pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
// pSymbol->MaxNameLen = MAX_LABEL_SIZE;
|
||||
// if (SafeSymFromAddr(fdProcessInfo->hProcess, (DWORD64)addr, &displacement, pSymbol) &&
|
||||
// (!displacement || (!noFuncOffset && pSymbol->Flags != SYMFLAG_EXPORT))) //without PDB, SYMFLAG_EXPORT is reported with garbage displacements
|
||||
|
||||
SymbolInfo symInfo;
|
||||
if (SymbolFromAddrCached(fdProcessInfo->hProcess, addr, symInfo))
|
||||
|
||||
bool res;
|
||||
if (noFuncOffset)
|
||||
res = SymbolFromAddressExact(addr, symInfo);
|
||||
else
|
||||
res = SymbolFromAddressExactOrLower(addr, symInfo);
|
||||
|
||||
if (res)
|
||||
{
|
||||
displacement = (DWORD64)symInfo.disp;
|
||||
|
||||
//auto name = demanglePE32ExternCFunc(symInfo.decoratedName.c_str());
|
||||
if (!bUndecorateSymbolNames || !SafeUnDecorateSymbolName(symInfo.decoratedName.c_str(), label, MAX_LABEL_SIZE, UNDNAME_NAME_ONLY))
|
||||
{
|
||||
|
|
@ -220,9 +221,13 @@ static bool getLabel(duint addr, char* label, bool noFuncOffset)
|
|||
duint val = 0;
|
||||
if (MemRead(basicinfo.memory.value, &val, sizeof(val), nullptr, true))
|
||||
{
|
||||
// if (SafeSymFromAddr(fdProcessInfo->hProcess, (DWORD64)val, &displacement, pSymbol) &&
|
||||
// (!displacement || (!noFuncOffset && pSymbol->Flags != SYMFLAG_EXPORT))) //without PDB, SYMFLAG_EXPORT is reported with garbage displacements
|
||||
if (SymbolFromAddrCached(fdProcessInfo->hProcess, addr, symInfo))
|
||||
bool res;
|
||||
if (noFuncOffset)
|
||||
res = SymbolFromAddressExact(addr, symInfo);
|
||||
else
|
||||
res = SymbolFromAddressExactOrLower(addr, symInfo);
|
||||
|
||||
if (res)
|
||||
{
|
||||
//pSymbol->Name[pSymbol->MaxNameLen - 1] = '\0';
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "threading.h"
|
||||
#include "symbolinfo.h"
|
||||
#include "murmurhash.h"
|
||||
#include "symbolsourcepdb.h"
|
||||
#include "memory.h"
|
||||
#include "label.h"
|
||||
#include <algorithm>
|
||||
|
|
@ -272,20 +273,38 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
|
|||
GetModuleInfo(info, (ULONG_PTR)data());
|
||||
}
|
||||
|
||||
// Load PDB if available.
|
||||
if (PDBDiaFile::initLibrary())
|
||||
// Load Symbols.
|
||||
info.symbols = &EmptySymbolSource; // Set to empty as default one.
|
||||
|
||||
// Try DIA
|
||||
if (info.symbols == &EmptySymbolSource &&
|
||||
SymbolSourcePDB::isLibraryAvailable())
|
||||
{
|
||||
if (!info.pdb.open(info.path))
|
||||
SymbolSourcePDB *symSource = new SymbolSourcePDB();
|
||||
if (symSource->loadPDB(info.path, info.base))
|
||||
{
|
||||
std::string msg = StringUtils::sprintf("Unable to load (MSDIA) PDB: %s\n", info.path);
|
||||
symSource->resizeSymbolBitmap(info.size);
|
||||
|
||||
info.symbols = symSource;
|
||||
|
||||
std::string msg = StringUtils::sprintf("Loaded (MSDIA) PDB: %s\n", info.path);
|
||||
GuiAddLogMessage(msg.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string msg = StringUtils::sprintf("Loaded (MSDIA) PDB: %s\n", info.path);
|
||||
GuiAddLogMessage(msg.c_str());
|
||||
delete symSource;
|
||||
}
|
||||
}
|
||||
if (info.symbols == &EmptySymbolSource &&
|
||||
true /* TODO */)
|
||||
{
|
||||
}
|
||||
|
||||
if (info.symbols->isLoaded())
|
||||
{
|
||||
std::string msg = StringUtils::sprintf("No symbols loaded for: %s\n", info.path);
|
||||
GuiAddLogMessage(msg.c_str());
|
||||
}
|
||||
|
||||
// Add module to list
|
||||
EXCLUSIVE_ACQUIRE(LockModules);
|
||||
|
|
@ -304,8 +323,6 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
SymUpdateModuleList();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
#include "_global.h"
|
||||
#include <functional>
|
||||
#include "pdbdiafile.h"
|
||||
|
||||
#include "symbolsourcebase.h"
|
||||
|
||||
struct MODSECTIONINFO
|
||||
{
|
||||
|
|
@ -44,7 +45,7 @@ struct MODINFO
|
|||
std::vector<MODRELOCATIONINFO> relocations;
|
||||
std::vector<duint> tlsCallbacks;
|
||||
std::vector<bool> invalidSymbols;
|
||||
PDBDiaFile pdb;
|
||||
SymbolSourceBase *symbols;
|
||||
|
||||
HANDLE fileHandle = nullptr;
|
||||
DWORD loadedSize = 0;
|
||||
|
|
|
|||
|
|
@ -49,16 +49,16 @@ bool PDBDiaFile::shutdownLibrary()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PDBDiaFile::open(const char *file, DiaValidationData_t *validationData)
|
||||
bool PDBDiaFile::open(const char *file, uint64_t loadAddress, DiaValidationData_t *validationData)
|
||||
{
|
||||
wchar_t buf[1024];
|
||||
|
||||
mbstowcs_s(nullptr, buf, file, 1024);
|
||||
|
||||
return open(buf, validationData);
|
||||
return open(buf, loadAddress, validationData);
|
||||
}
|
||||
|
||||
bool PDBDiaFile::open(const wchar_t *file, DiaValidationData_t *validationData)
|
||||
bool PDBDiaFile::open(const wchar_t *file, uint64_t loadAddress, DiaValidationData_t *validationData)
|
||||
{
|
||||
wchar_t fileExt[MAX_PATH] = { 0 };
|
||||
wchar_t fileDir[MAX_PATH] = { 0 };
|
||||
|
|
@ -129,6 +129,11 @@ bool PDBDiaFile::open(const wchar_t *file, DiaValidationData_t *validationData)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (loadAddress != 0)
|
||||
{
|
||||
m_session->put_loadAddress(loadAddress);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -801,7 +806,7 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<void(DiaSymbol_t&)> cal
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PDBDiaFile::findSymbolExactRVA(uint64_t address, DiaSymbol_t& sym, DiaSymbolType symType /*= DiaSymbolType::ANY*/)
|
||||
bool PDBDiaFile::findSymbolRVA(uint64_t address, DiaSymbol_t& sym, DiaSymbolType symType /*= DiaSymbolType::ANY*/)
|
||||
{
|
||||
if (m_session == nullptr || m_dataSource == nullptr)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ public:
|
|||
|
||||
static bool shutdownLibrary();
|
||||
|
||||
bool open(const char *file, DiaValidationData_t *validationData = nullptr);
|
||||
bool open(const char *file, uint64_t loadAddress = 0, DiaValidationData_t *validationData = nullptr);
|
||||
|
||||
bool open(const wchar_t *file, DiaValidationData_t *validationData = nullptr);
|
||||
bool open(const wchar_t *file, uint64_t loadAddress = 0, DiaValidationData_t *validationData = nullptr);
|
||||
|
||||
bool isOpen() const;
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
bool enumerateLexicalHierarchy(std::function<void(DiaSymbol_t&)> callback, const bool collectUndecoratedNames);
|
||||
|
||||
bool findSymbolExactRVA(uint64_t address, DiaSymbol_t& sym, DiaSymbolType symType = DiaSymbolType::ANY);
|
||||
bool findSymbolRVA(uint64_t address, DiaSymbol_t& sym, DiaSymbolType symType = DiaSymbolType::ANY);
|
||||
|
||||
private:
|
||||
bool testError(HRESULT hr);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef _SYMBOLSOURCEBASE_H_
|
||||
#define _SYMBOLSOURCEBASE_H_
|
||||
|
||||
#include "_global.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
struct SymbolInfo
|
||||
{
|
||||
duint addr;
|
||||
duint size;
|
||||
int32 disp;
|
||||
String decoratedName;
|
||||
String undecoratedName;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
class SymbolSourceBase
|
||||
{
|
||||
private:
|
||||
std::vector<uint8_t> _symbolBitmap;
|
||||
|
||||
public:
|
||||
virtual ~SymbolSourceBase() = default;
|
||||
|
||||
void resizeSymbolBitmap(size_t imageSize)
|
||||
{
|
||||
if (!isLoaded())
|
||||
return;
|
||||
|
||||
_symbolBitmap.resize(imageSize);
|
||||
std::fill(_symbolBitmap.begin(), _symbolBitmap.end(), false);
|
||||
}
|
||||
|
||||
void markAdressInvalid(uint32_t rva)
|
||||
{
|
||||
if (_symbolBitmap.empty())
|
||||
return;
|
||||
|
||||
_symbolBitmap[rva] = true;
|
||||
}
|
||||
|
||||
bool isAddressInvalid(uint32_t rva) const
|
||||
{
|
||||
if (_symbolBitmap.empty())
|
||||
return false;
|
||||
|
||||
return !!_symbolBitmap[rva];
|
||||
}
|
||||
|
||||
// Tells us if the symbols are loaded for this module.
|
||||
virtual bool isLoaded() const
|
||||
{
|
||||
return false; // Stub
|
||||
}
|
||||
|
||||
// Get the symbol at the specified address, will return false if not found.
|
||||
virtual bool findSymbolExact(duint rva, SymbolInfo& symInfo)
|
||||
{
|
||||
return false; // Stub
|
||||
}
|
||||
|
||||
// Get the symbol at the address or the closest behind, in case it got the closest it will set disp to non-zero, false on nothing.
|
||||
virtual bool findSymbolExactOrLower(duint rva, SymbolInfo& symInfo)
|
||||
{
|
||||
return false; // Stub
|
||||
}
|
||||
};
|
||||
|
||||
static SymbolSourceBase EmptySymbolSource;
|
||||
|
||||
#endif // _SYMBOLSOURCEBASE_H_
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
#include "symbolsourcepdb.h"
|
||||
|
||||
SymbolSourcePDB::~SymbolSourcePDB()
|
||||
{
|
||||
if (_pdb.isOpen())
|
||||
{
|
||||
_pdb.close();
|
||||
}
|
||||
}
|
||||
|
||||
bool SymbolSourcePDB::loadPDB(const std::string& path, duint imageBase)
|
||||
{
|
||||
if (!PDBDiaFile::initLibrary())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return _pdb.open(path.c_str());
|
||||
}
|
||||
|
||||
bool SymbolSourcePDB::isLoaded() const
|
||||
{
|
||||
return _pdb.isOpen();
|
||||
}
|
||||
|
||||
bool SymbolSourcePDB::findSymbolExact(duint rva, SymbolInfo& symInfo)
|
||||
{
|
||||
if (SymbolSourceBase::isAddressInvalid(rva))
|
||||
return false;
|
||||
|
||||
auto it = _symbols.find(rva);
|
||||
if (it != _symbols.end())
|
||||
{
|
||||
symInfo = it->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
DiaSymbol_t sym;
|
||||
if (_pdb.findSymbolRVA(rva, sym) && sym.disp == 0)
|
||||
{
|
||||
symInfo.addr = rva;
|
||||
symInfo.disp = 0;
|
||||
symInfo.size = sym.size;
|
||||
symInfo.decoratedName = sym.undecoratedName;
|
||||
symInfo.undecoratedName = sym.undecoratedName;
|
||||
symInfo.valid = true;
|
||||
|
||||
_symbols.insert(std::make_pair(rva, symInfo));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
markAdressInvalid(rva);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
typename A::iterator findExactOrLower(A& ctr, const B key)
|
||||
{
|
||||
if (ctr.empty())
|
||||
return ctr.end();
|
||||
|
||||
auto itr = ctr.lower_bound(key);
|
||||
|
||||
if (itr == ctr.begin() && itr->first != key)
|
||||
return ctr.end();
|
||||
else if (itr == ctr.end() || itr->first != key)
|
||||
return --itr;
|
||||
|
||||
return itr;
|
||||
}
|
||||
|
||||
bool SymbolSourcePDB::findSymbolExactOrLower(duint rva, SymbolInfo& symInfo)
|
||||
{
|
||||
auto it = findExactOrLower(_symbols, rva);
|
||||
if (it != _symbols.end())
|
||||
{
|
||||
symInfo = it->second;
|
||||
symInfo.disp = rva - symInfo.addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
DiaSymbol_t sym;
|
||||
if (_pdb.findSymbolRVA(rva, sym))
|
||||
{
|
||||
symInfo.addr = rva;
|
||||
symInfo.disp = sym.disp;
|
||||
symInfo.size = sym.size;
|
||||
symInfo.decoratedName = sym.undecoratedName;
|
||||
symInfo.undecoratedName = sym.undecoratedName;
|
||||
symInfo.valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef _SYMBOLSOURCEPDB_H_
|
||||
#define _SYMBOLSOURCEPDB_H_
|
||||
|
||||
#include "pdbdiafile.h"
|
||||
#include "symbolsourcebase.h"
|
||||
|
||||
class SymbolSourcePDB : public SymbolSourceBase
|
||||
{
|
||||
private:
|
||||
PDBDiaFile _pdb;
|
||||
std::map<duint, SymbolInfo> _symbols;
|
||||
|
||||
public:
|
||||
static bool isLibraryAvailable()
|
||||
{
|
||||
return PDBDiaFile::initLibrary();
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~SymbolSourcePDB();
|
||||
|
||||
virtual bool isLoaded() const;
|
||||
|
||||
virtual bool findSymbolExact(duint rva, SymbolInfo& symInfo);
|
||||
|
||||
virtual bool findSymbolExactOrLower(duint rva, SymbolInfo& symInfo);
|
||||
|
||||
public:
|
||||
bool loadPDB(const std::string& path, duint imageBase);
|
||||
};
|
||||
|
||||
#endif // _SYMBOLSOURCEPDB_H_
|
||||
|
|
@ -12,7 +12,7 @@ static std::unordered_map<duint, duint> symbolName;
|
|||
|
||||
static SortedLRU<duint, SymbolInfo> symbolCache;
|
||||
|
||||
bool SymbolFromAddrCached(HANDLE hProcess, duint address, SymbolInfo& symInfo)
|
||||
bool SymbolFromAddressExact(duint address, SymbolInfo& symInfo)
|
||||
{
|
||||
if (address == 0)
|
||||
return false;
|
||||
|
|
@ -20,78 +20,32 @@ bool SymbolFromAddrCached(HANDLE hProcess, duint address, SymbolInfo& symInfo)
|
|||
MODINFO* modInfo = ModInfoFromAddr(address);
|
||||
if (modInfo)
|
||||
{
|
||||
uint64_t rva = address - modInfo->base;
|
||||
if (modInfo->invalidSymbols[rva] == true)
|
||||
if (modInfo->symbols->isLoaded() == false)
|
||||
return false;
|
||||
|
||||
auto it = symbolCache.find(address);
|
||||
if (symbolCache.acquire(it))
|
||||
{
|
||||
symInfo = (*it).second;
|
||||
return symInfo.valid;
|
||||
}
|
||||
|
||||
if (modInfo->pdb.isOpen())
|
||||
{
|
||||
DiaSymbol_t diaSym;
|
||||
diaSym.disp = 0;
|
||||
|
||||
if (modInfo->pdb.findSymbolExactRVA(rva, diaSym) && diaSym.disp == 0)
|
||||
{
|
||||
symInfo.addr = diaSym.virtualAddress;
|
||||
symInfo.decoratedName = diaSym.name;
|
||||
symInfo.undecoratedName = diaSym.name;
|
||||
symInfo.size = diaSym.size;
|
||||
symInfo.valid = true;
|
||||
|
||||
symbolCache.insert(address, symInfo);
|
||||
|
||||
return symInfo.valid;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flag as invalid.
|
||||
modInfo->invalidSymbols[rva] = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
duint rva = address - modInfo->base;
|
||||
return modInfo->symbols->findSymbolExact(rva, symInfo);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Non-Module?
|
||||
auto it = symbolCache.find(address);
|
||||
if (symbolCache.acquire(it))
|
||||
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo& symInfo)
|
||||
{
|
||||
if (address == 0)
|
||||
return false;
|
||||
|
||||
MODINFO* modInfo = ModInfoFromAddr(address);
|
||||
if (modInfo)
|
||||
{
|
||||
symInfo = (*it).second;
|
||||
return symInfo.valid;
|
||||
if (modInfo->symbols->isLoaded() == false)
|
||||
return false;
|
||||
|
||||
duint rva = address - modInfo->base;
|
||||
return modInfo->symbols->findSymbolExactOrLower(rva, symInfo);
|
||||
}
|
||||
|
||||
DWORD64 disp = 0;
|
||||
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(char)];
|
||||
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_LABEL_SIZE;
|
||||
|
||||
// For performance reasons we map invalid symbols as invalid, for now.
|
||||
if (SafeSymFromAddr(hProcess, address, &disp, pSymbol) == TRUE && disp == 0)
|
||||
{
|
||||
symInfo.addr = pSymbol->Address;
|
||||
symInfo.decoratedName = pSymbol->Name;
|
||||
symInfo.undecoratedName = pSymbol->Name;
|
||||
symInfo.size = pSymbol->Size;
|
||||
symInfo.valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
symInfo.valid = false;
|
||||
}
|
||||
|
||||
symbolCache.insert(address, symInfo);
|
||||
|
||||
return symInfo.valid;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SymbolFromAddr(duint addr, SymbolInfo & symbol)
|
||||
|
|
|
|||
|
|
@ -2,14 +2,7 @@
|
|||
|
||||
#include "_global.h"
|
||||
|
||||
struct SymbolInfo
|
||||
{
|
||||
duint addr;
|
||||
duint size;
|
||||
String decoratedName;
|
||||
String undecoratedName;
|
||||
bool valid;
|
||||
};
|
||||
#include "symbolsourcebase.h"
|
||||
|
||||
struct LineInfo
|
||||
{
|
||||
|
|
@ -19,7 +12,8 @@ struct LineInfo
|
|||
String sourceFile;
|
||||
};
|
||||
|
||||
bool SymbolFromAddrCached(HANDLE hProcess, duint address, SymbolInfo& symInfo);
|
||||
bool SymbolFromAddressExact(duint address, SymbolInfo& symInfo);
|
||||
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo& symInfo);
|
||||
|
||||
bool SymbolFromAddr(duint addr, SymbolInfo & symbol);
|
||||
bool SymbolFromName(const char* name, SymbolInfo & symbol);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@
|
|||
<ClCompile Include="stringformat.cpp" />
|
||||
<ClCompile Include="stringutils.cpp" />
|
||||
<ClCompile Include="symbolinfo.cpp" />
|
||||
<ClCompile Include="symbolsourcepdb.cpp" />
|
||||
<ClCompile Include="symcache.cpp" />
|
||||
<ClCompile Include="tcpconnections.cpp" />
|
||||
<ClCompile Include="thread.cpp" />
|
||||
|
|
@ -234,6 +235,8 @@
|
|||
<ClInclude Include="reference.h" />
|
||||
<ClInclude Include="serializablemap.h" />
|
||||
<ClInclude Include="sortedlru.h" />
|
||||
<ClInclude Include="symbolsourcebase.h" />
|
||||
<ClInclude Include="symbolsourcepdb.h" />
|
||||
<ClInclude Include="symcache.h" />
|
||||
<ClInclude Include="taskthread.h" />
|
||||
<ClInclude Include="tcpconnections.h" />
|
||||
|
|
|
|||
|
|
@ -434,6 +434,9 @@
|
|||
<ClCompile Include="pdbdiafile.cpp">
|
||||
<Filter>Source Files\Information</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="symbolsourcepdb.cpp">
|
||||
<Filter>Source Files\Information</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="msdia\diacreate.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -964,5 +967,11 @@
|
|||
<ClInclude Include="pdbdiafile.h">
|
||||
<Filter>Header Files\Information</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="symbolsourcebase.h">
|
||||
<Filter>Header Files\Information</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="symbolsourcepdb.h">
|
||||
<Filter>Header Files\Information</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
Reference in New Issue