DBG: add symload command to manually load a PDB
This commit is contained in:
parent
4ce5b0baec
commit
1e075142a5
|
@ -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;
|
||||
|
|
|
@ -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[]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 "";
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue