From 457bc4b8a1bdcc604d435c49bba45426120c84f6 Mon Sep 17 00:00:00 2001 From: Jeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com> Date: Thu, 13 Feb 2025 23:39:05 -0600 Subject: [PATCH] Check external symbols start with _Z before demangling --- src/cpptrace.cpp | 6 +++--- src/ctrace.cpp | 2 +- src/demangle/demangle.hpp | 2 +- src/demangle/demangle_with_cxxabi.cpp | 13 ++++++------- src/demangle/demangle_with_nothing.cpp | 2 +- src/demangle/demangle_with_winapi.cpp | 2 +- src/platform/exception_type.hpp | 2 +- src/utils.cpp | 2 +- tools/resolver/main.cpp | 2 +- 9 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/cpptrace.cpp b/src/cpptrace.cpp index 7ea87ed..be497fb 100644 --- a/src/cpptrace.cpp +++ b/src/cpptrace.cpp @@ -62,7 +62,7 @@ namespace cpptrace { try { std::vector trace = detail::resolve_frames(frames); for(auto& frame : trace) { - frame.symbol = detail::demangle(frame.symbol); + frame.symbol = detail::demangle(frame.symbol, true); } return {std::move(trace)}; } catch(...) { // NOSONAR @@ -109,7 +109,7 @@ namespace cpptrace { try { std::vector trace = detail::resolve_frames(frames); for(auto& frame : trace) { - frame.symbol = detail::demangle(frame.symbol); + frame.symbol = detail::demangle(frame.symbol, true); } return {std::move(trace)}; } catch(...) { // NOSONAR @@ -312,7 +312,7 @@ namespace cpptrace { std::vector frames = detail::capture_frames(skip + 1, max_depth); std::vector trace = detail::resolve_frames(frames); for(auto& frame : trace) { - frame.symbol = detail::demangle(frame.symbol); + frame.symbol = detail::demangle(frame.symbol, true); } return {std::move(trace)}; } catch(...) { // NOSONAR diff --git a/src/ctrace.cpp b/src/ctrace.cpp index eacf15e..e67c9e3 100644 --- a/src/ctrace.cpp +++ b/src/ctrace.cpp @@ -107,7 +107,7 @@ CTRACE_FORMAT_EPILOGUE new_frame.line = frame.line.value_or(invalid_pos); new_frame.column = frame.column.value_or(invalid_pos); new_frame.filename = generate_owning_string(frame.filename).data; - new_frame.symbol = generate_owning_string(cpptrace::detail::demangle(frame.symbol)).data; + new_frame.symbol = generate_owning_string(cpptrace::detail::demangle(frame.symbol, true)).data; new_frame.is_inline = ctrace_bool(frame.is_inline); return new_frame; } diff --git a/src/demangle/demangle.hpp b/src/demangle/demangle.hpp index 9aba59d..9d2c148 100644 --- a/src/demangle/demangle.hpp +++ b/src/demangle/demangle.hpp @@ -5,7 +5,7 @@ namespace cpptrace { namespace detail { - std::string demangle(const std::string&); + std::string demangle(const std::string& name, bool check_prefix); } } diff --git a/src/demangle/demangle_with_cxxabi.cpp b/src/demangle/demangle_with_cxxabi.cpp index 30435e5..f089680 100644 --- a/src/demangle/demangle_with_cxxabi.cpp +++ b/src/demangle/demangle_with_cxxabi.cpp @@ -13,13 +13,12 @@ namespace cpptrace { namespace detail { - std::string demangle(const std::string& name) { - // TODO: Do a special check to ensure external names start with _Z? - // // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#demangler - // // check both _Z and __Z, apple prefixes all symbols with an underscore - // if(!(starts_with(name, "_Z") || starts_with(name, "__Z"))) { - // return name; - // } + std::string demangle(const std::string& name, bool check_prefix) { + // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#demangler + // Check both _Z and __Z, apple prefixes all symbols with an underscore + if(check_prefix && !(starts_with(name, "_Z") || starts_with(name, "__Z"))) { + return name; + } // Apple clang demangles __Z just fine but gcc doesn't, so just offset the leading underscore std::size_t offset = 0; if(starts_with(name, "__Z")) { diff --git a/src/demangle/demangle_with_nothing.cpp b/src/demangle/demangle_with_nothing.cpp index a3fcd98..7c81d03 100644 --- a/src/demangle/demangle_with_nothing.cpp +++ b/src/demangle/demangle_with_nothing.cpp @@ -6,7 +6,7 @@ namespace cpptrace { namespace detail { - std::string demangle(const std::string& name) { + std::string demangle(const std::string& name, bool) { return name; } } diff --git a/src/demangle/demangle_with_winapi.cpp b/src/demangle/demangle_with_winapi.cpp index 5d702c4..521c115 100644 --- a/src/demangle/demangle_with_winapi.cpp +++ b/src/demangle/demangle_with_winapi.cpp @@ -12,7 +12,7 @@ namespace cpptrace { namespace detail { - std::string demangle(const std::string& name) { + std::string demangle(const std::string& name, bool) { char buffer[500]; auto ret = UnDecorateSymbolName(name.c_str(), buffer, sizeof(buffer) - 1, 0); if(ret == 0) { diff --git a/src/platform/exception_type.hpp b/src/platform/exception_type.hpp index a9e967d..711497b 100644 --- a/src/platform/exception_type.hpp +++ b/src/platform/exception_type.hpp @@ -17,7 +17,7 @@ namespace detail { inline std::string exception_type_name() { #if defined(CPPTRACE_HAS_CXX_EXCEPTION_TYPE) && (IS_LIBSTDCXX || IS_LIBCXX) const std::type_info* t = abi::__cxa_current_exception_type(); - return t ? detail::demangle(t->name()) : ""; + return t ? detail::demangle(t->name(), false) : ""; #else return ""; #endif diff --git a/src/utils.cpp b/src/utils.cpp index 59af436..9182c97 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -12,7 +12,7 @@ namespace cpptrace { std::string demangle(const std::string& name) { - return detail::demangle(name); + return detail::demangle(name, false); } std::string get_snippet(const std::string& path, std::size_t line, std::size_t context_size, bool color) { diff --git a/tools/resolver/main.cpp b/tools/resolver/main.cpp index cb7da68..1670ead 100644 --- a/tools/resolver/main.cpp +++ b/tools/resolver/main.cpp @@ -26,7 +26,7 @@ void resolve(const std::filesystem::path& path, cpptrace::frame_ptr address) { if(trace.size() != 1) { throw std::runtime_error("Something went wrong, trace vector size didn't match"); } - trace[0].symbol = cpptrace::detail::demangle(trace[0].symbol); + trace[0].symbol = cpptrace::demangle(trace[0].symbol); formatter.print(trace[0]); std::cout<