diff --git a/src/dbg/module.cpp b/src/dbg/module.cpp index 7d044ee2..eedeff31 100644 --- a/src/dbg/module.cpp +++ b/src/dbg/module.cpp @@ -12,6 +12,7 @@ #include "console.h" #include "debugger.h" #include +#include "symbolundecorator.h" std::map, RangeCompare> modinfo; std::unordered_map hashNameMap; @@ -156,6 +157,13 @@ static void ReadExportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) { return Info.exports.at(a).rva < Info.exports.at(b).rva; }); + + // undecorate names + for(auto & x : Info.exports) + { + if(!x.name.empty()) + undecorateName(x.name, x.undecoratedName); + } } static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) @@ -237,6 +245,10 @@ static void ReadImportDirectory(MODINFO & Info, ULONG_PTR FileMapVA) { return Info.imports[a].iatRva < Info.imports[b].iatRva; }); + + // undecorate names + for(auto & i : Info.imports) + undecorateName(i.name, i.undecoratedName); } static void ReadTlsCallbacks(MODINFO & Info, ULONG_PTR FileMapVA) @@ -617,7 +629,6 @@ void GetModuleInfo(MODINFO & Info, ULONG_PTR FileMapVA) ReadExportDirectory(Info, FileMapVA); ReadImportDirectory(Info, FileMapVA); - dprintf("[%s%s] read %d imports and %d exports\n", Info.name, Info.extension, Info.imports.size(), Info.exports.size()); ReadTlsCallbacks(Info, FileMapVA); ReadBaseRelocationTable(Info, FileMapVA); ReadDebugDirectory(Info, FileMapVA); @@ -1166,7 +1177,7 @@ void MODIMPORT::convertToGuiSymbol(duint base, SYMBOLINFO* info) const info->addr = base + iatRva; info->type = sym_import; info->decoratedSymbol = (char*)name.c_str(); - info->undecoratedSymbol = ""; + info->undecoratedSymbol = (char*)undecoratedName.c_str(); info->freeDecorated = info->freeUndecorated = false; } @@ -1175,6 +1186,6 @@ void MODEXPORT::convertToGuiSymbol(duint base, SYMBOLINFO* info) const info->addr = base + rva; info->type = sym_export; info->decoratedSymbol = (char*)name.c_str(); - info->undecoratedSymbol = ""; + info->undecoratedSymbol = (char*)undecoratedName.c_str(); info->freeDecorated = info->freeUndecorated = false; } diff --git a/src/dbg/module.h b/src/dbg/module.h index 61d5b6f3..5629d24c 100644 --- a/src/dbg/module.h +++ b/src/dbg/module.h @@ -57,6 +57,7 @@ struct MODEXPORT : SymbolInfoGui bool forwarded = false; String forwardName; String name; + String undecoratedName; virtual void convertToGuiSymbol(duint base, SYMBOLINFO* info) const override; }; @@ -67,6 +68,7 @@ struct MODIMPORT : SymbolInfoGui DWORD iatRva; duint ordinal; //equal to -1 if imported by name String name; + String undecoratedName; virtual void convertToGuiSymbol(duint base, SYMBOLINFO* info) const override; }; diff --git a/src/dbg/pdbdiafile.cpp b/src/dbg/pdbdiafile.cpp index 082b2e51..00c0a161 100644 --- a/src/dbg/pdbdiafile.cpp +++ b/src/dbg/pdbdiafile.cpp @@ -13,6 +13,7 @@ #include "pdbdiafile.h" #include "stringutils.h" #include "console.h" +#include "symbolundecorator.h" //Taken from: https://msdn.microsoft.com/en-us/library/ms752876(v=vs.85).aspx class FileStream : public IStream @@ -973,50 +974,6 @@ bool PDBDiaFile::resolveSymbolSize(IDiaSymbol* symbol, uint64_t & size, uint32_t 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, InternalQueryContext_t & context) { HRESULT hr; @@ -1042,36 +999,7 @@ bool PDBDiaFile::convertSymbolInfo(IDiaSymbol* symbol, DiaSymbol_t & symbolInfo, 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"); }; - 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) - { - GuiSymbolLogAdd(StringUtils::sprintf("undecoration mismatch, msvcrt: \"%s\", DIA: \"%s\"\n", - symbolInfo.undecoratedName.c_str(), - test.c_str()).c_str()); - } - }*/ - } + undecorateName(symbolInfo.name, symbolInfo.undecoratedName); } else { diff --git a/src/dbg/symbolundecorator.h b/src/dbg/symbolundecorator.h new file mode 100644 index 00000000..9f3477ac --- /dev/null +++ b/src/dbg/symbolundecorator.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include + +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 +{ + X_UNDNAME_COMPLETE = 0x0, //Enables full undecoration. + X_UNDNAME_NO_LEADING_UNDERSCORES = 0x1, //Removes leading underscores from Microsoft extended keywords. + X_UNDNAME_NO_MS_KEYWORDS = 0x2, //Disables expansion of Microsoft extended keywords. + X_UNDNAME_NO_FUNCTION_RETURNS = 0x4, //Disables expansion of return type for primary declaration. + X_UNDNAME_NO_ALLOCATION_MODEL = 0x8, //Disables expansion of the declaration model. + X_UNDNAME_NO_ALLOCATION_LANGUAGE = 0x10, //Disables expansion of the declaration language specifier. + X_UNDNAME_NO_MS_THISTYPE = 0x20, //NYI Disable expansion of MS keywords on the 'this' type for primary declaration. + X_UNDNAME_NO_CV_THISTYPE = 0x40, //NYI Disable expansion of CV modifiers on the 'this' type for primary declaration/ + X_UNDNAME_NO_THISTYPE = 0x60, //Disables all modifiers on the this type. + X_UNDNAME_NO_ACCESS_SPECIFIERS = 0x80, //Disables expansion of access specifiers for members. + X_UNDNAME_NO_THROW_SIGNATURES = 0x100, //Disables expansion of "throw-signatures" for functions and pointers to functions. + X_UNDNAME_NO_MEMBER_TYPE = 0x200, //Disables expansion of static or virtual members. + X_UNDNAME_NO_RETURN_UDT_MODEL = 0x400, //Disables expansion of the Microsoft model for UDT returns. + X_UNDNAME_32_BIT_DECODE = 0x800, //Undecorates 32-bit decorated names. + X_UNDNAME_NAME_ONLY = 0x1000, //Gets only the name for primary declaration; returns just [scope::]name. Expands template params. + X_UNDNAME_TYPE_ONLY = 0x2000, //Input is just a type encoding; composes an abstract declarator. + X_UNDNAME_HAVE_PARAMETERS = 0x4000, //The real template parameters are available. + X_UNDNAME_NO_ECSU = 0x8000, //Suppresses enum/class/struct/union. + X_UNDNAME_NO_IDENT_CHAR_CHECK = 0x10000, //Suppresses check for valid identifier characters. + X_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 + ); + +template +inline bool undecorateName(const std::string & decoratedName, std::string & undecoratedName) +{ + //TODO: undocumented hack to have some kind of performance while undecorating names + auto mymalloc = [](size_t size) { return emalloc(size, "symbolundecorator::undecoratedName"); }; + auto myfree = [](void* ptr) { return efree(ptr, "symbolundecorator::undecoratedName"); }; + + undecoratedName.resize(max(MaxSize, decoratedName.length() * 2)); + if(!__unDNameEx((char*)undecoratedName.data(), + decoratedName.c_str(), + (int)undecoratedName.size(), + mymalloc, + myfree, + nullptr, + X_UNDNAME_COMPLETE)) + { + undecoratedName.clear(); + return false; + } + else + { + undecoratedName.resize(strlen(undecoratedName.c_str())); + if(decoratedName == undecoratedName) + undecoratedName = ""; //https://stackoverflow.com/a/18299315 + return true; + } +} \ No newline at end of file diff --git a/src/dbg/x64dbg_dbg.vcxproj b/src/dbg/x64dbg_dbg.vcxproj index 613c84ac..68d24279 100644 --- a/src/dbg/x64dbg_dbg.vcxproj +++ b/src/dbg/x64dbg_dbg.vcxproj @@ -238,6 +238,7 @@ + diff --git a/src/dbg/x64dbg_dbg.vcxproj.filters b/src/dbg/x64dbg_dbg.vcxproj.filters index be43c633..66bce11e 100644 --- a/src/dbg/x64dbg_dbg.vcxproj.filters +++ b/src/dbg/x64dbg_dbg.vcxproj.filters @@ -997,5 +997,8 @@ Header Files\Third Party\WinInet-Downloader + + Header Files\Symbols + \ No newline at end of file