1
0
Fork 0

DBG: use undocumented __unDNameEx function to significantly speed up symbol loading

Before:
Loaded 313534 line infos in 47.406
Loaded 140366 symbols in 171.640

After:
Loaded 313534 line infos in 4.187
Loaded 140366 symbols in 9.391
This commit is contained in:
Duncan Ogilvie 2017-12-19 04:10:02 +01:00
parent a9782ac6c6
commit 82774e2445
No known key found for this signature in database
GPG Key ID: FC89E0AAA0C1AAD8
3 changed files with 87 additions and 5 deletions

View File

@ -1,3 +1,4 @@
#include "_global.h"
#include <comutil.h> #include <comutil.h>
#include <windows.h> #include <windows.h>
#include <thread> #include <thread>
@ -10,6 +11,7 @@
#include "pdbdiafile.h" #include "pdbdiafile.h"
#include "stringutils.h" #include "stringutils.h"
#include "console.h"
volatile LONG PDBDiaFile::m_sbInitialized = 0; volatile LONG PDBDiaFile::m_sbInitialized = 0;
@ -802,6 +804,50 @@ bool PDBDiaFile::resolveSymbolSize(IDiaSymbol* symbol, uint64_t & size, uint32_t
return res; return res;
} }
typedef char* pchar_t;
typedef const char* pcchar_t;
typedef char* (*GetParameter_t)(long n);
using Alloc_t = decltype(malloc);
using Free_t = decltype(free);
enum
{
UNDNAME_COMPLETE = 0x0, //Enables full undecoration.
UNDNAME_NO_LEADING_UNDERSCORES = 0x1, //Removes leading underscores from Microsoft extended keywords.
UNDNAME_NO_MS_KEYWORDS = 0x2, //Disables expansion of Microsoft extended keywords.
UNDNAME_NO_FUNCTION_RETURNS = 0x4, //Disables expansion of return type for primary declaration.
UNDNAME_NO_ALLOCATION_MODEL = 0x8, //Disables expansion of the declaration model.
UNDNAME_NO_ALLOCATION_LANGUAGE = 0x10, //Disables expansion of the declaration language specifier.
UNDNAME_NO_MS_THISTYPE = 0x20, //NYI Disable expansion of MS keywords on the 'this' type for primary declaration.
UNDNAME_NO_CV_THISTYPE = 0x40, //NYI Disable expansion of CV modifiers on the 'this' type for primary declaration/
UNDNAME_NO_THISTYPE = 0x60, //Disables all modifiers on the this type.
UNDNAME_NO_ACCESS_SPECIFIERS = 0x80, //Disables expansion of access specifiers for members.
UNDNAME_NO_THROW_SIGNATURES = 0x100, //Disables expansion of "throw-signatures" for functions and pointers to functions.
UNDNAME_NO_MEMBER_TYPE = 0x200, //Disables expansion of static or virtual members.
UNDNAME_NO_RETURN_UDT_MODEL = 0x400, //Disables expansion of the Microsoft model for UDT returns.
UNDNAME_32_BIT_DECODE = 0x800, //Undecorates 32-bit decorated names.
UNDNAME_NAME_ONLY = 0x1000, //Gets only the name for primary declaration; returns just [scope::]name. Expands template params.
UNDNAME_TYPE_ONLY = 0x2000, //Input is just a type encoding; composes an abstract declarator.
UNDNAME_HAVE_PARAMETERS = 0x4000, //The real template parameters are available.
UNDNAME_NO_ECSU = 0x8000, //Suppresses enum/class/struct/union.
UNDNAME_NO_IDENT_CHAR_CHECK = 0x10000, //Suppresses check for valid identifier characters.
UNDNAME_NO_PTR64 = 0x20000, //Does not include ptr64 in output.
};
#if _MSC_VER != 1800
#error unDNameEx is undocumented and possibly unsupported on your runtime! Uncomment this line if you understand the risks and want continue regardless...
#endif //_MSC_VER
//undname.cxx
extern "C" pchar_t __cdecl __unDNameEx(_Out_opt_z_cap_(maxStringLength) pchar_t outputString,
pcchar_t name,
int maxStringLength, // Note, COMMA is leading following optional arguments
Alloc_t pAlloc,
Free_t pFree,
GetParameter_t pGetParameter,
unsigned long disableFlags
);
bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, const bool collectUndecoratedNames) bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, const bool collectUndecoratedNames)
{ {
HRESULT hr; HRESULT hr;
@ -825,9 +871,38 @@ bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo,
symbolInfo.name = getSymbolNameString(symbol); symbolInfo.name = getSymbolNameString(symbol);
if(collectUndecoratedNames) if(collectUndecoratedNames && !symbolInfo.name.empty() && symbolInfo.name.at(0) == '?')
{ {
symbolInfo.undecoratedName = getSymbolUndecoratedNameString(symbol); //TODO: undocumented hack to have some kind of performance while undecorating names
auto mymalloc = [](size_t size) { return emalloc(size, "convertSymbolInfo::undecoratedName"); };
auto myfree = [](void* ptr) { return efree(ptr, "convertSymbolInfo::undecoratedName"); };
symbolInfo.undecoratedName.resize(max(512, symbolInfo.name.length() * 2));
if(!__unDNameEx((char*)symbolInfo.undecoratedName.data(),
symbolInfo.name.c_str(),
symbolInfo.undecoratedName.size(),
mymalloc,
myfree,
nullptr,
UNDNAME_COMPLETE))
{
symbolInfo.undecoratedName.clear();
}
else
{
symbolInfo.undecoratedName.resize(strlen(symbolInfo.undecoratedName.c_str()));
if(symbolInfo.name == symbolInfo.undecoratedName)
symbolInfo.undecoratedName = ""; //https://stackoverflow.com/a/18299315
/*auto test = getSymbolUndecoratedNameString(symbol); //TODO: this does not appear to work very well
if(!symbolInfo.undecoratedName.empty())
{
if(test != symbolInfo.undecoratedName)
{
dprintf("undecoration mismatch, msvcrt: \"%s\", DIA: \"%s\"\n",
symbolInfo.undecoratedName.c_str(),
test.c_str());
}
}*/
}
} }
hr = symbol->get_addressSection((DWORD*)&symbolInfo.segment); hr = symbol->get_addressSection((DWORD*)&symbolInfo.segment);

View File

@ -79,10 +79,9 @@ void SymEnum(duint Base, CBSYMBOLENUM EnumCallback, void* UserData)
return true; return true;
} }
// Convert a mangled/decorated C++ name to a readable format // Don't show duplicated decorated/undecorated names
if(info.decoratedName == info.undecoratedName) if(info.undecoratedName.empty() || info.decoratedName == info.undecoratedName)
{ {
curSymbol.decoratedSymbol = curSymbol.undecoratedSymbol;
curSymbol.undecoratedSymbol = nullptr; curSymbol.undecoratedSymbol = nullptr;
} }

View File

@ -305,10 +305,18 @@ void SymbolView::cbSymbolEnum(SYMBOLINFO* symbol, void* user)
{ {
symbolList->setCellContent(index, 2, symbol->decoratedSymbol); symbolList->setCellContent(index, 2, symbol->decoratedSymbol);
} }
else
{
symbolList->setCellContent(index, 2, QString());
}
if(symbol->undecoratedSymbol) if(symbol->undecoratedSymbol)
{ {
symbolList->setCellContent(index, 3, symbol->undecoratedSymbol); symbolList->setCellContent(index, 3, symbol->undecoratedSymbol);
} }
else
{
symbolList->setCellContent(index, 3, QString());
}
if(symbol->isImported) if(symbol->isImported)
{ {