1
0
Fork 0

Refactor PDBDiaFile query.

This commit is contained in:
ZehMatt 2017-12-19 10:34:17 +01:00 committed by Duncan Ogilvie
parent 82774e2445
commit 59d166ecf4
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
3 changed files with 100 additions and 56 deletions

View File

@ -335,7 +335,7 @@ uint32_t getSymbolId(IDiaSymbol* sym)
return id;
}
bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> callback, const bool collectUndecoratedNames)
bool PDBDiaFile::enumerateLexicalHierarchy(const Query_t & query)
{
ScopedDiaSymbol globalScope;
IDiaSymbol* symbol = nullptr;
@ -348,10 +348,13 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> ca
if(hr != S_OK)
return false;
std::unordered_set<uint32_t> visited;
InternalQueryContext_t context;
context.callback = query.callback;
context.collectSize = query.collectSize;
context.collectUndecoratedNames = query.collectUndecoratedNames;
uint32_t scopeId = getSymbolId(globalScope);
visited.insert(scopeId);
context.visited.insert(scopeId);
// Enumerate compilands.
{
@ -363,7 +366,7 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> ca
while(res == true && (hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
if(!enumerateCompilandScope(sym, callback, visited, collectUndecoratedNames))
if(!enumerateCompilandScope(sym, context))
{
return false;
}
@ -380,10 +383,10 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> ca
{
while(res == true && (hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
if(convertSymbolInfo(symbol, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(symbol, symbolInfo, context))
{
ScopedDiaSymbol sym(symbol);
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -402,9 +405,9 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> ca
while(res == true && (hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -423,9 +426,9 @@ bool PDBDiaFile::enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> ca
while(res == true && (hr = enumSymbols->Next(1, &symbol, &celt)) == S_OK && celt == 1)
{
ScopedDiaSymbol sym(symbol);
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -474,7 +477,11 @@ bool PDBDiaFile::findSymbolRVA(uint64_t address, DiaSymbol_t & sym, DiaSymbolTyp
sym.disp = disp;
if(!convertSymbolInfo(scopedSym, sym, true))
InternalQueryContext_t context;
context.collectSize = true;
context.collectUndecoratedNames = true;
if(!convertSymbolInfo(scopedSym, sym, context))
res = false;
else
res = true;
@ -483,7 +490,7 @@ bool PDBDiaFile::findSymbolRVA(uint64_t address, DiaSymbol_t & sym, DiaSymbolTyp
return res;
}
bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bool(DiaSymbol_t &)> & callback, std::unordered_set<uint32_t> & visited, const bool collectUndecoratedNames)
bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryContext_t & context)
{
IDiaSymbol* symbol = nullptr;
bool res = true;
@ -509,7 +516,7 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bo
if(hr == S_OK)
{
if(!processFunctionSymbol(sym, callback, visited, collectUndecoratedNames))
if(!processFunctionSymbol(sym, context))
{
return false;
}
@ -533,9 +540,9 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bo
if(hr == S_OK)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -559,9 +566,9 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bo
if(hr == S_OK)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -585,9 +592,9 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bo
if(hr == S_OK)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -600,7 +607,7 @@ bool PDBDiaFile::enumerateCompilandScope(IDiaSymbol* compiland, std::function<bo
return true;
}
bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, std::function<bool(DiaSymbol_t &)> & callback, std::unordered_set<uint32_t> & visited, const bool collectUndecoratedNames /*= false*/)
bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, InternalQueryContext_t & context)
{
IDiaSymbol* symbol = nullptr;
ULONG celt = 0;
@ -609,18 +616,18 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, std::function<bo
bool res = true;
uint32_t symId = getSymbolId(functionSym);
if(visited.find(symId) != visited.end())
if(context.visited.find(symId) != context.visited.end())
{
printf("Dupe\n");
return true;
}
visited.insert(symId);
context.visited.insert(symId);
DiaSymbol_t symbolInfo;
if(convertSymbolInfo(functionSym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(functionSym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
return false;
}
@ -640,9 +647,9 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, std::function<bo
if(hr == S_OK && locType == LocIsStatic)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -665,9 +672,9 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, std::function<bo
if(hr == S_OK)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -690,9 +697,9 @@ bool PDBDiaFile::processFunctionSymbol(IDiaSymbol* functionSym, std::function<bo
if(hr == S_OK)
{
if(convertSymbolInfo(sym, symbolInfo, collectUndecoratedNames))
if(convertSymbolInfo(sym, symbolInfo, context))
{
if(!callback(symbolInfo))
if(!context.callback(symbolInfo))
{
return false;
}
@ -790,7 +797,9 @@ bool PDBDiaFile::resolveSymbolSize(IDiaSymbol* symbol, uint64_t & size, uint32_t
}
}
else
else if(symTag == SymTagPublicSymbol ||
symTag == SymTagFunction ||
symTag == SymTagBlock)
{
hr = symbol->get_length(&tempSize);
if(hr == S_OK)
@ -848,7 +857,7 @@ extern "C" pchar_t __cdecl __unDNameEx(_Out_opt_z_cap_(maxStringLength) pchar_t
unsigned long disableFlags
);
bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, const bool collectUndecoratedNames)
bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, InternalQueryContext_t & context)
{
HRESULT hr;
DWORD symTagType;
@ -871,7 +880,7 @@ bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo,
symbolInfo.name = getSymbolNameString(symbol);
if(collectUndecoratedNames && !symbolInfo.name.empty() && symbolInfo.name.at(0) == '?')
if(context.collectUndecoratedNames && !symbolInfo.name.empty() && symbolInfo.name.at(0) == '?')
{
//TODO: undocumented hack to have some kind of performance while undecorating names
auto mymalloc = [](size_t size) { return emalloc(size, "convertSymbolInfo::undecoratedName"); };
@ -929,11 +938,13 @@ bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo,
return false;
}
symbolInfo.size = 0;
if(!resolveSymbolSize(symbol, symbolInfo.size, symTagType) || symbolInfo.size == 0)
symbolInfo.size = -1;
if(context.collectSize)
{
symbolInfo.size = -1;
if(!resolveSymbolSize(symbol, symbolInfo.size, symTagType) || symbolInfo.size == 0)
{
symbolInfo.size = -1;
}
}
switch(symTagType)

View File

@ -15,6 +15,20 @@ struct IDiaSymbol;
class PDBDiaFile
{
public:
struct Query_t
{
std::function<bool(DiaSymbol_t &)> callback;
bool collectUndecoratedNames;
bool collectSize;
};
private:
struct InternalQueryContext_t : public Query_t
{
std::unordered_set<uint32_t> visited;
};
private:
static volatile long m_sbInitialized;
@ -40,7 +54,7 @@ public:
bool getFunctionLineNumbers(DWORD rva, ULONGLONG size, uint64_t imageBase, std::map<uint64_t, DiaLineInfo_t> & lines);
bool enumerateLexicalHierarchy(std::function<bool(DiaSymbol_t &)> callback, const bool collectUndecoratedNames);
bool enumerateLexicalHierarchy(const Query_t & query);
bool findSymbolRVA(uint64_t address, DiaSymbol_t & sym, DiaSymbolType symType = DiaSymbolType::ANY);
@ -50,10 +64,10 @@ private:
std::string getSymbolNameString(IDiaSymbol* sym);
std::string getSymbolUndecoratedNameString(IDiaSymbol* sym);
bool enumerateCompilandScope(IDiaSymbol* compiland, std::function<bool(DiaSymbol_t &)> & callback, std::unordered_set<uint32_t> & visited, const bool collectUndecoratedNames);
bool processFunctionSymbol(IDiaSymbol* profilerFunction, std::function<bool(DiaSymbol_t &)> & callback, std::unordered_set<uint32_t> & visited, const bool collectUndecoratedNames);
bool enumerateCompilandScope(IDiaSymbol* compiland, InternalQueryContext_t & context);
bool processFunctionSymbol(IDiaSymbol* profilerFunction, InternalQueryContext_t & context);
bool resolveSymbolSize(IDiaSymbol* symbol, uint64_t & size, uint32_t symTag);
bool convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, const bool collectUndecoratedNames);
bool convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, InternalQueryContext_t & context);
};

View File

@ -22,6 +22,18 @@ SymbolSourcePDB::~SymbolSourcePDB()
}
}
static void SetThreadDescription(std::thread & thread, WString name)
{
typedef HRESULT(WINAPI * fnSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
fnSetThreadDescription fp = (fnSetThreadDescription)GetProcAddress(GetModuleHandleA("kernel32.dll"), "SetThreadDescription");
if(!fp)
return; // Only available on windows 10.
HANDLE handle = static_cast<HANDLE>(thread.native_handle());
fp(handle, name.c_str());
}
bool SymbolSourcePDB::loadPDB(const std::string & path, duint imageBase, duint imageSize)
{
if(!PDBDiaFile::initLibrary())
@ -38,7 +50,9 @@ bool SymbolSourcePDB::loadPDB(const std::string & path, duint imageBase, duint i
_requiresShutdown = false;
_loadCounter.store(2);
_symbolsThread = std::thread(&SymbolSourcePDB::loadSymbolsAsync, this, path);
SetThreadDescription(_symbolsThread, L"SymbolsThread");
_sourceLinesThread = std::thread(&SymbolSourcePDB::loadSourceLinesAsync, this, path);
SetThreadDescription(_symbolsThread, L"SourceLinesThread");
}
#endif
return res;
@ -89,7 +103,10 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
DWORD lastUpdate = 0;
DWORD loadStart = GetTickCount64();
bool res = _pdb.enumerateLexicalHierarchy([&](DiaSymbol_t & sym)->bool
PDBDiaFile::Query_t query;
query.collectSize = true;
query.collectUndecoratedNames = true;
query.callback = [&](DiaSymbol_t & sym)->bool
{
if(_requiresShutdown)
return false;
@ -107,24 +124,24 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
symInfo.addr = sym.virtualAddress;
symInfo.publicSymbol = sym.publicSymbol;
_lockSymbols.lock();
// Check if we already have it inside, private symbols have priority over public symbols.
auto it = _sym.find(symInfo.addr);
if(it != _sym.end())
{
if(it->second.publicSymbol == true && symInfo.publicSymbol == false)
ScopedSpinLock lock(_lockSymbols);
auto it = _sym.find(symInfo.addr);
if(it != _sym.end())
{
// Replace.
it->second = symInfo;
if(it->second.publicSymbol == true && symInfo.publicSymbol == false)
{
// Replace.
it->second = symInfo;
}
}
else
{
_sym.insert(std::make_pair(symInfo.addr, symInfo));
}
}
else
{
_sym.insert(std::make_pair(symInfo.addr, symInfo));
}
_lockSymbols.unlock();
DWORD curTick = GetTickCount();
if(curTick - lastUpdate > 500)
@ -135,7 +152,9 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
}
return true;
}, true);
};
bool res = _pdb.enumerateLexicalHierarchy(query);
if(!res)
{