From 62e5e001271cdec32e9c604b205726fa75f1bc9a Mon Sep 17 00:00:00 2001 From: Nicholas McDaniel Date: Fri, 27 Dec 2024 11:37:23 -0500 Subject: [PATCH 1/3] Add cxx_demangle support to Windows --- library/CMakeLists.txt | 5 ++++- library/MiscUtils.cpp | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 12417c02ee..c24a4cedbb 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -329,7 +329,7 @@ elseif(UNIX) set(PROJECT_LIBS rt dl dfhack-md5 ${DFHACK_TINYXML}) else(WIN32) # FIXME: do we really need psapi? - set(PROJECT_LIBS psapi dfhack-md5 ${DFHACK_TINYXML}) + set(PROJECT_LIBS psapi dbghelp dfhack-md5 ${DFHACK_TINYXML}) endif() set(VERSION_SRCS DFHackVersion.cpp) @@ -418,6 +418,9 @@ target_link_libraries(dfhack protobuf-lite clsocket lua jsoncpp_static dfhack-ve set_target_properties(dfhack PROPERTIES INTERFACE_LINK_LIBRARIES "") target_link_libraries(dfhack-client protobuf-lite clsocket jsoncpp_static) +if(WIN32) + target_link_libraries(dfhack-client dbghelp) +endif() target_link_libraries(dfhack-run dfhack-client) if(APPLE) diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index f0a129090f..be59e9f6aa 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -33,6 +33,7 @@ distribution. // We don't want min and max macros #define NOMINMAX #include + #include #else #include #include @@ -687,10 +688,35 @@ DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::str else *status_out = "unknown error"; } return out; -#else - if (status_out) { - *status_out = "not implemented on this platform"; +#elif defined(_WIN32) + const char* mangled_cstr = mangled_name.c_str(); + + char demangledBuf[MAX_SYM_NAME]; + DWORD flags = UNDNAME_NAME_ONLY; + + if (mangled_cstr[0] == '.') { + // Symbol is a type, demangle as such + // Flag is actually "UNDNAME_TYPE_ONLY", but hasn't been renamed for this method yet. + flags |= UNDNAME_NO_ARGUMENTS; + mangled_cstr++; } - return ""; + + DWORD res = UnDecorateSymbolName(mangled_cstr, (char*)&demangledBuf, MAX_SYM_NAME, flags); + + std::string out; + if (res == 0) { + // Demangling failed + *status_out = "demangling failed"; + return out; + } + if (demangledBuf[0] == '?') { + // Wine failed to demangle symbol + *status_out = "wine demangling failed"; + return out; + } + out = (char*)&demangledBuf; + return out; +#else + #error Platform does not support symbol demangling #endif } From 09842d3ed116da37414f456b59a55cde632604d1 Mon Sep 17 00:00:00 2001 From: Nicholas McDaniel Date: Fri, 27 Dec 2024 11:37:52 -0500 Subject: [PATCH 2/3] Use cxx_demangle to demangle classnames on Windows --- library/Process-windows.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/library/Process-windows.cpp b/library/Process-windows.cpp index 7d9469b455..2450eb87bd 100644 --- a/library/Process-windows.cpp +++ b/library/Process-windows.cpp @@ -34,6 +34,7 @@ distribution. #include "Internal.h" #include "MemAccess.h" #include "Memory.h" +#include "MiscUtils.h" #include "VersionInfo.h" #include "VersionInfoFactory.h" @@ -128,21 +129,28 @@ Process::~Process() string Process::doReadClassName (void * vptr) { - char * rtti = readPtr((char *)vptr - sizeof(void*)); + char* rtti = readPtr((char *)vptr - sizeof(void*)); #ifdef DFHACK64 - void *base; + void* base; if (!RtlPcToFileHeader(rtti, &base)) return "dummy"; - char * typeinfo = (char *)base + readDWord(rtti + 0xC); - string raw = readCString(typeinfo + 0x10+4); // skips the .?AV + char* typeinfo = (char *)base + readDWord(rtti + 0xC); + std::string raw = readCString(typeinfo + 0x10); #else - char * typeinfo = readPtr(rtti + 0xC); - string raw = readCString(typeinfo + 0xC); // skips the .?AV + char* typeinfo = readPtr(rtti + 0xC); + std::string raw = readCString(typeinfo + 0x8); #endif - if (!raw.length()) + if (raw.length() == 0) return "dummy"; - raw.resize(raw.length() - 2);// trim @@ from end - return raw; + + string status; + string demangled = cxx_demangle(raw, &status); + + if (demangled.length() == 0) { + return "dummy"; + } + + return demangled; } /* From 7bb14d881441f088ca67ee0481a586faafe9d472 Mon Sep 17 00:00:00 2001 From: Nicholas McDaniel Date: Fri, 27 Dec 2024 11:50:44 -0500 Subject: [PATCH 3/3] Use cxx_demangle to demangle classnames on Linux/Darwin --- library/Process-darwin.cpp | 14 ++++++++++---- library/Process-linux.cpp | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/library/Process-darwin.cpp b/library/Process-darwin.cpp index 63114e77ce..f8c0833a78 100644 --- a/library/Process-darwin.cpp +++ b/library/Process-darwin.cpp @@ -47,6 +47,7 @@ distribution. #include "Internal.h" #include "MemAccess.h" #include "Memory.h" +#include "MiscUtils.h" #include "VersionInfo.h" #include "VersionInfoFactory.h" #include "md5wrapper.h" @@ -122,13 +123,18 @@ Process::~Process() string Process::doReadClassName (void * vptr) { - //FIXME: BAD!!!!! char * typeinfo = Process::readPtr(((char *)vptr - sizeof(void*))); char * typestring = Process::readPtr(typeinfo + sizeof(void*)); string raw = readCString(typestring); - size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers - size_t end = raw.length(); - return raw.substr(start,end-start); + + string status; + string demangled = cxx_demangle(raw, &status); + + if (demangled.length() == 0) { + return "dummy"; + } + + return demangled; } const char * diff --git a/library/Process-linux.cpp b/library/Process-linux.cpp index ea54516034..85e83f54f6 100644 --- a/library/Process-linux.cpp +++ b/library/Process-linux.cpp @@ -40,6 +40,7 @@ distribution. #include "Internal.h" #include "MemAccess.h" #include "Memory.h" +#include "MiscUtils.h" #include "VersionInfo.h" #include "VersionInfoFactory.h" #include "modules/Filesystem.h" @@ -120,13 +121,18 @@ Process::~Process() string Process::doReadClassName (void * vptr) { - //FIXME: BAD!!!!! - char * typeinfo = Process::readPtr(((char *)vptr - sizeof(void*))); - char * typestring = Process::readPtr(typeinfo + sizeof(void*)); + char* typeinfo = Process::readPtr(((char *)vptr - sizeof(void*))); + char* typestring = Process::readPtr(typeinfo + sizeof(void*)); string raw = readCString(typestring); - size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers - size_t end = raw.length(); - return raw.substr(start,end-start); + + string status; + string demangled = cxx_demangle(raw, &status); + + if (demangled.length() == 0) { + return "dummy"; + } + + return demangled; } //FIXME: cross-reference with ELF segment entries?