Commit 6ab667fd by Abseil Team Committed by Copybara-Service

Add an internal wrapper for `abi::__cxa_demangle()`.

PiperOrigin-RevId: 568665135
Change-Id: I42ec9bc6cfe923777f7b60ea032c7b64428493c9
parent cced061b
...@@ -864,19 +864,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ...@@ -864,19 +864,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_INTERNAL_HAS_RTTI 1 #define ABSL_INTERNAL_HAS_RTTI 1
#endif #endif
// `ABSL_INTERNAL_HAS_CXA_DEMANGLE` determines whether `abi::__cxa_demangle` is
// available.
#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
#error ABSL_INTERNAL_HAS_CXA_DEMANGLE cannot be directly set
#elif defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 0
#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
!defined(__mips__)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
#elif defined(__clang__) && !defined(_MSC_VER)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
#endif
// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support. // ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of // See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets. // which architectures support the various x86 instruction sets.
......
...@@ -731,7 +731,6 @@ cc_library( ...@@ -731,7 +731,6 @@ cc_library(
deps = [ deps = [
"//absl/base:config", "//absl/base:config",
"//absl/base:core_headers", "//absl/base:core_headers",
"//absl/debugging:demangle_internal",
"//absl/meta:type_traits", "//absl/meta:type_traits",
"//absl/strings", "//absl/strings",
"//absl/types:span", "//absl/types:span",
......
...@@ -777,7 +777,6 @@ absl_cc_library( ...@@ -777,7 +777,6 @@ absl_cc_library(
DEPS DEPS
absl::config absl::config
absl::core_headers absl::core_headers
absl::debugging_internal
absl::meta absl::meta
absl::strings absl::strings
absl::span absl::span
......
...@@ -172,7 +172,6 @@ ...@@ -172,7 +172,6 @@
#include <utility> #include <utility>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/debugging/internal/demangle.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/types/span.h" #include "absl/types/span.h"
...@@ -182,6 +181,14 @@ ...@@ -182,6 +181,14 @@
#include <sanitizer/asan_interface.h> #include <sanitizer/asan_interface.h>
#endif #endif
#if defined(__GXX_RTTI)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE
#endif
#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
#include <cxxabi.h>
#endif
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace container_internal { namespace container_internal {
...@@ -287,9 +294,19 @@ constexpr size_t Max(size_t a, size_t b, Ts... rest) { ...@@ -287,9 +294,19 @@ constexpr size_t Max(size_t a, size_t b, Ts... rest) {
template <class T> template <class T>
std::string TypeName() { std::string TypeName() {
std::string out; std::string out;
absl::StrAppend(&out, "<", int status = 0;
absl::debugging_internal::DemangleString(typeid(T).name()), char* demangled = nullptr;
">"); #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
#endif
if (status == 0 && demangled != nullptr) { // Demangling succeeded.
absl::StrAppend(&out, "<", demangled, ">");
free(demangled);
} else {
#if defined(__GXX_RTTI) || defined(_CPPRTTI)
absl::StrAppend(&out, "<", typeid(T).name(), ">");
#endif
}
return out; return out;
} }
......
...@@ -217,10 +217,7 @@ cc_library( ...@@ -217,10 +217,7 @@ cc_library(
hdrs = ["internal/demangle.h"], hdrs = ["internal/demangle.h"],
copts = ABSL_DEFAULT_COPTS, copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS, linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [ visibility = ["//visibility:private"],
"//absl/container:__pkg__",
"//absl/debugging:__pkg__",
],
deps = [ deps = [
"//absl/base", "//absl/base",
"//absl/base:config", "//absl/base:config",
......
...@@ -21,15 +21,7 @@ ...@@ -21,15 +21,7 @@
#include <cstdint> #include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstdlib>
#include <limits> #include <limits>
#include <string>
#include "absl/base/config.h"
#if ABSL_INTERNAL_HAS_CXA_DEMANGLE
#include <cxxabi.h>
#endif
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -1991,22 +1983,6 @@ bool Demangle(const char* mangled, char* out, size_t out_size) { ...@@ -1991,22 +1983,6 @@ bool Demangle(const char* mangled, char* out, size_t out_size) {
state.parse_state.out_cur_idx > 0; state.parse_state.out_cur_idx > 0;
} }
std::string DemangleString(const char* mangled) {
std::string out;
int status = 0;
char* demangled = nullptr;
#if ABSL_INTERNAL_HAS_CXA_DEMANGLE
demangled = abi::__cxa_demangle(mangled, nullptr, nullptr, &status);
#endif
if (status == 0 && demangled != nullptr) {
out.append(demangled);
free(demangled);
} else {
out.append(mangled);
}
return out;
}
} // namespace debugging_internal } // namespace debugging_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
...@@ -12,23 +12,13 @@ ...@@ -12,23 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ // An async-signal-safe and thread-safe demangler for Itanium C++ ABI
#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ // (aka G++ V3 ABI).
#include <string>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Demangle `mangled`. On success, return true and write the
// demangled symbol name to `out`. Otherwise, return false.
// `out` is modified even if demangling is unsuccessful.
// //
// This function provides an alternative to libstdc++'s abi::__cxa_demangle, // The demangler is implemented to be used in async signal handlers to
// which is not async signal safe (it uses malloc internally). It's intended to // symbolize stack traces. We cannot use libstdc++'s
// be used in async signal handlers to symbolize stack traces. // abi::__cxa_demangle() in such signal handlers since it's not async
// signal safe (it uses malloc() internally).
// //
// Note that this demangler doesn't support full demangling. More // Note that this demangler doesn't support full demangling. More
// specifically, it doesn't print types of function parameters and // specifically, it doesn't print types of function parameters and
...@@ -40,31 +30,39 @@ namespace debugging_internal { ...@@ -40,31 +30,39 @@ namespace debugging_internal {
// //
// Example: // Example:
// //
// | Mangled Name | Demangle | DemangleString // | Mangled Name | The Demangler | abi::__cxa_demangle()
// |---------------|-------------|----------------------- // |---------------|---------------|-----------------------
// | _Z1fv | f() | f() // | _Z1fv | f() | f()
// | _Z1fi | f() | f(int) // | _Z1fi | f() | f(int)
// | _Z3foo3bar | foo() | foo(bar) // | _Z3foo3bar | foo() | foo(bar)
// | _Z1fIiEvi | f<>() | void f<int>(int) // | _Z1fIiEvi | f<>() | void f<int>(int)
// | _ZN1N1fE | N::f | N::f // | _ZN1N1fE | N::f | N::f
// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar() // | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
// | _Zrm1XS_" | operator%() | operator%(X, X) // | _Zrm1XS_" | operator%() | operator%(X, X)
// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo() // | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
// | _Z1fSs | f() | f(std::basic_string<char, // | _Z1fSs | f() | f(std::basic_string<char,
// | | | std::char_traits<char>, // | | | std::char_traits<char>,
// | | | std::allocator<char> >) // | | | std::allocator<char> >)
// //
// See the unit test for more examples. // See the unit test for more examples.
// //
// Note: we might want to write demanglers for ABIs other than Itanium // Note: we might want to write demanglers for ABIs other than Itanium
// C++ ABI in the future. // C++ ABI in the future.
bool Demangle(const char* mangled, char* out, size_t out_size);
// A wrapper around `abi::__cxa_demangle()`. On success, returns the demangled
// name. On failure, returns the input mangled name.
// //
// This function is not async-signal-safe.
std::string DemangleString(const char* mangled); #ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Demangle `mangled`. On success, return true and write the
// demangled symbol name to `out`. Otherwise, return false.
// `out` is modified even if demangling is unsuccessful.
bool Demangle(const char* mangled, char* out, size_t out_size);
} // namespace debugging_internal } // namespace debugging_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
#include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/debugging/internal/stack_consumption.h" #include "absl/debugging/internal/stack_consumption.h"
...@@ -29,8 +28,6 @@ ABSL_NAMESPACE_BEGIN ...@@ -29,8 +28,6 @@ ABSL_NAMESPACE_BEGIN
namespace debugging_internal { namespace debugging_internal {
namespace { namespace {
using ::testing::ContainsRegex;
// A wrapper function for Demangle() to make the unit test simple. // A wrapper function for Demangle() to make the unit test simple.
static const char *DemangleIt(const char * const mangled) { static const char *DemangleIt(const char * const mangled) {
static char demangled[4096]; static char demangled[4096];
...@@ -240,25 +237,6 @@ TEST(DemangleRegression, DeeplyNestedArrayType) { ...@@ -240,25 +237,6 @@ TEST(DemangleRegression, DeeplyNestedArrayType) {
TestOnInput(data.c_str()); TestOnInput(data.c_str());
} }
struct Base {
virtual ~Base() = default;
};
struct Derived : public Base {};
TEST(DemangleStringTest, SupportsSymbolNameReturnedByTypeId) {
EXPECT_EQ(DemangleString(typeid(int).name()), "int");
// We want to test that `DemangleString` can demangle the symbol names
// returned by `typeid`, but without hard-coding the actual demangled values
// (because they are platform-specific).
EXPECT_THAT(
DemangleString(typeid(Base).name()),
ContainsRegex("absl.*debugging_internal.*anonymous namespace.*::Base"));
EXPECT_THAT(DemangleString(typeid(Derived).name()),
ContainsRegex(
"absl.*debugging_internal.*anonymous namespace.*::Derived"));
}
} // namespace } // namespace
} // namespace debugging_internal } // namespace debugging_internal
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment