libiberty rust-demangle, ignore .suffix

Rust symbols can have a .suffix because of compiler transformations.
These can be ignored in the demangled name. Which is what this patch
implements. By stopping at the first dot for v0 symbols and searching
backwards to the ending 'E' for legacy symbols.

An alternative implementation could be to follow what C++ does and
represent these as [clone .suffix] tagged onto the demangled name.
But this seems somewhat confusing since it results in a demangled
name that cannot be mangled again. And it would mean trying to
decode compiler internal naming.

https://bugs.kde.org/show_bug.cgi?id=445916
https://github.com/rust-lang/rust/issues/60705

libiberty/Changelog

	* rust-demangle.c (rust_demangle_callback): Ignore everything
	after '.' char in sym for v0. For legacy symbols search
	backwards to find the last 'E' before any '.'.
	* testsuite/rust-demangle-expected: Add new .suffix testcases.
This commit is contained in:
Mark Wielaard 2021-12-02 18:00:39 +01:00
parent db69f666a7
commit d3b2ead595
2 changed files with 44 additions and 3 deletions

View File

@ -1375,13 +1375,19 @@ rust_demangle_callback (const char *mangled, int options,
/* Rust symbols (v0) use only [_0-9a-zA-Z] characters. */
for (p = rdm.sym; *p; p++)
{
/* Rust v0 symbols can have '.' suffixes, ignore those. */
if (rdm.version == 0 && *p == '.')
break;
rdm.sym_len++;
if (*p == '_' || ISALNUM (*p))
continue;
/* Legacy Rust symbols can also contain [.:$] characters. */
if (rdm.version == -1 && (*p == '$' || *p == '.' || *p == ':'))
/* Legacy Rust symbols can also contain [.:$] characters.
Or @ in the .suffix (which will be skipped, see below). */
if (rdm.version == -1 && (*p == '$' || *p == '.' || *p == ':'
|| *p == '@'))
continue;
return 0;
@ -1390,7 +1396,16 @@ rust_demangle_callback (const char *mangled, int options,
/* Legacy Rust symbols need to be handled separately. */
if (rdm.version == -1)
{
/* Legacy Rust symbols always end with E. */
/* Legacy Rust symbols always end with E. But can be followed by a
.suffix (which we want to ignore). */
int dot_suffix = 1;
while (rdm.sym_len > 0 &&
!(dot_suffix && rdm.sym[rdm.sym_len - 1] == 'E'))
{
dot_suffix = rdm.sym[rdm.sym_len - 1] == '.';
rdm.sym_len--;
}
if (!(rdm.sym_len > 0 && rdm.sym[rdm.sym_len - 1] == 'E'))
return 0;
rdm.sym_len--;

View File

@ -295,3 +295,29 @@ _RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E
--format=auto
_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO
<const_generic::Foo<_>>::foo::FOO
#
# Suffixes
#
--format=rust
_RNvMs0_NtCs5l0EXMQXRMU_21rustc_data_structures17obligation_forestINtB5_16ObligationForestNtNtNtCsdozMG8X9FIu_21rustc_trait_selection6traits7fulfill26PendingPredicateObligationE22register_obligation_atB1v_.llvm.8517020237817239694
<rustc_data_structures::obligation_forest::ObligationForest<rustc_trait_selection::traits::fulfill::PendingPredicateObligation>>::register_obligation_at
--format=rust
_ZN4core3ptr85drop_in_place$LT$std..rt..lang_start$LT$$LP$$RP$$GT$..$u7b$$u7b$closure$u7d$$u7d$$GT$17h27f14859c664490dE.llvm.8091179795805947855
core::ptr::drop_in_place<std::rt::lang_start<()>::{{closure}}>
# old style rustc llvm thinlto
--format=rust
_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9
backtrace::foo
--format=rust
_ZN9backtrace3foo17hbb467fcdaea5d79bE.llvm.A5310EB9@@16
backtrace::foo
# new style rustc llvm thinlto
--format=rust
_RC3foo.llvm.9D1C9369
foo
--format=rust
_RC3foo.llvm.9D1C9369@@16
foo
--format=rust
_RNvC9backtrace3foo.llvm.A5310EB9
backtrace::foo