1
0
Fork 0

DBG: implement a much nicer data structure for SymbolSourcePDB

This commit is contained in:
Duncan Ogilvie 2017-12-22 04:46:18 +01:00
parent c7d0f50207
commit 2ce2470ea1
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
2 changed files with 89 additions and 80 deletions

View File

@ -90,37 +90,6 @@ void SymbolSourcePDB::loadPDBAsync()
{
}
inline int mystricmp(const char* s1, const char* s2)
{
unsigned char c1, c2;
while((c1 = tolower(*s1++)) == (c2 = tolower(*s2++)))
if(c1 == '\0')
return 0;
return c1 - c2;
}
inline int hackicmp(const char* s1, const char* s2)
{
unsigned char c1, c2;
while((c1 = *s1++) == (c2 = *s2++))
if(c1 == '\0')
return 0;
return mystricmp(s1 - 1, s2 - 1);
}
struct HackCmp
{
bool operator()(const SymbolInfo & a, const SymbolInfo & b)
{
return cmp(a, b, false) < 0;
}
int cmp(const SymbolInfo & a, const SymbolInfo & b, bool caseSensitive)
{
return (caseSensitive ? strcmp : hackicmp)(a.decoratedName.c_str(), b.decoratedName.c_str());
}
};
bool SymbolSourcePDB::loadSymbolsAsync(String path)
{
ScopedDecrement ref(_loadCounter);
@ -155,24 +124,25 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
symInfo.disp = sym.disp;
symInfo.addr = sym.virtualAddress;
symInfo.publicSymbol = sym.publicSymbol;
_symNames.push_back(symInfo);
_symData.push_back(symInfo);
// Check if we already have it inside, private symbols have priority over public symbols.
// TODO: only use this map during initialization phase
{
ScopedSpinLock lock(_lockSymbols);
auto it = _symAddrs.find(symInfo.addr);
if(it != _symAddrs.end())
{
if(_symNames[it->second].publicSymbol == true && symInfo.publicSymbol == false)
if(_symData[it->second].publicSymbol == true && symInfo.publicSymbol == false)
{
// Replace.
it->second = _symNames.size() - 1;
it->second = _symData.size() - 1;
}
}
else
{
_symAddrs.insert({ symInfo.addr, _symNames.size() - 1 });
_symAddrs.insert({ symInfo.addr, _symData.size() - 1 });
}
}
@ -199,29 +169,27 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
{
ScopedSpinLock lock(_lockSymbols);
//handle symbol sorting
std::sort(_symNames.begin(), _symNames.end(), HackCmp());
_symAddrs.clear();
for(size_t i = 0; i < _symNames.size(); i++)
//TODO: actually do something with this map
_symAddrMap.reserve(_symAddrs.size());
for(auto & it : _symAddrs)
{
auto & symInfo = _symNames.at(i);
// Check if we already have it inside, private symbols have priority over public symbols.
auto it = _symAddrs.find(symInfo.addr);
if(it != _symAddrs.end())
{
if(_symNames[it->second].publicSymbol == true && symInfo.publicSymbol == false)
{
// Replace.
it->second = i;
}
}
else
{
_symAddrs.insert({ symInfo.addr, i });
}
AddrIndex addrIndex;
addrIndex.addr = it.first;
addrIndex.index = it.second;
_symAddrMap.push_back(addrIndex);
}
std::sort(_symAddrMap.begin(), _symAddrMap.end());
//handle symbol name sorting
_symNameMap.resize(_symData.size());
for(size_t i = 0; i < _symData.size(); i++)
{
NameIndex nameIndex;
nameIndex.index = i;
nameIndex.name = _symData.at(i).decoratedName.c_str(); //NOTE: DO NOT MODIFY decoratedName is any way!
_symNameMap[i] = nameIndex;
}
std::sort(_symNameMap.begin(), _symNameMap.end());
}
DWORD64 ms = GetTickCount64() - loadStart;
@ -237,7 +205,7 @@ bool SymbolSourcePDB::loadSymbolsAsync(String path)
fuck.resize(_symAddrs.size());
size_t i = 0;
for(auto it = _symAddrs.begin(); it != _symAddrs.end(); ++it)
fuck[i++] = &_symNames[it->second];
fuck[i++] = &_symData[it->second];
blub.data = fuck.data();
GuiSetModuleSymbols(_imageBase, &blub);
@ -340,7 +308,7 @@ bool SymbolSourcePDB::findSymbolExact(duint rva, SymbolInfo & symInfo)
auto it = _symAddrs.find(rva);
if(it != _symAddrs.end())
{
symInfo = _symNames[(*it).second];
symInfo = _symData[it->second];
return true;
}
@ -375,7 +343,7 @@ bool SymbolSourcePDB::findSymbolExactOrLower(duint rva, SymbolInfo & symInfo)
auto it = findExactOrLower(_symAddrs, rva);
if(it != _symAddrs.end())
{
symInfo = _symNames[(*it).second];
symInfo = _symData[it->second];
symInfo.disp = (int32_t)(rva - symInfo.addr);
return true;
}
@ -389,7 +357,7 @@ void SymbolSourcePDB::enumSymbols(const CbEnumSymbol & cbEnum)
for(auto & it : _symAddrs)
{
const SymbolInfo & sym = _symNames[it.second];
const SymbolInfo & sym = _symData[it.second];
if(!cbEnum(sym))
{
break;
@ -432,25 +400,23 @@ ForwardIt binary_find(ForwardIt first, ForwardIt last, const T & value, Compare
bool SymbolSourcePDB::findSymbolByName(const std::string & name, SymbolInfo & symInfo, bool caseSensitive)
{
HackCmp hackCmp;
ScopedSpinLock lock(_lockSymbols);
SymbolInfo find;
find.decoratedName = name;
auto found = binary_find(_symNames.begin(), _symNames.end(), find, hackCmp);
if(found != _symNames.end())
NameIndex find;
find.name = name.c_str();
auto found = binary_find(_symNameMap.begin(), _symNameMap.end(), find);
if(found != _symNameMap.end())
{
do
{
if(hackCmp.cmp(*found, find, caseSensitive) == 0)
if(find.cmp(*found, find, caseSensitive) == 0)
{
symInfo = *found;
symInfo = _symData.at(found->index);
return true;
}
++found;
}
while(found != _symNames.end() && hackCmp.cmp(find, *found, false) == 0);
while(found != _symNameMap.end() && find.cmp(find, *found, false) == 0);
}
return false;
}
@ -461,14 +427,14 @@ bool SymbolSourcePDB::findSymbolsByPrefix(const std::string & prefix, std::vecto
{
PrefixCmp(size_t n) : n(n) { }
bool operator()(const SymbolInfo & a, const SymbolInfo & b)
bool operator()(const NameIndex & a, const NameIndex & b)
{
return cmp(a, b, false) < 0;
}
int cmp(const SymbolInfo & a, const SymbolInfo & b, bool caseSensitive)
int cmp(const NameIndex & a, const NameIndex & b, bool caseSensitive)
{
return (caseSensitive ? strncmp : _strnicmp)(a.decoratedName.c_str(), b.decoratedName.c_str(), n);
return (caseSensitive ? strncmp : _strnicmp)(a.name, b.name, n);
}
private:
@ -477,18 +443,18 @@ bool SymbolSourcePDB::findSymbolsByPrefix(const std::string & prefix, std::vecto
ScopedSpinLock lock(_lockSymbols);
SymbolInfo find;
find.decoratedName = prefix;
auto found = binary_find(_symNames.begin(), _symNames.end(), find, prefixCmp);
if(found == _symNames.end())
NameIndex find;
find.name = prefix.c_str();
auto found = binary_find(_symNameMap.begin(), _symNameMap.end(), find, prefixCmp);
if(found == _symNameMap.end())
return false;
bool result = false;
for(; found != _symNames.end() && prefixCmp.cmp(find, *found, false); ++found)
for(; found != _symNameMap.end() && prefixCmp.cmp(find, *found, false); ++found)
{
if(!caseSensitive || prefixCmp.cmp(find, *found, true))
{
symbols.push_back(*found);
symbols.push_back(_symData.at(found->index));
result = true;
}
}

View File

@ -56,8 +56,37 @@ class SymbolSourcePDB : public SymbolSourceBase
private:
PDBDiaFile _pdb;
//All the symbol data, sorted by name
std::vector<SymbolInfo> _symNames;
std::vector<SymbolInfo> _symData;
struct AddrIndex
{
duint addr;
size_t index;
bool operator<(const AddrIndex & b) const
{
return addr < b.addr;
}
};
std::vector<AddrIndex> _symAddrMap; //rva -> data index (sorted on rva)
struct NameIndex
{
const char* name;
size_t index;
bool operator<(const NameIndex & b) const
{
return cmp(*this, b, false) < 0;
}
static int cmp(const NameIndex & a, const NameIndex & b, bool caseSensitive)
{
return (caseSensitive ? strcmp : hackicmp)(a.name, b.name);
}
};
std::vector<NameIndex> _symNameMap; //name -> data index (sorted on name)
//Symbol addresses to index in _symNames (TODO: refactor to std::vector)
std::map<duint, size_t> _symAddrs;
@ -73,6 +102,20 @@ private:
SpinLock _lockSymbols;
SpinLock _lockLines;
private:
static int hackicmp(const char* s1, const char* s2)
{
unsigned char c1, c2;
while((c1 = *s1++) == (c2 = *s2++))
if(c1 == '\0')
return 0;
s1--, s2--;
while((c1 = tolower(*s1++)) == (c2 = tolower(*s2++)))
if(c1 == '\0')
return 0;
return c1 - c2;
}
public:
static bool isLibraryAvailable()
{