1
0
Fork 0

DBG: add symload command to manually load a PDB

This commit is contained in:
Duncan Ogilvie 2019-06-12 16:51:19 +02:00
parent 4ce5b0baec
commit 1e075142a5
9 changed files with 92 additions and 46 deletions

View File

@ -188,6 +188,44 @@ bool cbDebugDownloadSymbol(int argc, char* argv[])
return true;
}
bool cbDebugLoadSymbol(int argc, char* argv[])
{
if(IsArgumentsLessThan(argc, 3))
return false;
//get some module information
duint modbase = ModBaseFromName(argv[1]);
if(!modbase)
{
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid module \"%s\"!\n"), argv[1]);
return false;
}
auto pdbFile = argv[2];
if(!FileExists(pdbFile))
{
dputs(QT_TRANSLATE_NOOP("DBG", "File does not exist!"));
return false;
}
bool forceLoad = argc > 3 && DbgEval(argv[3]);
EXCLUSIVE_ACQUIRE(LockModules);
auto info = ModInfoFromAddr(modbase);
if(!info)
{
// TODO: this really isn't supposed to happen, but could if the module is suddenly unloaded
dputs("module not found...");
return false;
}
// trigger a symbol load
if(!info->loadSymbols(pdbFile, forceLoad))
{
dputs(QT_TRANSLATE_NOOP("DBG", "Symbol load failed... See symbol log for more information"));
return false;
}
GuiSymbolRefreshCurrent();
dputs(QT_TRANSLATE_NOOP("DBG", "Done! See symbol log for more information"));
return true;
}
bool cbInstrImageinfo(int argc, char* argv[])
{
duint address;

View File

@ -12,6 +12,7 @@ bool cbInstrAnalyseadv(int argc, char* argv[]);
bool cbInstrVirtualmod(int argc, char* argv[]);
bool cbDebugDownloadSymbol(int argc, char* argv[]);
bool cbDebugLoadSymbol(int argc, char* argv[]);
bool cbInstrImageinfo(int argc, char* argv[]);
bool cbInstrGetRelocSize(int argc, char* argv[]);
bool cbInstrExhandlers(int argc, char* argv[]);

View File

@ -832,8 +832,13 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
GetModuleInfo(info, (ULONG_PTR)data());
}
info.symbols = &EmptySymbolSource; // empty symbol source per default
// TODO: setting to auto load symbols
info.loadSymbols();
for(const auto & pdbPath : info.pdbPaths)
{
if(info.loadSymbols(pdbPath, bForceLoadSymbols))
break;
}
// Add module to list
EXCLUSIVE_ACQUIRE(LockModules);
@ -1192,10 +1197,9 @@ bool ModRelocationsInRange(duint Address, duint Size, std::vector<MODRELOCATIONI
return !Relocations.empty();
}
bool MODINFO::loadSymbols()
bool MODINFO::loadSymbols(const String & pdbPath, bool forceLoad)
{
unloadSymbols();
symbols = &EmptySymbolSource; // empty symbol source per default
// Try DIA
if(symbols == &EmptySymbolSource && SymbolSourceDIA::isLibraryAvailable())
@ -1208,32 +1212,29 @@ bool MODINFO::loadSymbols()
validationData.signature = pdbValidation.signature;
validationData.age = pdbValidation.age;
SymbolSourceDIA* symSource = new SymbolSourceDIA();
for(const auto & pdbPath : pdbPaths)
if(!FileExists(pdbPath.c_str()))
{
if(!FileExists(pdbPath.c_str()))
{
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Skipping non-existent PDB: %s\n", pdbPath.c_str()).c_str());
}
else if(symSource->loadPDB(pdbPath, modname, base, size, bForceLoadSymbols ? nullptr : &validationData))
{
symSource->resizeSymbolBitmap(size);
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Skipping non-existent PDB: %s\n", pdbPath.c_str()).c_str());
}
else if(symSource->loadPDB(pdbPath, modname, base, size, forceLoad ? nullptr : &validationData))
{
symSource->resizeSymbolBitmap(size);
symbols = symSource;
symbols = symSource;
std::string msg;
if(symSource->isLoading())
msg = StringUtils::sprintf("[DIA] Loading PDB (async): %s\n", pdbPath.c_str());
else
msg = StringUtils::sprintf("[DIA] Loaded PDB: %s\n", pdbPath.c_str());
GuiSymbolLogAdd(msg.c_str());
return true;
}
std::string msg;
if(symSource->isLoading())
msg = StringUtils::sprintf("[DIA] Loading PDB (async): %s\n", pdbPath.c_str());
else
{
// TODO: more detailled error codes?
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Failed to load PDB: %s\n", pdbPath.c_str()).c_str());
}
msg = StringUtils::sprintf("[DIA] Loaded PDB: %s\n", pdbPath.c_str());
GuiSymbolLogAdd(msg.c_str());
return true;
}
else
{
// TODO: more detailled error codes?
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Failed to load PDB: %s\n", pdbPath.c_str()).c_str());
}
delete symSource;
}

View File

@ -129,7 +129,7 @@ struct MODINFO
GuiInvalidateSymbolSource(base);
}
bool loadSymbols();
bool loadSymbols(const String & pdbPath, bool forceLoad);
void unloadSymbols();
void unmapFile();
const MODEXPORT* findExport(duint rva) const;

View File

@ -274,7 +274,7 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
if(validationData != nullptr)
{
CComPtr<IDiaSymbol> globalSym;
IDiaSymbol* globalSym = nullptr;
hr = m_session->get_globalScope(&globalSym);
if(testError(hr))
{
@ -286,9 +286,10 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
hr = globalSym->get_age(&age);
if(!testError(hr) && validationData->age != age)
{
globalSym->Release();
close();
GuiSymbolLogAdd("PDB age is not matching.\n");
GuiSymbolLogAdd(StringUtils::sprintf("Validation error: PDB age is not matching (expected: %u, actual: %u).\n", validationData->age, age).c_str());
return false;
}
@ -310,12 +311,28 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
hr = globalSym->get_guid(&guid);
if(!testError(hr) && memcmp(&guid, &validationData->guid, sizeof(GUID)) != 0)
{
globalSym->Release();
close();
GuiSymbolLogAdd("PDB guid is not matching.\n");
auto guidStr = [](const GUID & guid) -> String
{
// https://stackoverflow.com/a/22848342/1806760
char guid_string[37]; // 32 hex chars + 4 hyphens + null terminator
sprintf_s(guid_string,
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2],
guid.Data4[3], guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
return guid_string;
};
GuiSymbolLogAdd(StringUtils::sprintf("Validation error: PDB guid is not matching (expected: %s, actual: %s).\n",
guidStr(validationData->guid).c_str(), guidStr(guid).c_str()).c_str());
return false;
}
}
globalSym->Release();
}
else
{

View File

@ -513,7 +513,7 @@ String StringUtils::ToHex(unsigned long long value)
#define HEXLOOKUP "0123456789ABCDEF"
String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
String StringUtils::ToHex(const unsigned char* buffer, size_t size, bool reverse)
{
String result;
result.resize(size * 2);
@ -526,7 +526,7 @@ String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
return result;
}
String StringUtils::ToCompressedHex(unsigned char* buffer, size_t size)
String StringUtils::ToCompressedHex(const unsigned char* buffer, size_t size)
{
if(!size)
return "";

View File

@ -42,8 +42,8 @@ public:
static bool EndsWith(const String & str, const String & suffix);
static bool FromHex(const String & text, std::vector<unsigned char> & data, bool reverse = false);
static String ToHex(unsigned long long value);
static String ToHex(unsigned char* buffer, size_t size, bool reverse = false);
static String ToCompressedHex(unsigned char* buffer, size_t size);
static String ToHex(const unsigned char* buffer, size_t size, bool reverse = false);
static String ToCompressedHex(const unsigned char* buffer, size_t size);
static bool FromCompressedHex(const String & text, std::vector<unsigned char> & data);
template<typename T>

View File

@ -243,20 +243,8 @@ bool SymDownloadSymbol(duint Base, const char* SymbolStore)
return false;
}
// insert the downloaded symbol path in the beginning of the PDB load order
auto destPathUtf8 = StringUtils::Utf16ToUtf8(destinationPath);
for(auto it = info->pdbPaths.begin(); it != info->pdbPaths.end(); ++it)
{
if(*it == destPathUtf8)
{
info->pdbPaths.erase(it);
break;
}
}
info->pdbPaths.insert(info->pdbPaths.begin(), destPathUtf8);
// trigger a symbol load
info->loadSymbols();
info->loadSymbols(StringUtils::Utf16ToUtf8(destinationPath), bForceLoadSymbols);
}
return true;

View File

@ -324,6 +324,7 @@ static void registercommands()
dbgcmdnew("virtualmod", cbInstrVirtualmod, true); //virtual module
dbgcmdnew("symdownload,downloadsym", cbDebugDownloadSymbol, true); //download symbols
dbgcmdnew("symload,loadsym", cbDebugLoadSymbol, true); //load symbols
dbgcmdnew("imageinfo,modimageinfo", cbInstrImageinfo, true); //print module image information
dbgcmdnew("GetRelocSize,grs", cbInstrGetRelocSize, true); //get relocation table size
dbgcmdnew("exhandlers", cbInstrExhandlers, true); //enumerate exception handlers