1
0
Fork 0

DBG: attempt to load symbols from multiple locations

This commit is contained in:
Duncan Ogilvie 2018-02-11 02:06:01 +01:00
parent 637815b63d
commit ff11a39533
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
8 changed files with 163 additions and 80 deletions

View File

@ -7,7 +7,9 @@
#include "memory.h"
#include "label.h"
#include <algorithm>
#include <shlwapi.h>
#include "console.h"
#include "debugger.h"
std::map<Range, MODINFO, RangeCompare> modinfo;
std::unordered_map<duint, std::string> hashNameMap;
@ -181,8 +183,8 @@ void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
}
}(debugDir.Type);
dprintf("IMAGE_DEBUG_DIRECTORY:\nCharacteristics: %08X\nTimeDateStamp: %08X\nMajorVersion: %04X\nMinorVersion: %04X\nType: %s\nSizeOfData: %08X\nAddressOfRawData: %08X\nPointerToRawData: %08X\n",
debugDir.Characteristics, debugDir.TimeDateStamp, debugDir.MajorVersion, debugDir.MinorVersion, typeName, debugDir.SizeOfData, debugDir.AddressOfRawData, debugDir.PointerToRawData);
/*dprintf("IMAGE_DEBUG_DIRECTORY:\nCharacteristics: %08X\nTimeDateStamp: %08X\nMajorVersion: %04X\nMinorVersion: %04X\nType: %s\nSizeOfData: %08X\nAddressOfRawData: %08X\nPointerToRawData: %08X\n",
debugDir.Characteristics, debugDir.TimeDateStamp, debugDir.MajorVersion, debugDir.MinorVersion, typeName, debugDir.SizeOfData, debugDir.AddressOfRawData, debugDir.PointerToRawData);*/
if(debugDir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) //TODO: support other types (DBG)?
{
@ -227,6 +229,8 @@ void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
auto cv = (CV_INFO_PDB20*)(FileMapVA + codeViewOffset);
Info.pdbSignature = StringUtils::sprintf("%X%X", cv->Signature, cv->Age);
Info.pdbFile = String((const char*)cv->PdbFileName);
Info.pdbValidation.signature = cv->Signature;
Info.pdbValidation.age = cv->Age;
}
else if(signature == 'SDSR')
{
@ -236,6 +240,8 @@ void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
StringUtils::ToHex(cv->Signature.Data4, 8).c_str(),
cv->Age);
Info.pdbFile = String((const char*)cv->PdbFileName);
memcpy(&Info.pdbValidation.guid, &cv->Signature, sizeof(GUID));
Info.pdbValidation.age = cv->Age;
}
else
{
@ -243,7 +249,44 @@ void ReadDebugDirectory(MODINFO & Info, ULONG_PTR FileMapVA)
return;
}
dprintf("%s%s pdbSignature: %s, pdbFile: \"%s\"\n", Info.name, Info.extension, Info.pdbSignature.c_str(), Info.pdbFile.c_str());
//dprintf("%s%s pdbSignature: %s, pdbFile: \"%s\"\n", Info.name, Info.extension, Info.pdbSignature.c_str(), Info.pdbFile.c_str());
if(!Info.pdbFile.empty())
{
// Get the directory/filename from the debug directory PDB path
String dir, file;
auto lastIdx = Info.pdbFile.rfind('\\');
if(lastIdx == String::npos)
file = Info.pdbFile;
else
{
dir = Info.pdbFile.substr(0, lastIdx - 1);
file = Info.pdbFile.substr(lastIdx + 1);
}
// Program directory
char pdbPath[MAX_PATH];
strcpy_s(pdbPath, Info.path);
auto lastBack = strrchr(pdbPath, '\\');
if(lastBack)
{
lastBack[1] = '\0';
strncat_s(pdbPath, file.c_str(), _TRUNCATE);
Info.pdbPaths.push_back(pdbPath);
}
// Debug directory full path
const bool bAllowUncPathsInDebugDirectory = false; // TODO: create setting for this
if(!dir.empty() && (bAllowUncPathsInDebugDirectory || !PathIsUNCW(StringUtils::Utf8ToUtf16(Info.pdbFile).c_str())))
Info.pdbPaths.push_back(Info.pdbFile);
// Symbol cache
auto cachePath = String(szSymbolCachePath);
if(cachePath.back() != '\\')
cachePath += '\\';
cachePath += StringUtils::sprintf("%s\\%s\\%s", file.c_str(), Info.pdbSignature.c_str(), file.c_str());
Info.pdbPaths.push_back(cachePath);
}
}
void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA)
@ -346,7 +389,6 @@ bool ModLoad(duint Base, duint Size, const char* FullPath)
info.loadedSize = 0;
info.fileMap = nullptr;
info.fileMapVA = 0;
//info.invalidSymbols.resize(Size);
// Determine whether the module is located in system
wchar_t sysdir[MAX_PATH];
@ -396,43 +438,8 @@ 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.
// Try DIA
if(info.symbols == &EmptySymbolSource &&
SymbolSourceDIA::isLibraryAvailable())
{
SymbolSourceDIA* symSource = new SymbolSourceDIA();
if(symSource->loadPDB(info.path, Base, info.size))
{
symSource->resizeSymbolBitmap(info.size);
info.symbols = symSource;
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);
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());
}
// TODO: setting to auto load symbols
info.loadSymbols();
// Add module to list
EXCLUSIVE_ACQUIRE(LockModules);
@ -466,20 +473,12 @@ bool ModUnload(duint Base)
return false;
// Unload the mapped file from memory
const auto & info = found->second;
auto & info = found->second;
if(info.fileMapVA)
StaticFileUnloadW(StringUtils::Utf8ToUtf16(info.path).c_str(), false, info.fileHandle, info.loadedSize, info.fileMap, info.fileMapVA);
if(info.symbols != nullptr &&
info.symbols != &EmptySymbolSource)
{
if(info.symbols->isLoading())
{
info.symbols->cancelLoading();
}
delete info.symbols;
}
// Unload symbols from the module
info.unloadSymbols();
// Remove it from the list
modinfo.erase(found);
@ -878,3 +877,74 @@ bool ModRelocationsInRange(duint Address, duint Size, std::vector<MODRELOCATIONI
return !Relocations.empty();
}
bool MODINFO::loadSymbols()
{
unloadSymbols();
symbols = &EmptySymbolSource; // empty symbol source per default
// Try DIA
if(symbols == &EmptySymbolSource && SymbolSourceDIA::isLibraryAvailable())
{
// TODO: do something with searchPaths
DiaValidationData_t validationData;
memcpy(&validationData.guid, &pdbValidation.guid, sizeof(GUID));
validationData.signature = pdbValidation.signature;
validationData.age = pdbValidation.age;
SymbolSourceDIA* symSource = new SymbolSourceDIA();
for(const auto & pdbPath : pdbPaths)
{
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, base, size, &validationData))
{
symSource->resizeSymbolBitmap(size);
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;
}
else
{
// TODO: more detailled error codes?
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] Failed to load PDB: %s\n", pdbPath.c_str()).c_str());
}
}
delete symSource;
}
if(symbols == &EmptySymbolSource && true) // TODO: try loading from other sources?
{
}
if(!symbols->isOpen())
{
std::string msg = StringUtils::sprintf("No symbols loaded for: %s%s\n", name, extension);
GuiSymbolLogAdd(msg.c_str());
return false;
}
return true;
}
void MODINFO::unloadSymbols()
{
if(symbols != nullptr && symbols != &EmptySymbolSource)
{
if(symbols->isLoading())
{
symbols->cancelLoading();
}
delete symbols;
symbols = &EmptySymbolSource;
}
}

View File

@ -29,6 +29,18 @@ struct MODRELOCATIONINFO
bool Contains(duint Address) const;
};
struct PdbValidationData
{
GUID guid;
DWORD signature = 0;
DWORD age = 0;
PdbValidationData()
{
memset(&guid, 0, sizeof(guid));
}
};
struct MODINFO
{
duint base = 0; // Module base
@ -44,10 +56,12 @@ struct MODINFO
std::vector<MODIMPORTINFO> imports;
std::vector<MODRELOCATIONINFO> relocations;
std::vector<duint> tlsCallbacks;
//std::vector<bool> invalidSymbols; //TODO: remove?
SymbolSourceBase* symbols;
SymbolSourceBase* symbols = nullptr;
String pdbSignature;
String pdbFile;
PdbValidationData pdbValidation;
std::vector<String> pdbPaths; // Possible PDB paths (tried in order)
HANDLE fileHandle = nullptr;
DWORD loadedSize = 0;
@ -62,6 +76,9 @@ struct MODINFO
memset(extension, 0, sizeof(extension));
memset(path, 0, sizeof(path));
}
bool loadSymbols();
void unloadSymbols();
};
bool ModLoad(duint Base, duint Size, const char* FullPath);

View File

@ -20,7 +20,7 @@ class DiaLoadCallback : public IDiaLoadCallback2
/* [in] */ DWORD cbData,
/* [size_is][in] */ BYTE* pbData) override
{
dprintf("[DIA] NotifyDebugDir: %s\n", StringUtils::ToHex(pbData, cbData).c_str());
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] NotifyDebugDir: %s\n", StringUtils::ToHex(pbData, cbData).c_str()).c_str());
return S_OK;
}
@ -28,7 +28,7 @@ class DiaLoadCallback : public IDiaLoadCallback2
/* [in] */ LPCOLESTR dbgPath,
/* [in] */ HRESULT resultCode) override
{
dprintf("[DIA] NotifyOpenDBG: %s, %08X\n", StringUtils::Utf16ToUtf8(dbgPath).c_str(), resultCode);
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] NotifyOpenDBG: %s, %08X\n", StringUtils::Utf16ToUtf8(dbgPath).c_str(), resultCode).c_str());
return S_OK;
}
@ -36,7 +36,7 @@ class DiaLoadCallback : public IDiaLoadCallback2
/* [in] */ LPCOLESTR pdbPath,
/* [in] */ HRESULT resultCode) override
{
dprintf("[DIA] NotifyOpenPDB: %s, %08X\n", StringUtils::Utf16ToUtf8(pdbPath).c_str(), resultCode);
GuiSymbolLogAdd(StringUtils::sprintf("[DIA] NotifyOpenPDB: %s, %08X\n", StringUtils::Utf16ToUtf8(pdbPath).c_str(), resultCode).c_str());
return S_OK;
}
@ -157,11 +157,7 @@ bool PDBDiaFile::shutdownLibrary()
bool PDBDiaFile::open(const char* file, uint64_t loadAddress, DiaValidationData_t* validationData)
{
wchar_t buf[1024];
mbstowcs_s(nullptr, buf, file, 1024);
return open(buf, loadAddress, validationData);
return open(StringUtils::Utf8ToUtf16(file).c_str(), loadAddress, validationData);
}
bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationData_t* validationData)
@ -189,7 +185,7 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
}
else
{
printf("Unable to initialize PDBDia Library.\n");
GuiSymbolLogAdd("Unable to initialize PDBDia Library.\n");
return false;
}
}
@ -200,15 +196,15 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
{
if(validationData != nullptr)
{
hr = m_dataSource->loadAndValidateDataFromPdb(file, (GUID*)validationData->guid, validationData->signature, validationData->age);
hr = m_dataSource->loadAndValidateDataFromPdb(file, &validationData->guid, validationData->signature, validationData->age);
if((hr == E_PDB_INVALID_SIG) || (hr == E_PDB_INVALID_AGE))
{
printf("PDB is not matching.\n");
GuiSymbolLogAdd("PDB is not matching.\n");
return false;
}
else if(hr == E_PDB_FORMAT)
{
printf("PDB uses an obsolete format.\n");
GuiSymbolLogAdd("PDB uses an obsolete format.\n");
return false;
}
}
@ -227,7 +223,7 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
{
if(hr != E_PDB_NOT_FOUND)
{
printf("Unable to open PDB file - %08X\n", hr);
GuiSymbolLogAdd(StringUtils::sprintf("Unable to open PDB file - %08X\n", hr).c_str());
}
return false;
}
@ -235,7 +231,7 @@ bool PDBDiaFile::open(const wchar_t* file, uint64_t loadAddress, DiaValidationDa
hr = m_dataSource->openSession(&m_session);
if(testError(hr) || m_session == nullptr)
{
printf("Unable to create new PDBDia Session - %08X\n", hr);
GuiSymbolLogAdd(StringUtils::sprintf("Unable to create new PDBDia Session - %08X\n", hr).c_str());
return false;
}
@ -689,7 +685,7 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, InternalQueryCon
uint32_t symId = getSymbolId(functionSym);
if(context.visited.find(symId) != context.visited.end())
{
printf("Dupe\n");
GuiSymbolLogAdd("Dupe\n");
return true;
}
@ -976,9 +972,9 @@ bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo,
{
if(test != symbolInfo.undecoratedName)
{
dprintf("undecoration mismatch, msvcrt: \"%s\", DIA: \"%s\"\n",
GuiSymbolLogAdd(StringUtils::sprintf("undecoration mismatch, msvcrt: \"%s\", DIA: \"%s\"\n",
symbolInfo.undecoratedName.c_str(),
test.c_str());
test.c_str()).c_str());
}
}*/
}

View File

@ -51,7 +51,7 @@ enum class DiaCallingConvention
struct DiaValidationData_t
{
uint8_t guid[16];
GUID guid;
uint32_t signature;
uint32_t age;
};

View File

@ -32,7 +32,7 @@ using CbEnumSymbol = std::function<bool(const SymbolInfo &)>;
class SymbolSourceBase
{
private:
std::vector<uint8_t> _symbolBitmap;
std::vector<uint8_t> _symbolBitmap; // TODO: what is the maximum size for this?
public:
virtual ~SymbolSourceBase() = default;

View File

@ -35,14 +35,14 @@ static void SetThreadDescription(std::thread & thread, WString name)
fp(handle, name.c_str());
}
bool SymbolSourceDIA::loadPDB(const std::string & path, duint imageBase, duint imageSize)
bool SymbolSourceDIA::loadPDB(const std::string & path, duint imageBase, duint imageSize, DiaValidationData_t* validationData)
{
if(!PDBDiaFile::initLibrary())
{
return false;
}
bool res = _pdb.open(path.c_str());
bool res = _pdb.open(path.c_str(), 0, validationData);
#if 1 // Async loading.
if(res)
{
@ -195,7 +195,7 @@ bool SymbolSourceDIA::loadSymbolsAsync(String path)
DWORD64 ms = GetTickCount64() - loadStart;
double secs = (double)ms / 1000.0;
dprintf("Loaded %d symbols in %.03f\n", _symAddrs.size(), secs);
GuiSymbolLogAdd(StringUtils::sprintf("Loaded %d symbols in %.03f\n", _symAddrs.size(), secs).c_str());
//TODO: make beautiful
ListInfo blub;
@ -225,7 +225,7 @@ bool SymbolSourceDIA::loadSourceLinesAsync(String path)
return false;
}
dprintf("Loading Source lines...\n");
GuiSymbolLogAdd(StringUtils::sprintf("Loading Source lines...\n").c_str());
DWORD64 lineLoadStart = GetTickCount64();
@ -291,7 +291,7 @@ bool SymbolSourceDIA::loadSourceLinesAsync(String path)
DWORD64 ms = GetTickCount64() - lineLoadStart;
double secs = (double)ms / 1000.0;
dprintf("Loaded %d line infos in %.03f\n", _lines.size(), secs);
GuiSymbolLogAdd(StringUtils::sprintf("Loaded %d line infos in %.03f\n", _lines.size(), secs).c_str());
GuiUpdateAllViews();

View File

@ -146,7 +146,7 @@ public:
virtual bool findSymbolsByPrefix(const std::string & prefix, const std::function<bool(const SymbolInfo &)> & cbSymbol, bool caseSensitive) override;
public:
bool loadPDB(const std::string & path, duint imageBase, duint imageSize);
bool loadPDB(const std::string & path, duint imageBase, duint imageSize, DiaValidationData_t* validationData);
private:
void loadPDBAsync();

View File

@ -147,7 +147,7 @@ void SymbolView::loadWindowSettings()
void SymbolView::setModuleSymbols(duint base, const std::vector<void*> & symbols)
{
//TODO: reload actual symbol list, race conditions
GuiAddLogMessage(QString("base: %1, count: %2\n").arg(ToPtrString(base)).arg(symbols.size()).toUtf8().constData());
GuiSymbolLogAdd(QString("[SymbolView] base: %1, count: %2\n").arg(ToPtrString(base)).arg(symbols.size()).toUtf8().constData());
mModuleSymbolMap[base] = symbols;
}