Initial for async symbol loading.
This commit is contained in:
parent
3a3afa3744
commit
b176fb7e46
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue