From 46aab00b2fb19c1815a8faf42b866f0d9374fd3d Mon Sep 17 00:00:00 2001 From: Jan Michael Auer Date: Tue, 7 Apr 2020 20:00:31 +0200 Subject: [PATCH] Support multiple clone suffixes --- build.rs | 1 + src/ast.rs | 58 +++++++++++++++++++++++++++----------------------- tests/tests.rs | 11 ++++++++++ 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/build.rs b/build.rs index 6d07843..3737b74 100644 --- a/build.rs +++ b/build.rs @@ -149,6 +149,7 @@ use std::fmt::Write; s.extend(149..154); s.extend(158..168); s.extend(169..175); + s.extend(176..177); s.extend(177..180); s.extend(181..183); s.extend(184..186); diff --git a/src/ast.rs b/src/ast.rs index 16ad0ae..26ae9b5 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1303,7 +1303,7 @@ macro_rules! define_vocabulary { #[derive(Clone, Debug, PartialEq, Eq)] pub enum MangledName { /// The encoding of the mangled symbol name. - Encoding(Encoding, Option), + Encoding(Encoding, Vec), /// A top-level type. Technically not allowed by the standard, however in /// practice this can happen, and is tested for by libiberty. @@ -1325,12 +1325,8 @@ impl Parse for MangledName { if let Ok(tail) = consume(b"_Z", input).or_else(|_| consume(b"__Z", input)) { let (encoding, tail) = Encoding::parse(ctx, subs, tail)?; - if let Ok((clone_suffix, tail)) = CloneSuffix::parse(ctx, subs, tail) { - return Ok((MangledName::Encoding(encoding, Some(clone_suffix)), tail)); - } - else { - return Ok((MangledName::Encoding(encoding, None), tail)); - } + let (clone_suffixes, tail) = zero_or_more(ctx, subs, tail)?; + return Ok((MangledName::Encoding(encoding, clone_suffixes), tail)); } if let Ok(tail) = consume(b"_GLOBAL_", input) { @@ -1359,8 +1355,10 @@ where match *self { MangledName::Encoding(ref enc, ref cs) => { enc.demangle(ctx, scope)?; - if let Some(clone_suffix) = cs { - clone_suffix.demangle(ctx, scope)?; + if !cs.is_empty() { + for clone_suffix in cs { + clone_suffix.demangle(ctx, scope)?; + } } Ok(()) }, @@ -1514,7 +1512,7 @@ where /// ::= [ . ] [ . ]* #[derive(Clone, Debug, PartialEq, Eq)] -pub struct CloneSuffix(CloneTypeIdentifier, isize); +pub struct CloneSuffix(CloneTypeIdentifier, Vec); impl Parse for CloneSuffix { fn parse<'a, 'b>( @@ -1525,16 +1523,18 @@ impl Parse for CloneSuffix { try_begin_parse!("CloneSuffix", ctx, input); let tail = consume(b".", input)?; - let (identifier, tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?; + let (identifier, mut tail) = CloneTypeIdentifier::parse(ctx, subs, tail)?; if tail.is_empty() { return Err(error::Error::UnexpectedText); } - let tail = consume(b".", tail)?; - - let (nonnegative, tail) = parse_number(10, false, tail)?; + let mut numbers = Vec::with_capacity(1); + while let Ok((n, t)) = consume(b".", tail).and_then(|t| parse_number(10, false, t)) { + numbers.push(n); + tail = t; + } - let clone_suffix = CloneSuffix(identifier, nonnegative); + let clone_suffix = CloneSuffix(identifier, numbers); Ok((clone_suffix, tail)) } } @@ -1549,8 +1549,12 @@ where scope: Option>, ) -> fmt::Result { let ctx = try_begin_demangle!(self, ctx, scope); + write!(ctx, " [clone")?; self.0.demangle(ctx, scope)?; - write!(ctx, ".{}]", self.1)?; + for nonnegative in &self.1 { + write!(ctx, ".{}", nonnegative)?; + } + write!(ctx, "]")?; Ok(()) } } @@ -2799,7 +2803,7 @@ where let source_name = String::from_utf8_lossy(ident); ctx.set_source_name(self.start, self.end); - write!(ctx, " [clone .{}", source_name)?; + write!(ctx, " .{}", source_name)?; Ok(()) } } @@ -7791,7 +7795,7 @@ mod tests { SourceName(Identifier { start: 3, end: 6, - }))))), None), + }))))), Vec::new()), b"..." } b"_GLOBAL__I__Z3foo..." => { @@ -7807,7 +7811,7 @@ mod tests { Identifier { start: 14, end: 17, - }))))), None)))), + }))))), Vec::new())))), b"..." } } @@ -7891,7 +7895,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } b".I__Z3foo..." => { @@ -7906,7 +7910,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } b"$I__Z3foo..." => { @@ -7921,7 +7925,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } b"_D__Z3foo..." => { @@ -7936,7 +7940,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } b".D__Z3foo..." => { @@ -7951,7 +7955,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } b"$D__Z3foo..." => { @@ -7966,7 +7970,7 @@ mod tests { Identifier { start: 6, end: 9, - }))))), None))), + }))))), Vec::new()))), b"..." } } @@ -9597,7 +9601,7 @@ mod tests { SourceName(Identifier { start: 4, end: 7, - }))))), None))), + }))))), Vec::new()))), b"...", [] } @@ -9979,7 +9983,7 @@ mod tests { SourceName(Identifier { start: 4, end: 7, - }))))), None)), + }))))), Vec::new())), b"...", [] } diff --git a/tests/tests.rs b/tests/tests.rs index e1765da..6b6f781 100755 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -479,6 +479,17 @@ demangles!( "_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPcEEvT_S7_St20forward_iterator_tag.isra.90", "void std::__cxx11::basic_string, std::allocator >::_M_construct(char*, char*, std::forward_iterator_tag) [clone .isra.90]" ); +demangles!( + multiple_clone_suffixes, + "_ZN15google_breakpad17ProcCpuInfoReader14GetValueAndLenEPm.isra.20.part.21", + "google_breakpad::ProcCpuInfoReader::GetValueAndLen(unsigned long*) [clone .isra.20] [clone .part.21]" +); +// Taken from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40831 +demangles!( + multiple_clone_numbers, + "_Z3fooi.part.9.165493.constprop.775.31805", + "foo(int) [clone .part.9.165493] [clone .constprop.775.31805]" +); demangles!( _Z1fDpDv1_c, "f(char __vector(1)...)"