Skip to content

Commit 1e07514

Browse files
committed
DBG: add symload command to manually load a PDB
1 parent 4ce5b0b commit 1e07514

File tree

9 files changed

+92
-46
lines changed

9 files changed

+92
-46
lines changed

src/dbg/commands/cmd-analysis.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,44 @@ bool cbDebugDownloadSymbol(int argc, char* argv[])
188188
return true;
189189
}
190190

191+
bool cbDebugLoadSymbol(int argc, char* argv[])
192+
{
193+
if(IsArgumentsLessThan(argc, 3))
194+
return false;
195+
//get some module information
196+
duint modbase = ModBaseFromName(argv[1]);
197+
if(!modbase)
198+
{
199+
dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid module \"%s\"!\n"), argv[1]);
200+
return false;
201+
}
202+
auto pdbFile = argv[2];
203+
if(!FileExists(pdbFile))
204+
{
205+
dputs(QT_TRANSLATE_NOOP("DBG", "File does not exist!"));
206+
return false;
207+
}
208+
bool forceLoad = argc > 3 && DbgEval(argv[3]);
209+
EXCLUSIVE_ACQUIRE(LockModules);
210+
auto info = ModInfoFromAddr(modbase);
211+
if(!info)
212+
{
213+
// TODO: this really isn't supposed to happen, but could if the module is suddenly unloaded
214+
dputs("module not found...");
215+
return false;
216+
}
217+
218+
// trigger a symbol load
219+
if(!info->loadSymbols(pdbFile, forceLoad))
220+
{
221+
dputs(QT_TRANSLATE_NOOP("DBG", "Symbol load failed... See symbol log for more information"));
222+
return false;
223+
}
224+
GuiSymbolRefreshCurrent();
225+
dputs(QT_TRANSLATE_NOOP("DBG", "Done! See symbol log for more information"));
226+
return true;
227+
}
228+
191229
bool cbInstrImageinfo(int argc, char* argv[])
192230
{
193231
duint address;

src/dbg/commands/cmd-analysis.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ bool cbInstrAnalyseadv(int argc, char* argv[]);
1212

1313
bool cbInstrVirtualmod(int argc, char* argv[]);
1414
bool cbDebugDownloadSymbol(int argc, char* argv[]);
15+
bool cbDebugLoadSymbol(int argc, char* argv[]);
1516
bool cbInstrImageinfo(int argc, char* argv[]);
1617
bool cbInstrGetRelocSize(int argc, char* argv[]);
1718
bool cbInstrExhandlers(int argc, char* argv[]);

src/dbg/module.cpp

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -832,8 +832,13 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
832832
GetModuleInfo(info, (ULONG_PTR)data());
833833
}
834834

835+
info.symbols = &EmptySymbolSource; // empty symbol source per default
835836
// TODO: setting to auto load symbols
836-
info.loadSymbols();
837+
for(const auto & pdbPath : info.pdbPaths)
838+
{
839+
if(info.loadSymbols(pdbPath, bForceLoadSymbols))
840+
break;
841+
}
837842

838843
// Add module to list
839844
EXCLUSIVE_ACQUIRE(LockModules);
@@ -1192,10 +1197,9 @@ bool ModRelocationsInRange(duint Address, duint Size, std::vector<MODRELOCATIONI
11921197
return !Relocations.empty();
11931198
}
11941199

1195-
bool MODINFO::loadSymbols()
1200+
bool MODINFO::loadSymbols(const String & pdbPath, bool forceLoad)
11961201
{
11971202
unloadSymbols();
1198-
symbols = &EmptySymbolSource; // empty symbol source per default
11991203

12001204
// Try DIA
12011205
if(symbols == &EmptySymbolSource && SymbolSourceDIA::isLibraryAvailable())
@@ -1208,32 +1212,29 @@ bool MODINFO::loadSymbols()
12081212
validationData.signature = pdbValidation.signature;
12091213
validationData.age = pdbValidation.age;
12101214
SymbolSourceDIA* symSource = new SymbolSourceDIA();
1211-
for(const auto & pdbPath : pdbPaths)
1215+
if(!FileExists(pdbPath.c_str()))
12121216
{
1213-
if(!FileExists(pdbPath.c_str()))
1214-
{
1215-
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Skipping non-existent PDB: %s\n", pdbPath.c_str()).c_str());
1216-
}
1217-
else if(symSource->loadPDB(pdbPath, modname, base, size, bForceLoadSymbols ? nullptr : &validationData))
1218-
{
1219-
symSource->resizeSymbolBitmap(size);
1220-
1221-
symbols = symSource;
1217+
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Skipping non-existent PDB: %s\n", pdbPath.c_str()).c_str());
1218+
}
1219+
else if(symSource->loadPDB(pdbPath, modname, base, size, forceLoad ? nullptr : &validationData))
1220+
{
1221+
symSource->resizeSymbolBitmap(size);
12221222

1223-
std::string msg;
1224-
if(symSource->isLoading())
1225-
msg = StringUtils::sprintf("[DIA] Loading PDB (async): %s\n", pdbPath.c_str());
1226-
else
1227-
msg = StringUtils::sprintf("[DIA] Loaded PDB: %s\n", pdbPath.c_str());
1228-
GuiSymbolLogAdd(msg.c_str());
1223+
symbols = symSource;
12291224

1230-
return true;
1231-
}
1225+
std::string msg;
1226+
if(symSource->isLoading())
1227+
msg = StringUtils::sprintf("[DIA] Loading PDB (async): %s\n", pdbPath.c_str());
12321228
else
1233-
{
1234-
// TODO: more detailled error codes?
1235-
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Failed to load PDB: %s\n", pdbPath.c_str()).c_str());
1236-
}
1229+
msg = StringUtils::sprintf("[DIA] Loaded PDB: %s\n", pdbPath.c_str());
1230+
GuiSymbolLogAdd(msg.c_str());
1231+
1232+
return true;
1233+
}
1234+
else
1235+
{
1236+
// TODO: more detailled error codes?
1237+
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Failed to load PDB: %s\n", pdbPath.c_str()).c_str());
12371238
}
12381239
delete symSource;
12391240
}

src/dbg/module.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ struct MODINFO
129129
GuiInvalidateSymbolSource(base);
130130
}
131131

132-
bool loadSymbols();
132+
bool loadSymbols(const String & pdbPath, bool forceLoad);
133133
void unloadSymbols();
134134
void unmapFile();
135135
const MODEXPORT* findExport(duint rva) const;

src/dbg/pdbdiafile.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
274274

275275
if(validationData != nullptr)
276276
{
277-
CComPtr<IDiaSymbol> globalSym;
277+
IDiaSymbol* globalSym = nullptr;
278278
hr = m_session->get_globalScope(&globalSym);
279279
if(testError(hr))
280280
{
@@ -286,9 +286,10 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
286286
hr = globalSym->get_age(&age);
287287
if(!testError(hr) && validationData->age != age)
288288
{
289+
globalSym->Release();
289290
close();
290291

291-
GuiSymbolLogAdd("PDB age is not matching.\n");
292+
GuiSymbolLogAdd(StringUtils::sprintf("Validation error: PDB age is not matching (expected: %u, actual: %u).\n", validationData->age, age).c_str());
292293
return false;
293294
}
294295

@@ -310,12 +311,28 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
310311
hr = globalSym->get_guid(&guid);
311312
if(!testError(hr) && memcmp(&guid, &validationData->guid, sizeof(GUID)) != 0)
312313
{
314+
globalSym->Release();
313315
close();
314316

315-
GuiSymbolLogAdd("PDB guid is not matching.\n");
317+
auto guidStr = [](const GUID & guid) -> String
318+
{
319+
// https://stackoverflow.com/a/22848342/1806760
320+
char guid_string[37]; // 32 hex chars + 4 hyphens + null terminator
321+
sprintf_s(guid_string,
322+
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
323+
guid.Data1, guid.Data2, guid.Data3,
324+
guid.Data4[0], guid.Data4[1], guid.Data4[2],
325+
guid.Data4[3], guid.Data4[4], guid.Data4[5],
326+
guid.Data4[6], guid.Data4[7]);
327+
return guid_string;
328+
};
329+
330+
GuiSymbolLogAdd(StringUtils::sprintf("Validation error: PDB guid is not matching (expected: %s, actual: %s).\n",
331+
guidStr(validationData->guid).c_str(), guidStr(guid).c_str()).c_str());
316332
return false;
317333
}
318334
}
335+
globalSym->Release();
319336
}
320337
else
321338
{

src/dbg/stringutils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ String StringUtils::ToHex(unsigned long long value)
513513

514514
#define HEXLOOKUP "0123456789ABCDEF"
515515

516-
String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
516+
String StringUtils::ToHex(const unsigned char* buffer, size_t size, bool reverse)
517517
{
518518
String result;
519519
result.resize(size * 2);
@@ -526,7 +526,7 @@ String StringUtils::ToHex(unsigned char* buffer, size_t size, bool reverse)
526526
return result;
527527
}
528528

529-
String StringUtils::ToCompressedHex(unsigned char* buffer, size_t size)
529+
String StringUtils::ToCompressedHex(const unsigned char* buffer, size_t size)
530530
{
531531
if(!size)
532532
return "";

src/dbg/stringutils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ class StringUtils
4242
static bool EndsWith(const String & str, const String & suffix);
4343
static bool FromHex(const String & text, std::vector<unsigned char> & data, bool reverse = false);
4444
static String ToHex(unsigned long long value);
45-
static String ToHex(unsigned char* buffer, size_t size, bool reverse = false);
46-
static String ToCompressedHex(unsigned char* buffer, size_t size);
45+
static String ToHex(const unsigned char* buffer, size_t size, bool reverse = false);
46+
static String ToCompressedHex(const unsigned char* buffer, size_t size);
4747
static bool FromCompressedHex(const String & text, std::vector<unsigned char> & data);
4848

4949
template<typename T>

src/dbg/symbolinfo.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -243,20 +243,8 @@ bool SymDownloadSymbol(duint Base, const char* SymbolStore)
243243
return false;
244244
}
245245

246-
// insert the downloaded symbol path in the beginning of the PDB load order
247-
auto destPathUtf8 = StringUtils::Utf16ToUtf8(destinationPath);
248-
for(auto it = info->pdbPaths.begin(); it != info->pdbPaths.end(); ++it)
249-
{
250-
if(*it == destPathUtf8)
251-
{
252-
info->pdbPaths.erase(it);
253-
break;
254-
}
255-
}
256-
info->pdbPaths.insert(info->pdbPaths.begin(), destPathUtf8);
257-
258246
// trigger a symbol load
259-
info->loadSymbols();
247+
info->loadSymbols(StringUtils::Utf16ToUtf8(destinationPath), bForceLoadSymbols);
260248
}
261249

262250
return true;

src/dbg/x64dbg.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ static void registercommands()
324324

325325
dbgcmdnew("virtualmod", cbInstrVirtualmod, true); //virtual module
326326
dbgcmdnew("symdownload,downloadsym", cbDebugDownloadSymbol, true); //download symbols
327+
dbgcmdnew("symload,loadsym", cbDebugLoadSymbol, true); //load symbols
327328
dbgcmdnew("imageinfo,modimageinfo", cbInstrImageinfo, true); //print module image information
328329
dbgcmdnew("GetRelocSize,grs", cbInstrGetRelocSize, true); //get relocation table size
329330
dbgcmdnew("exhandlers", cbInstrExhandlers, true); //enumerate exception handlers

0 commit comments

Comments
 (0)