From 46499a66cca55a6f8d181257fac8620532c78c32 Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 10 Aug 2023 15:01:19 -0400 Subject: [PATCH 1/3] Add cxx_demangle() and Lua wrapper --- docs/dev/Lua API.rst | 5 +++++ library/LuaApi.cpp | 19 +++++++++++++++++++ library/MiscUtils.cpp | 27 +++++++++++++++++++++++++++ library/include/MiscUtils.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index cd35d9465..a18b00480 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -2735,6 +2735,11 @@ and are only documented here for completeness: The oldval, newval or delta arguments may be used to specify additional constraints. Returns: *found_index*, or *nil* if end reached. +* ``dfhack.internal.cxxDemangle(mangled_name)`` + + Decodes a mangled C++ symbol name. Returns the demangled name on success, or + ``nil, error_message`` on failure. + * ``dfhack.internal.getDir(path)`` Lists files/directories in a directory. diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index c19c10197..578bb4746 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -3333,6 +3333,24 @@ static int internal_diffscan(lua_State *L) return 1; } +static int internal_cxxDemangle(lua_State *L) +{ + std::string mangled = luaL_checkstring(L, 1); + std::string status; + std::string demangled = cxx_demangle(mangled, &status); + if (demangled.length()) + { + lua_pushstring(L, demangled.c_str()); + return 1; + } + else + { + lua_pushnil(L); + lua_pushstring(L, status.c_str()); + return 2; + } +} + static int internal_runCommand(lua_State *L) { color_ostream *out = NULL; @@ -3637,6 +3655,7 @@ static const luaL_Reg dfhack_internal_funcs[] = { { "memcmp", internal_memcmp }, { "memscan", internal_memscan }, { "diffscan", internal_diffscan }, + { "cxxDemangle", internal_cxxDemangle }, { "getDir", filesystem_listdir }, { "runCommand", internal_runCommand }, { "getModifiers", internal_getModifiers }, diff --git a/library/MiscUtils.cpp b/library/MiscUtils.cpp index 7ffd4e1c6..a90cf1208 100644 --- a/library/MiscUtils.cpp +++ b/library/MiscUtils.cpp @@ -36,6 +36,7 @@ distribution. #else #include #include + #include #endif #include @@ -472,3 +473,29 @@ DFHACK_EXPORT std::string DF2CONSOLE(DFHack::color_ostream &out, const std::stri { return out.is_console() ? DF2CONSOLE(in) : in; } + +DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::string *status_out) +{ +#ifdef __GNUC__ + int status; + char *demangled = abi::__cxa_demangle(mangled_name.c_str(), nullptr, nullptr, &status); + std::string out; + if (demangled) { + out = demangled; + free(demangled); + } + if (status_out) { + if (status == 0) *status_out = "success"; + else if (status == -1) *status_out = "memory allocation failure"; + else if (status == -2) *status_out = "invalid mangled name"; + else if (status == -3) *status_out = "invalid arguments"; + else *status_out = "unknown error"; + } + return out; +#else + if (status_out) { + *status_out = "not implemented on this platform"; + } + return ""; +#endif +} diff --git a/library/include/MiscUtils.h b/library/include/MiscUtils.h index 59adcdbe5..06915fde5 100644 --- a/library/include/MiscUtils.h +++ b/library/include/MiscUtils.h @@ -474,3 +474,5 @@ DFHACK_EXPORT std::string UTF2DF(const std::string &in); DFHACK_EXPORT std::string DF2UTF(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(const std::string &in); DFHACK_EXPORT std::string DF2CONSOLE(DFHack::color_ostream &out, const std::string &in); + +DFHACK_EXPORT std::string cxx_demangle(const std::string &mangled_name, std::string *status_out); From 0ac7d23bcf69346374d9ff25470a1bb6866ae5da Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 10 Aug 2023 15:06:24 -0400 Subject: [PATCH 2/3] Add memscan.read_global_table() and memscan.read_c_string() --- library/lua/memscan.lua | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/library/lua/memscan.lua b/library/lua/memscan.lua index 4a9824010..a8c265adb 100644 --- a/library/lua/memscan.lua +++ b/library/lua/memscan.lua @@ -533,4 +533,32 @@ function get_screen_size() return w,h end +-- Global table + +function read_c_string(char_ptr) + local s = '' + local i = 0 + while char_ptr[i] ~= 0 do + s = s .. string.char(char_ptr[i]) + i = i + 1 + end + return s +end + +function read_global_table(global_table) + global_table = global_table or df.global.global_table + local out = {} + local i = 0 + while true do + -- use _displace() so we can read past the bounds of the array set in structures, if necessary + local entry = global_table[0]:_displace(i) + if not entry.name or not entry.address then + break + end + out[read_c_string(entry.name)] = entry + i = i + 1 + end + return out +end + return _ENV From ea43d6c801f07c27be49c02c4933ad7ff550645b Mon Sep 17 00:00:00 2001 From: lethosor Date: Thu, 10 Aug 2023 15:06:45 -0400 Subject: [PATCH 3/3] get_code_segment(): update check for DF executable on Linux --- library/lua/memscan.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/library/lua/memscan.lua b/library/lua/memscan.lua index a8c265adb..a4c07d38c 100644 --- a/library/lua/memscan.lua +++ b/library/lua/memscan.lua @@ -217,6 +217,7 @@ function get_code_segment() for i,mem in ipairs(dfhack.internal.getMemRanges()) do if mem.read and mem.execute and (string.match(mem.name,'/dwarfort%.exe$') + or string.match(mem.name,'/dwarfort$') or string.match(mem.name,'/Dwarf_Fortress$') or string.match(mem.name,'Dwarf Fortress%.exe')) then