1
0
Fork 0

Refactor symbol loading/query to use a common interface.

This commit is contained in:
ZehMatt 2017-11-22 01:02:25 +01:00 committed by Duncan Ogilvie
parent 121486a137
commit bd173bf01e
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
12 changed files with 292 additions and 102 deletions

View File

@ -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';

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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_

View File

@ -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;
}

32
src/dbg/symbolsourcepdb.h Normal file
View File

@ -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_

View File

@ -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)

View File

@ -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);

View File

@ -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" />

View File

@ -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>