Skip to content

Commit 9f3b117

Browse files
authoredDec 28, 2024
Merge pull request #5144 from NicksWorld/feat/cxxdemangle
Improved Symbol Demangling
2 parents 7d832f3 + 7bb14d8 commit 9f3b117

5 files changed

+73
-24
lines changed
 

‎library/CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ elseif(UNIX)
329329
set(PROJECT_LIBS rt dl dfhack-md5 ${DFHACK_TINYXML})
330330
else(WIN32)
331331
# FIXME: do we really need psapi?
332-
set(PROJECT_LIBS psapi dfhack-md5 ${DFHACK_TINYXML})
332+
set(PROJECT_LIBS psapi dbghelp dfhack-md5 ${DFHACK_TINYXML})
333333
endif()
334334

335335
set(VERSION_SRCS DFHackVersion.cpp)
@@ -418,6 +418,9 @@ target_link_libraries(dfhack protobuf-lite clsocket lua jsoncpp_static dfhack-ve
418418
set_target_properties(dfhack PROPERTIES INTERFACE_LINK_LIBRARIES "")
419419

420420
target_link_libraries(dfhack-client protobuf-lite clsocket jsoncpp_static)
421+
if(WIN32)
422+
target_link_libraries(dfhack-client dbghelp)
423+
endif()
421424
target_link_libraries(dfhack-run dfhack-client)
422425

423426
if(APPLE)

‎library/MiscUtils.cpp

+30-4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ distribution.
3333
// We don't want min and max macros
3434
#define NOMINMAX
3535
#include <Windows.h>
36+
#include <DbgHelp.h>
3637
#else
3738
#include <sys/time.h>
3839
#include <ctime>
@@ -687,10 +688,35 @@ DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::str
687688
else *status_out = "unknown error";
688689
}
689690
return out;
690-
#else
691-
if (status_out) {
692-
*status_out = "not implemented on this platform";
691+
#elif defined(_WIN32)
692+
const char* mangled_cstr = mangled_name.c_str();
693+
694+
char demangledBuf[MAX_SYM_NAME];
695+
DWORD flags = UNDNAME_NAME_ONLY;
696+
697+
if (mangled_cstr[0] == '.') {
698+
// Symbol is a type, demangle as such
699+
// Flag is actually "UNDNAME_TYPE_ONLY", but hasn't been renamed for this method yet.
700+
flags |= UNDNAME_NO_ARGUMENTS;
701+
mangled_cstr++;
693702
}
694-
return "";
703+
704+
DWORD res = UnDecorateSymbolName(mangled_cstr, (char*)&demangledBuf, MAX_SYM_NAME, flags);
705+
706+
std::string out;
707+
if (res == 0) {
708+
// Demangling failed
709+
*status_out = "demangling failed";
710+
return out;
711+
}
712+
if (demangledBuf[0] == '?') {
713+
// Wine failed to demangle symbol
714+
*status_out = "wine demangling failed";
715+
return out;
716+
}
717+
out = (char*)&demangledBuf;
718+
return out;
719+
#else
720+
#error Platform does not support symbol demangling
695721
#endif
696722
}

‎library/Process-darwin.cpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ distribution.
4747
#include "Internal.h"
4848
#include "MemAccess.h"
4949
#include "Memory.h"
50+
#include "MiscUtils.h"
5051
#include "VersionInfo.h"
5152
#include "VersionInfoFactory.h"
5253
#include "md5wrapper.h"
@@ -122,13 +123,18 @@ Process::~Process()
122123

123124
string Process::doReadClassName (void * vptr)
124125
{
125-
//FIXME: BAD!!!!!
126126
char * typeinfo = Process::readPtr(((char *)vptr - sizeof(void*)));
127127
char * typestring = Process::readPtr(typeinfo + sizeof(void*));
128128
string raw = readCString(typestring);
129-
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
130-
size_t end = raw.length();
131-
return raw.substr(start,end-start);
129+
130+
string status;
131+
string demangled = cxx_demangle(raw, &status);
132+
133+
if (demangled.length() == 0) {
134+
return "dummy";
135+
}
136+
137+
return demangled;
132138
}
133139

134140
const char *

‎library/Process-linux.cpp

+12-6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ distribution.
4040
#include "Internal.h"
4141
#include "MemAccess.h"
4242
#include "Memory.h"
43+
#include "MiscUtils.h"
4344
#include "VersionInfo.h"
4445
#include "VersionInfoFactory.h"
4546
#include "modules/Filesystem.h"
@@ -120,13 +121,18 @@ Process::~Process()
120121

121122
string Process::doReadClassName (void * vptr)
122123
{
123-
//FIXME: BAD!!!!!
124-
char * typeinfo = Process::readPtr(((char *)vptr - sizeof(void*)));
125-
char * typestring = Process::readPtr(typeinfo + sizeof(void*));
124+
char* typeinfo = Process::readPtr(((char *)vptr - sizeof(void*)));
125+
char* typestring = Process::readPtr(typeinfo + sizeof(void*));
126126
string raw = readCString(typestring);
127-
size_t start = raw.find_first_of("abcdefghijklmnopqrstuvwxyz");// trim numbers
128-
size_t end = raw.length();
129-
return raw.substr(start,end-start);
127+
128+
string status;
129+
string demangled = cxx_demangle(raw, &status);
130+
131+
if (demangled.length() == 0) {
132+
return "dummy";
133+
}
134+
135+
return demangled;
130136
}
131137

132138
//FIXME: cross-reference with ELF segment entries?

‎library/Process-windows.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ distribution.
3434
#include "Internal.h"
3535
#include "MemAccess.h"
3636
#include "Memory.h"
37+
#include "MiscUtils.h"
3738
#include "VersionInfo.h"
3839
#include "VersionInfoFactory.h"
3940

@@ -128,21 +129,28 @@ Process::~Process()
128129

129130
string Process::doReadClassName (void * vptr)
130131
{
131-
char * rtti = readPtr((char *)vptr - sizeof(void*));
132+
char* rtti = readPtr((char *)vptr - sizeof(void*));
132133
#ifdef DFHACK64
133-
void *base;
134+
void* base;
134135
if (!RtlPcToFileHeader(rtti, &base))
135136
return "dummy";
136-
char * typeinfo = (char *)base + readDWord(rtti + 0xC);
137-
string raw = readCString(typeinfo + 0x10+4); // skips the .?AV
137+
char* typeinfo = (char *)base + readDWord(rtti + 0xC);
138+
std::string raw = readCString(typeinfo + 0x10);
138139
#else
139-
char * typeinfo = readPtr(rtti + 0xC);
140-
string raw = readCString(typeinfo + 0xC); // skips the .?AV
140+
char* typeinfo = readPtr(rtti + 0xC);
141+
std::string raw = readCString(typeinfo + 0x8);
141142
#endif
142-
if (!raw.length())
143+
if (raw.length() == 0)
143144
return "dummy";
144-
raw.resize(raw.length() - 2);// trim @@ from end
145-
return raw;
145+
146+
string status;
147+
string demangled = cxx_demangle(raw, &status);
148+
149+
if (demangled.length() == 0) {
150+
return "dummy";
151+
}
152+
153+
return demangled;
146154
}
147155

148156
/*

0 commit comments

Comments
 (0)