From 2ecb2baba829a7ed4fff4bc60edf0c1643dc129c Mon Sep 17 00:00:00 2001 From: Ted Mielczarek Date: Mon, 24 Oct 2016 15:16:28 -0400 Subject: Don't demangle Rust symbols by default, but allow linking to rust-demangle. The Rust compiler uses GCC C++ name mangling, but it has another layer of encoding so abi::cxa_demangle doesn't produce great results. This patch changes dump_syms to dump unmangled names by default so that consumers can demangle them after-the-fact. It also adds a tiny bit of support for linking against a Rust library I wrote that can demangle Rust symbols nicely: https://github.com/luser/rust-demangle-capi BUG= Change-Id: I63a425035ebb7ac516f067fed2aa782849ea9604 Reviewed-on: https://chromium-review.googlesource.com/402308 Reviewed-by: Mark Mentovai --- src/common/dwarf/dwarf2enums.h | 1 + src/common/dwarf_cu_to_module.cc | 4 +++ src/common/dwarf_cu_to_module_unittest.cc | 48 +++++++++++++++++++++++++++++++ src/common/language.cc | 39 +++++++++++++++++++++++++ src/common/language.h | 1 + 5 files changed, 93 insertions(+) (limited to 'src') diff --git a/src/common/dwarf/dwarf2enums.h b/src/common/dwarf/dwarf2enums.h index 09567555..4316a89c 100644 --- a/src/common/dwarf/dwarf2enums.h +++ b/src/common/dwarf/dwarf2enums.h @@ -544,6 +544,7 @@ enum DwarfLanguage DW_LANG_ObjC_plus_plus =0x0011, DW_LANG_UPC =0x0012, DW_LANG_D =0x0013, + DW_LANG_Rust =0x001c, DW_LANG_Swift =0x001e, // Implementation-defined language code range. DW_LANG_lo_user = 0x8000, diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc index 100f3962..8d874366 100644 --- a/src/common/dwarf_cu_to_module.cc +++ b/src/common/dwarf_cu_to_module.cc @@ -777,6 +777,10 @@ void DwarfCUToModule::SetLanguage(DwarfLanguage language) { cu_context_->language = Language::Swift; break; + case dwarf2reader::DW_LANG_Rust: + cu_context_->language = Language::Rust; + break; + // DWARF has no generic language code for assembly language; this is // what the GNU toolchain uses. case dwarf2reader::DW_LANG_Mips_Assembler: diff --git a/src/common/dwarf_cu_to_module_unittest.cc b/src/common/dwarf_cu_to_module_unittest.cc index e789f9da..2ce4a609 100644 --- a/src/common/dwarf_cu_to_module_unittest.cc +++ b/src/common/dwarf_cu_to_module_unittest.cc @@ -1205,6 +1205,7 @@ TEST_F(Specifications, Function) { } TEST_F(Specifications, MangledName) { + // Language defaults to C++, so no need to set it here. PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); StartCU(); @@ -1221,6 +1222,53 @@ TEST_F(Specifications, MangledName) { 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); } +TEST_F(Specifications, MangledNameSwift) { + // Swift mangled names should pass through untouched. + SetLanguage(dwarf2reader::DW_LANG_Swift); + PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); + StartCU(); + const string kName = "_TFC9swifttest5Shape17simpleDescriptionfS0_FT_Si"; + DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, + dwarf2reader::DW_TAG_subprogram, "declaration-name", + kName); + DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, + 0xcd3c51b946fb1eeeLL, "", + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); + root_handler_.Finish(); + + TestFunctionCount(1); + TestFunction(0, kName, + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); +} + +TEST_F(Specifications, MangledNameRust) { + SetLanguage(dwarf2reader::DW_LANG_Rust); + PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661); + + StartCU(); + const string kName = "_ZN14rustc_demangle8demangle17h373defa94bffacdeE"; + DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL, + dwarf2reader::DW_TAG_subprogram, "declaration-name", + kName); + DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram, + 0xcd3c51b946fb1eeeLL, "", + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); + root_handler_.Finish(); + + TestFunctionCount(1); + TestFunction(0, +#ifndef HAVE_RUST_DEMANGLE + // Rust mangled names should pass through untouched if not + // using rust-demangle. + kName, +#else + // If rust-demangle is available this should be properly + // demangled. + "rustc_demangle::demangle", +#endif + 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL); +} + TEST_F(Specifications, MemberFunction) { PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691); diff --git a/src/common/language.cc b/src/common/language.cc index 087395e9..09eaceb6 100644 --- a/src/common/language.cc +++ b/src/common/language.cc @@ -40,6 +40,10 @@ #include #endif +#if defined(HAVE_RUST_DEMANGLE) +#include +#endif + #include namespace { @@ -136,6 +140,40 @@ class SwiftLanguage: public Language { SwiftLanguage SwiftLanguageSingleton; +// Rust language-specific operations. +class RustLanguage: public Language { + public: + RustLanguage() {} + + string MakeQualifiedName(const string &parent_name, + const string &name) const { + return MakeQualifiedNameWithSeparator(parent_name, ".", name); + } + + virtual DemangleResult DemangleName(const string& mangled, + std::string* demangled) const { + // Rust names use GCC C++ name mangling, but demangling them with + // abi_demangle doesn't produce stellar results due to them having + // another layer of encoding. + // If callers provide rustc-demangle, use that. +#if defined(HAVE_RUST_DEMANGLE) + char* rust_demangled = rust_demangle(mangled.c_str()); + if (rust_demangled == nullptr) { + return kDemangleFailure; + } + demangled->assign(rust_demangled); + free_rust_demangled_name(rust_demangled); +#else + // Otherwise, pass through the mangled name so callers can demangle + // after the fact. + demangled->assign(mangled); +#endif + return kDemangleSuccess; + } +}; + +RustLanguage RustLanguageSingleton; + // Assembler language-specific operations. class AssemblerLanguage: public Language { public: @@ -153,6 +191,7 @@ AssemblerLanguage AssemblerLanguageSingleton; const Language * const Language::CPlusPlus = &CPPLanguageSingleton; const Language * const Language::Java = &JavaLanguageSingleton; const Language * const Language::Swift = &SwiftLanguageSingleton; +const Language * const Language::Rust = &RustLanguageSingleton; const Language * const Language::Assembler = &AssemblerLanguageSingleton; } // namespace google_breakpad diff --git a/src/common/language.h b/src/common/language.h index 05786199..4ebea1ab 100644 --- a/src/common/language.h +++ b/src/common/language.h @@ -96,6 +96,7 @@ class Language { static const Language * const CPlusPlus, * const Java, * const Swift, + * const Rust, * const Assembler; }; -- cgit v1.2.1