diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d77271c3..5ac816f0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,8 @@ int main(void) } " HAVE___SYNC_VAL_COMPARE_AND_SWAP) +check_cxx_symbol_exists (abi::__cxa_demangle cxxabi.h HAVE___CXA_DEMANGLE) + if (WITH_TLS) set (GLOG_THREAD_LOCAL_STORAGE 1) endif (WITH_TLS) @@ -576,6 +578,13 @@ if (BUILD_TESTING) target_link_libraries (demangle_unittest PRIVATE glog_test) + add_test (NAME demangle COMMAND demangle_unittest) + + if (HAVE___CXA_DEMANGLE) + # Demangle tests use a different (reduced) representation of symbols + set_tests_properties (demangle PROPERTIES DISABLED ON) + endif (HAVE___CXA_DEMANGLE) + if (HAVE_STACKTRACE) add_executable (stacktrace_unittest src/stacktrace_unittest.cc @@ -598,7 +607,6 @@ if (BUILD_TESTING) target_link_libraries (signalhandler_unittest PRIVATE glog_test) endif (HAVE_STACKTRACE AND HAVE_SYMBOLIZE) - add_test (NAME demangle COMMAND demangle_unittest) add_test (NAME logging COMMAND logging_unittest) set_tests_properties (logging PROPERTIES TIMEOUT 30) diff --git a/src/config.h.cmake.in b/src/config.h.cmake.in index 9b6c11629..430959539 100644 --- a/src/config.h.cmake.in +++ b/src/config.h.cmake.in @@ -118,4 +118,7 @@ /* Define if thread-local storage is enabled. */ #cmakedefine GLOG_THREAD_LOCAL_STORAGE +/* define if abi::__cxa_demangle is available in cxxabi.h */ +#cmakedefine HAVE___CXA_DEMANGLE + #endif // GLOG_CONFIG_H diff --git a/src/demangle.cc b/src/demangle.cc index 30204242a..b9ca47b30 100644 --- a/src/demangle.cc +++ b/src/demangle.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006, Google Inc. +// Copyright (c) 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -36,18 +36,24 @@ #include "demangle.h" +#include #include +#include #include #include "utilities.h" +#if defined(HAVE___CXA_DEMANGLE) +# include +#endif + #if defined(GLOG_OS_WINDOWS) # include #endif namespace google { -#if !defined(GLOG_OS_WINDOWS) +#if !defined(GLOG_OS_WINDOWS) && !defined(HAVE___CXA_DEMANGLE) namespace { struct AbbrevPair { const char* const abbrev; @@ -1334,6 +1340,18 @@ bool Demangle(const char* mangled, char* out, size_t out_size) { (void)out_size; return false; # endif +#elif defined(HAVE___CXA_DEMANGLE) + int status = -1; + std::size_t n = 0; + std::unique_ptr unmangled{ + abi::__cxa_demangle(mangled, nullptr, &n, &status), &std::free}; + + if (!unmangled) { + return false; + } + + std::copy_n(unmangled.get(), std::min(n, out_size), out); + return status == 0; #else State state; InitState(&state, mangled, out, out_size); diff --git a/src/symbolize_unittest.cc b/src/symbolize_unittest.cc index c6a03c9f1..2fc1277e6 100644 --- a/src/symbolize_unittest.cc +++ b/src/symbolize_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006, Google Inc. +// Copyright (c) 2024, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -146,7 +146,11 @@ void ATTRIBUTE_NOINLINE Foo::func(int x) { TEST(Symbolize, SymbolizeWithDemangling) { Foo::func(100); # if !defined(_MSC_VER) || !defined(NDEBUG) +# if defined(HAVE___CXA_DEMANGLE) + EXPECT_STREQ("Foo::func(int)", TrySymbolize((void*)(&Foo::func))); +# else EXPECT_STREQ("Foo::func()", TrySymbolize((void*)(&Foo::func))); +# endif # endif } # endif @@ -282,12 +286,14 @@ static const char* SymbolizeStackConsumption(void* pc, int* stack_consumed) { return g_symbolize_result; } -# ifdef __ppc64__ +# if !defined(HAVE___CXA_DEMANGLE) +# ifdef __ppc64__ // Symbolize stack consumption should be within 4kB. -const int kStackConsumptionUpperLimit = 4096; -# else +constexpr int kStackConsumptionUpperLimit = 4096; +# else // Symbolize stack consumption should be within 2kB. -const int kStackConsumptionUpperLimit = 2048; +constexpr int kStackConsumptionUpperLimit = 2048; +# endif # endif TEST(Symbolize, SymbolizeStackConsumption) { @@ -298,7 +304,9 @@ TEST(Symbolize, SymbolizeStackConsumption) { &stack_consumed); EXPECT_STREQ("nonstatic_func", symbol); EXPECT_GT(stack_consumed, 0); +# if !defined(HAVE___CXA_DEMANGLE) EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); +# endif // The name of an internal linkage symbol is not specified; allow either a // mangled or an unmangled name here. @@ -308,10 +316,12 @@ TEST(Symbolize, SymbolizeStackConsumption) { EXPECT_TRUE(strcmp("static_func", symbol) == 0 || strcmp("static_func()", symbol) == 0); EXPECT_GT(stack_consumed, 0); +# if !defined(HAVE___CXA_DEMANGLE) EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); +# endif } -# ifdef TEST_WITH_MODERN_GCC +# if defined(TEST_WITH_MODERN_GCC) && !defined(HAVE___CXA_DEMANGLE) TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) { Foo::func(100); int stack_consumed; @@ -320,7 +330,11 @@ TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) { symbol = SymbolizeStackConsumption(reinterpret_cast(&Foo::func), &stack_consumed); +# if defined(HAVE___CXA_DEMANGLE) + EXPECT_STREQ("Foo::func(int)", symbol); +# else EXPECT_STREQ("Foo::func()", symbol); +# endif EXPECT_GT(stack_consumed, 0); EXPECT_LT(stack_consumed, kStackConsumptionUpperLimit); }