Skip to content

Commit

Permalink
[lldb] Enable Rust v0 symbol demangling
Browse files Browse the repository at this point in the history
Rust's v0 name mangling scheme [1] is easy to disambiguate from other
name mangling schemes because symbols always start with `_R`. The llvm
Demangle library supports demangling the Rust v0 scheme. Use it to
demangle Rust symbols.

Added unit tests that check simple symbols. Ran LLDB built with this
patch to debug some Rust programs compiled with the v0 name mangling
scheme. Confirmed symbol names were demangled as expected.

Note: enabling the new name mangling scheme requires a nightly
toolchain:

```
$ cat main.rs
fn main() {
    println!("Hello world!");
}
$ $(rustup which --toolchain nightly rustc) -Z symbol-mangling-version=v0 main.rs -g
$ /home/asm/hacking/llvm/build/bin/lldb ./main --one-line 'b main.rs:2'
(lldb) target create "./main"
Current executable set to '/home/asm/hacking/llvm/rust/main' (x86_64).
(lldb) b main.rs:2
Breakpoint 1: where = main`main::main + 4 at main.rs:2:5, address = 0x00000000000076a4
(lldb) r
Process 948449 launched: '/home/asm/hacking/llvm/rust/main' (x86_64)
warning: (x86_64) /lib64/libgcc_s.so.1 No LZMA support found for reading .gnu_debugdata section
Process 948449 stopped
* thread #1, name = 'main', stop reason = breakpoint 1.1
    frame #0: 0x000055555555b6a4 main`main::main at main.rs:2:5
   1    fn main() {
-> 2        println!("Hello world!");
   3    }
(lldb) bt
error: need to add support for DW_TAG_base_type '()' encoded with DW_ATE = 0x7, bit_size = 0
* thread #1, name = 'main', stop reason = breakpoint 1.1
  * frame #0: 0x000055555555b6a4 main`main::main at main.rs:2:5
    frame #1: 0x000055555555b78b main`<fn() as core::ops::function::FnOnce<()>>::call_once((null)=(main`main::main at main.rs:1), (null)=<unavailable>) at function.rs:227:5
    frame rust-lang#2: 0x000055555555b66e main`std::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>(f=(main`main::main at main.rs:1)) at backtrace.rs:125:18
    frame rust-lang#3: 0x000055555555b851 main`std::rt::lang_start::<()>::{closure#0} at rt.rs:49:18
    frame rust-lang#4: 0x000055555556c9f9 main`std::rt::lang_start_internal::hc51399759a90501a [inlined] core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::h04259e4a34d07c2f at function.rs:259:13
    frame rust-lang#5: 0x000055555556c9f2 main`std::rt::lang_start_internal::hc51399759a90501a [inlined] std::panicking::try::do_call::hb8da45704d5cfbbf at panicking.rs:401:40
    frame rust-lang#6: 0x000055555556c9f2 main`std::rt::lang_start_internal::hc51399759a90501a [inlined] std::panicking::try::h4beadc19a78fec52 at panicking.rs:365:19
    frame rust-lang#7: 0x000055555556c9f2 main`std::rt::lang_start_internal::hc51399759a90501a [inlined] std::panic::catch_unwind::hc58016cd36ba81a4 at panic.rs:433:14
    frame rust-lang#8: 0x000055555556c9f2 main`std::rt::lang_start_internal::hc51399759a90501a at rt.rs:34:21
    frame rust-lang#9: 0x000055555555b830 main`std::rt::lang_start::<()>(main=(main`main::main at main.rs:1), argc=1, argv=0x00007fffffffcb18) at rt.rs:48:5
    frame rust-lang#10: 0x000055555555b6fc main`main + 28
    frame rust-lang#11: 0x00007ffff73f2493 libc.so.6`__libc_start_main + 243
    frame rust-lang#12: 0x000055555555b59e main`_start + 46
(lldb)
```

[1]: rust-lang/rust#60705

Reviewed By: clayborg, teemperor

Differential Revision: https://reviews.llvm.org/D104054
  • Loading branch information
asm89 authored and Teemperor committed Jun 21, 2021
1 parent 9699442 commit 0a2d4f3
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
3 changes: 2 additions & 1 deletion lldb/include/lldb/Core/Mangled.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class Mangled {
enum ManglingScheme {
eManglingSchemeNone = 0,
eManglingSchemeMSVC,
eManglingSchemeItanium
eManglingSchemeItanium,
eManglingSchemeRustV0
};

/// Default constructor.
Expand Down
23 changes: 23 additions & 0 deletions lldb/source/Core/Mangled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ Mangled::ManglingScheme Mangled::GetManglingScheme(llvm::StringRef const name) {
if (name.startswith("?"))
return Mangled::eManglingSchemeMSVC;

if (name.startswith("_R"))
return Mangled::eManglingSchemeRustV0;

if (name.startswith("_Z"))
return Mangled::eManglingSchemeItanium;

Expand Down Expand Up @@ -199,6 +202,19 @@ static char *GetItaniumDemangledStr(const char *M) {
return demangled_cstr;
}

static char *GetRustV0DemangledStr(const char *M) {
char *demangled_cstr = llvm::rustDemangle(M, nullptr, nullptr, nullptr);

if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
if (demangled_cstr && demangled_cstr[0])
LLDB_LOG(log, "demangled rustv0: {0} -> \"{1}\"", M, demangled_cstr);
else
LLDB_LOG(log, "demangled rustv0: {0} -> error: failed to demangle", M);
}

return demangled_cstr;
}

// Explicit demangling for scheduled requests during batch processing. This
// makes use of ItaniumPartialDemangler's rich demangle info
bool Mangled::DemangleWithRichManglingInfo(
Expand Down Expand Up @@ -256,6 +272,10 @@ bool Mangled::DemangleWithRichManglingInfo(
return context.FromCxxMethodName(m_demangled);
}
}

case eManglingSchemeRustV0:
// Rich demangling scheme is not supported for Rust
return false;
}
llvm_unreachable("Fully covered switch above!");
}
Expand Down Expand Up @@ -284,6 +304,9 @@ ConstString Mangled::GetDemangledName() const {
demangled_name = GetItaniumDemangledStr(mangled_name);
break;
}
case eManglingSchemeRustV0:
demangled_name = GetRustV0DemangledStr(mangled_name);
break;
case eManglingSchemeNone:
llvm_unreachable("eManglingSchemeNone was handled already");
}
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Symbol/Symtab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ static bool lldb_skip_name(llvm::StringRef mangled,
case Mangled::eManglingSchemeMSVC:
return false;

// No filters for this scheme yet. Include all names in indexing.
case Mangled::eManglingSchemeRustV0:
return false;

// Don't try and demangle things we can't categorize.
case Mangled::eManglingSchemeNone:
return true;
Expand Down
17 changes: 17 additions & 0 deletions lldb/unittests/Core/MangledTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ TEST(MangledTest, EmptyForInvalidName) {
EXPECT_STREQ("", TheDemangled.GetCString());
}

TEST(MangledTest, ResultForValidRustV0Name) {
ConstString mangled_name("_RNvC1a4main");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();

ConstString expected_result("a::main");
EXPECT_STREQ(expected_result.GetCString(), the_demangled.GetCString());
}

TEST(MangledTest, EmptyForInvalidRustV0Name) {
ConstString mangled_name("_RRR");
Mangled the_mangled(mangled_name);
ConstString the_demangled = the_mangled.GetDemangledName();

EXPECT_STREQ("", the_demangled.GetCString());
}

TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>
subsystems;
Expand Down

0 comments on commit 0a2d4f3

Please sign in to comment.