diff --git a/folly/Demangle.cpp b/folly/Demangle.cpp index 2a5c9f7ad2d..08df6d69a73 100644 --- a/folly/Demangle.cpp +++ b/folly/Demangle.cpp @@ -256,6 +256,19 @@ size_t demangle(const char* name, char* out, size_t outSize) { } } + // fallback to cxxabi if available + if (cxxabi_demangle) { + int status; + size_t len = outSize; + // Use the provided buffer instead of allocating + char* demangled = cxxabi_demangle(name, out, &len, &status); + if (status == 0 && demangled == out) { + // Successfully demangled into the provided buffer + return strlen(out); + } + // If demangling failed or allocated (shouldn't happen), fall through + } + // fallback - just return original return folly::strlcpy(out, name, outSize); } diff --git a/folly/Demangle.h b/folly/Demangle.h index 521f7dd3210..95c24a9383e 100644 --- a/folly/Demangle.h +++ b/folly/Demangle.h @@ -59,11 +59,10 @@ inline fbstring demangle(const std::type_info& type) { * * This function does not allocate memory and is async-signal-safe. * - * Note that the underlying function for the fbstring-returning demangle is - * somewhat standard (abi::__cxa_demangle, which uses malloc), the underlying - * function for this version is less so (cplus_demangle_v3_callback from - * libiberty), so it is possible for the fbstring version to work, while this - * version returns the original, mangled name. + * This function tries libiberty first (cplus_demangle_v3_callback), then falls + * back to cxxabi (abi::__cxa_demangle with the provided buffer) if libiberty + * is not available. If neither is available, it returns the original mangled + * name. */ size_t demangle(const char* name, char* out, size_t outSize); inline size_t demangle(const std::type_info& type, char* buf, size_t bufSize) { diff --git a/folly/test/DemangleTest.cpp b/folly/test/DemangleTest.cpp index 29023d8a54c..d9a1edcce24 100644 --- a/folly/test/DemangleTest.cpp +++ b/folly/test/DemangleTest.cpp @@ -41,8 +41,10 @@ TEST_F(DemangleTest, demangle_return_string) { TEST_F(DemangleTest, demangle_to_buffer) { using type = folly_test::ThisIsAVeryLongStructureName; auto const raw = typeid(type).name(); - auto const expected = - demangle_build_has_liberty() ? pretty_name() : raw; + // Buffer-based demangle now falls back to cxxabi if liberty is not available + auto const expected = (demangle_build_has_liberty() || demangle_build_has_cxxabi()) + ? pretty_name() + : raw; { std::vector buf; @@ -69,7 +71,10 @@ TEST_F(DemangleTest, demangle_long_symbol) { EXPECT_EQ(std::string(choice), demangle(raw).toStdString()); - auto const expected = demangle_build_has_liberty() ? choice : raw; + // Buffer-based demangle now falls back to cxxabi if liberty is not available + auto const expected = + (demangle_build_has_liberty() || demangle_build_has_cxxabi()) ? choice + : raw; constexpr size_t size = 15; std::vector buf; buf.resize(1 + size);