1
0
Fork 0

Initial for async symbol loading.

This commit is contained in:
ZehMatt 2017-12-08 02:21:20 +01:00 committed by Duncan Ogilvie
parent 3a3afa3744
commit b176fb7e46
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
6 changed files with 1319 additions and 1193 deletions

View File

@ -222,12 +222,12 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
// Copy information to struct
strcpy_s(info.name, file);
info.base = Base;
info.size = Size;
info.size = Size;
info.fileHandle = nullptr;
info.loadedSize = 0;
info.fileMap = nullptr;
info.fileMapVA = 0;
info.invalidSymbols.resize(Size);
info.invalidSymbols.resize(Size);
// Determine whether the module is located in system
wchar_t sysdir[MAX_PATH];
@ -255,10 +255,10 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
{
GetModuleInfo(info, info.fileMapVA);
Size = GetPE32DataFromMappedFile(info.fileMapVA, 0, UE_SIZEOFIMAGE);
info.size = Size;
Size = GetPE32DataFromMappedFile(info.fileMapVA, 0, UE_SIZEOFIMAGE);
info.size = Size;
dprintf("Module Size: %08X\n", info.size);
dprintf("Module Size: %08X\n", info.size);
}
else
{
@ -278,38 +278,43 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
GetModuleInfo(info, (ULONG_PTR)data());
}
// Load Symbols.
info.symbols = &EmptySymbolSource; // Set to empty as default one.
// Load Symbols.
info.symbols = &EmptySymbolSource; // Set to empty as default one.
// Try DIA
if (info.symbols == &EmptySymbolSource &&
SymbolSourcePDB::isLibraryAvailable())
{
SymbolSourcePDB *symSource = new SymbolSourcePDB();
if (symSource->loadPDB(info.path, Base))
{
symSource->resizeSymbolBitmap(info.size);
// Try DIA
if(info.symbols == &EmptySymbolSource &&
SymbolSourcePDB::isLibraryAvailable())
{
SymbolSourcePDB* symSource = new SymbolSourcePDB();
if(symSource->loadPDB(info.path, Base))
{
symSource->resizeSymbolBitmap(info.size);
info.symbols = symSource;
info.symbols = symSource;
std::string msg = StringUtils::sprintf("Loaded (MSDIA) PDB: %s\n", info.path);
GuiAddLogMessage(msg.c_str());
}
else
{
delete symSource;
}
}
if (info.symbols == &EmptySymbolSource &&
true /* TODO */)
{
}
std::string msg;
if(symSource->isLoading())
msg = StringUtils::sprintf("Loading async (MSDIA) PDB: %s\n", info.path);
else
msg = StringUtils::sprintf("Loaded (MSDIA) PDB: %s\n", info.path);
if (info.symbols->isLoaded() == false)
{
std::string msg = StringUtils::sprintf("No symbols loaded for: %s\n", info.path);
GuiAddLogMessage(msg.c_str());
}
GuiAddLogMessage(msg.c_str());
}
else
{
delete symSource;
}
}
if(info.symbols == &EmptySymbolSource &&
true /* TODO */)
{
}
if(info.symbols->isOpen() == false)
{
std::string msg = StringUtils::sprintf("No symbols loaded for: %s\n", info.path);
GuiAddLogMessage(msg.c_str());
}
// Add module to list
EXCLUSIVE_ACQUIRE(LockModules);

File diff suppressed because it is too large Load Diff

View File

@ -8,64 +8,69 @@
struct SymbolInfo
{
duint addr;
duint size;
int32 disp;
String decoratedName;
String undecoratedName;
bool valid;
duint addr;
duint size;
int32 disp;
String decoratedName;
String undecoratedName;
bool valid;
};
class SymbolSourceBase
{
private:
std::vector<uint8_t> _symbolBitmap;
std::vector<uint8_t> _symbolBitmap;
public:
virtual ~SymbolSourceBase() = default;
virtual ~SymbolSourceBase() = default;
void resizeSymbolBitmap(size_t imageSize)
{
if (!isLoaded())
return;
void resizeSymbolBitmap(size_t imageSize)
{
if(!isOpen())
return;
_symbolBitmap.resize(imageSize);
std::fill(_symbolBitmap.begin(), _symbolBitmap.end(), false);
}
_symbolBitmap.resize(imageSize);
std::fill(_symbolBitmap.begin(), _symbolBitmap.end(), false);
}
void markAdressInvalid(duint rva)
{
if (_symbolBitmap.empty())
return;
void markAdressInvalid(duint rva)
{
if(_symbolBitmap.empty())
return;
_symbolBitmap[rva] = true;
}
_symbolBitmap[rva] = true;
}
bool isAddressInvalid(duint rva) const
{
if (_symbolBitmap.empty())
return false;
bool isAddressInvalid(duint rva) const
{
if(_symbolBitmap.empty())
return false;
return !!_symbolBitmap[rva];
}
return !!_symbolBitmap[rva];
}
// Tells us if the symbols are loaded for this module.
virtual bool isLoaded() const
{
return false; // Stub
}
// Tells us if the symbols are loaded for this module.
virtual bool isOpen() 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
}
virtual bool isLoading() const
{
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
}
// 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;

View File

@ -1,97 +1,194 @@
#include "symbolsourcepdb.h"
#include "console.h"
#include "debugger.h"
class ScopedCriticalSection
{
private:
CRITICAL_SECTION* _cs;
public:
ScopedCriticalSection(CRITICAL_SECTION* cs) : _cs(cs) { EnterCriticalSection(cs); }
~ScopedCriticalSection() { LeaveCriticalSection(_cs); }
};
SymbolSourcePDB::SymbolSourcePDB()
: _isLoading(false),
_requiresShutdown(false)
{
InitializeCriticalSection(&_cs);
}
SymbolSourcePDB::~SymbolSourcePDB()
{
if (_pdb.isOpen())
{
_pdb.close();
}
if(_isLoading)
{
_requiresShutdown = true;
if(_loadThread.joinable())
_loadThread.join();
}
if(_pdb.isOpen())
{
_pdb.close();
}
DeleteCriticalSection(&_cs);
}
bool SymbolSourcePDB::loadPDB(const std::string& path, duint imageBase)
bool SymbolSourcePDB::loadPDB(const std::string & path, duint imageBase)
{
if (!PDBDiaFile::initLibrary())
{
return false;
}
return _pdb.open(path.c_str());
if(!PDBDiaFile::initLibrary())
{
return false;
}
#if 1
bool res = _pdb.open(path.c_str());
if(res)
{
_isLoading = true;
_requiresShutdown = false;
_loadStart = GetTickCount64();
_loadThread = std::thread(&SymbolSourcePDB::loadPDBAsync, this);
}
return res;
#else
return _pdb.open(path.c_str());
#endif
}
bool SymbolSourcePDB::isLoaded() const
bool SymbolSourcePDB::isOpen() const
{
return _pdb.isOpen();
return _pdb.isOpen();
}
bool SymbolSourcePDB::findSymbolExact(duint rva, SymbolInfo& symInfo)
bool SymbolSourcePDB::isLoading() const
{
if (SymbolSourceBase::isAddressInvalid(rva))
return false;
return _isLoading;
}
auto it = _symbols.find(rva);
if (it != _symbols.end())
{
symInfo = (*it).second;
return true;
}
void SymbolSourcePDB::loadPDBAsync()
{
_pdb.enumerateLexicalHierarchy([&](DiaSymbol_t & sym)->void
{
// FIXME: This won't do us any good atm.
if(_requiresShutdown)
return;
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;
if(sym.type == DiaSymbolType::FUNCTION ||
sym.type == DiaSymbolType::LABEL ||
sym.type == DiaSymbolType::DATA)
{
SymbolInfo symInfo;
symInfo.decoratedName = sym.name;
symInfo.undecoratedName = sym.undecoratedName;
symInfo.size = sym.size;
symInfo.disp = sym.disp;
symInfo.addr = sym.virtualAddress;
_symbols.insert(rva, symInfo);
EnterCriticalSection(&_cs);
_sym.insert(std::make_pair(symInfo.addr, symInfo));
return true;
}
if(_sym.size() % 1000 == 0)
{
GuiUpdateAllViews();
}
LeaveCriticalSection(&_cs);
}
markAdressInvalid(rva);
return false;
}, true);
DWORD64 ms = GetTickCount64() - _loadStart;
double secs = (double)ms / 1000.0;
dprintf("Loaded %d symbols in %.03f\n", _sym.size(), secs);
GuiUpdateAllViews();
_isLoading = false;
}
bool SymbolSourcePDB::findSymbolExact(duint rva, SymbolInfo & symInfo)
{
ScopedCriticalSection lock(&_cs);
if(SymbolSourceBase::isAddressInvalid(rva))
return false;
auto it = _sym.find(rva);
if(it != _sym.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(rva, symInfo);
return true;
}
*/
#if 1
if(_isLoading == false)
markAdressInvalid(rva);
#endif
return false;
}
template <typename A, typename B>
typename A::iterator findExactOrLower(A& ctr, const B key)
typename A::iterator findExactOrLower(A & ctr, const B key)
{
if (ctr.empty())
return ctr.end();
if(ctr.empty())
return ctr.end();
auto itr = ctr.lower_bound(key);
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;
if(itr == ctr.begin() && (*itr).first != key)
return ctr.end();
else if(itr == ctr.end() || (*itr).first != key)
return --itr;
return itr;
return itr;
}
bool SymbolSourcePDB::findSymbolExactOrLower(duint rva, SymbolInfo& symInfo)
bool SymbolSourcePDB::findSymbolExactOrLower(duint rva, SymbolInfo & symInfo)
{
auto it = findExactOrLower(_symbols, rva);
if (it != _symbols.end())
{
symInfo = (*it).second;
symInfo.disp = (int32_t)(rva - symInfo.addr);
return true;
}
ScopedCriticalSection lock(&_cs);
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;
auto it = findExactOrLower(_sym, rva);
if(it != _sym.end())
{
symInfo = (*it).second;
symInfo.disp = (int32_t)(rva - symInfo.addr);
return true;
}
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 nullptr;
return true;
}
*/
return nullptr;
}

View File

@ -5,29 +5,47 @@
#include "symbolsourcebase.h"
#include "sortedlru.h"
#include <thread>
#include <atomic>
#include <mutex>
class SymbolSourcePDB : public SymbolSourceBase
{
private:
PDBDiaFile _pdb;
SortedLRU<duint, SymbolInfo> _symbols;
PDBDiaFile _pdb;
SortedLRU<duint, SymbolInfo> _symbols;
std::map<duint, SymbolInfo> _sym;
std::thread _loadThread;
std::atomic<bool> _isLoading;
std::atomic<bool> _requiresShutdown;
std::atomic_flag _isWriting;
CRITICAL_SECTION _cs;
DWORD64 _loadStart;
public:
static bool isLibraryAvailable()
{
return PDBDiaFile::initLibrary();
}
static bool isLibraryAvailable()
{
return PDBDiaFile::initLibrary();
}
public:
virtual ~SymbolSourcePDB();
SymbolSourcePDB();
virtual bool isLoaded() const;
virtual ~SymbolSourcePDB();
virtual bool findSymbolExact(duint rva, SymbolInfo& symInfo);
virtual bool isOpen() const;
virtual bool findSymbolExactOrLower(duint rva, SymbolInfo& symInfo);
virtual bool isLoading() const;
virtual bool findSymbolExact(duint rva, SymbolInfo & symInfo);
virtual bool findSymbolExactOrLower(duint rva, SymbolInfo & symInfo);
public:
bool loadPDB(const std::string& path, duint imageBase);
bool loadPDB(const std::string & path, duint imageBase);
private:
void loadPDBAsync();
};
#endif // _SYMBOLSOURCEPDB_H_

View File

@ -12,40 +12,40 @@ static std::unordered_map<duint, duint> symbolName;
static SortedLRU<duint, SymbolInfo> symbolCache;
bool SymbolFromAddressExact(duint address, SymbolInfo& symInfo)
bool SymbolFromAddressExact(duint address, SymbolInfo & symInfo)
{
if (address == 0)
return false;
if(address == 0)
return false;
MODINFO* modInfo = ModInfoFromAddr(address);
if (modInfo)
{
if (modInfo->symbols->isLoaded() == false)
return false;
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo)
{
if(modInfo->symbols->isOpen() == false)
return false;
duint rva = address - modInfo->base;
return modInfo->symbols->findSymbolExact(rva, symInfo);
}
duint rva = address - modInfo->base;
return modInfo->symbols->findSymbolExact(rva, symInfo);
}
return false;
return false;
}
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo& symInfo)
bool SymbolFromAddressExactOrLower(duint address, SymbolInfo & symInfo)
{
if (address == 0)
return false;
if(address == 0)
return false;
MODINFO* modInfo = ModInfoFromAddr(address);
if (modInfo)
{
if (modInfo->symbols->isLoaded() == false)
return false;
MODINFO* modInfo = ModInfoFromAddr(address);
if(modInfo)
{
if(modInfo->symbols->isOpen() == false)
return false;
duint rva = address - modInfo->base;
return modInfo->symbols->findSymbolExactOrLower(rva, symInfo);
}
duint rva = address - modInfo->base;
return modInfo->symbols->findSymbolExactOrLower(rva, symInfo);
}
return false;
return false;
}
bool SymbolFromAddr(duint addr, SymbolInfo & symbol)