.
This file is part of the libiberty library.
diff --git a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
index a02bd3981b..780b09b3a2 100644
--- a/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
+++ b/Ghidra/Features/Base/src/main/help/help/topics/AutoAnalysisPlugin/AutoAnalysis.htm
@@ -441,7 +441,7 @@
Use Deprecated Demangler -
By default, GCC symbols will be demangled using the most up-to-date demangler
- that Ghidra contains (version 2.33.1 as of this writing). Turning this
+ that Ghidra contains (version 2.41 as of this writing). Turning this
option on will invoke the now deprecated version of the demangler (version 2.24).
@@ -457,7 +457,7 @@
<GHIDRA_INSTALL_DIR>/GPL/DemanglerGnu/os/<OS>/
-
demangler_gnu_v2_33_1
+ demangler_gnu_v2_41
<GHIDRA_INSTALL_DIR>/GPL/DemanglerGnu/os/<OS>/
demangler_gnu_v2_24
diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java
index 7ba4275019..d68b3a8f6f 100644
--- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java
+++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerOptions.java
@@ -34,14 +34,15 @@ public class GnuDemanglerOptions extends DemanglerOptions {
public static final String GNU_DEMANGLER_V2_24 = "demangler_gnu_v2_24";
/**
- * Version 2.33.1 of the GNU demangler. This version supports less formats than older versions.
+ * Version 2.41 of the GNU demangler. This version supports less formats than
+ * {@link #GNU_DEMANGLER_V2_24}.
*/
- public static final String GNU_DEMANGLER_V2_33_1 = "demangler_gnu_v2_33_1";
+ public static final String GNU_DEMANGLER_V2_41 = "demangler_gnu_v2_41";
/**
* The default version to use of the GNU demangler
*/
- public static final String GNU_DEMANGLER_DEFAULT = GNU_DEMANGLER_V2_33_1;
+ public static final String GNU_DEMANGLER_DEFAULT = GNU_DEMANGLER_V2_41;
private final GnuDemanglerFormat format;
private final boolean isDeprecated;
@@ -112,7 +113,7 @@ public class GnuDemanglerOptions extends DemanglerOptions {
* @return the name
*/
public String getDemanglerName() {
- return isDeprecated ? GNU_DEMANGLER_V2_24 : GNU_DEMANGLER_V2_33_1;
+ return isDeprecated ? GNU_DEMANGLER_V2_24 : GNU_DEMANGLER_V2_41;
}
/**
diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java
index 5a66637191..f56bf27726 100644
--- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java
+++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java
@@ -320,6 +320,22 @@ public class GnuDemanglerParser {
*/
private static final Pattern LITERAL_NUMBER_PATTERN = Pattern.compile("-*\\d+[ul]{0,1}");
+ /**
+ * Pattern to identify a legacy rust string that contains its hash id suffix and capture the
+ * non-hash portion.
+ *
+ * Legacy mangled rust symbols:
+ * - start with _ZN
+ * - end withe E or E.
+ * - have a 16 digit hash that starts with 17h
+ *
+ * The demangled string has the leading '17' and trailing 'E|E.' removed.
+ *
+ * Sample: std::io::Read::read_to_end::hb85a0f6802e14499
+ */
+ private static final Pattern RUST_LEGACY_SUFFIX_PATTERN =
+ Pattern.compile("(.*)::h[0-9a-f]{16}");
+
private String mangledSource;
private String demangledSource;
@@ -333,6 +349,8 @@ public class GnuDemanglerParser {
*/
public DemangledObject parse(String mangled, String demangled) throws DemanglerParseException {
+ demangled = cleanupRustLegacySymbol(demangled);
+
this.mangledSource = mangled;
this.demangledSource = demangled;
@@ -465,6 +483,14 @@ public class GnuDemanglerParser {
return function;
}
+ private String cleanupRustLegacySymbol(String demangled) {
+ Matcher m = RUST_LEGACY_SUFFIX_PATTERN.matcher(demangled);
+ if (m.matches()) {
+ return m.group(1);
+ }
+ return demangled;
+ }
+
private void setReturnType(String demangled, DemangledFunction function, String returnType) {
String updatedReturnType = returnType;
diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java
index 1922a5c323..e03c6375c4 100644
--- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java
+++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java
@@ -33,7 +33,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
process = GnuDemanglerNativeProcess
- .getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
+ .getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_41);
parser = new GnuDemanglerParser();
}
@@ -1025,12 +1025,11 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String demangled = process.demangle(mangled);
/*
- typeinfo for
- std::__ndk1::__function::__func<
- dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1},
- std::__ndk1::allocator<{lambda(dummy::it::other::Namespace*)#1}>,
- int (dummy::it::other::Namespace*)
- >
+ typeinfo for
+ std::__ndk1::__function::__func<
+ dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1},
+ std::__ndk1::allocator,
+ int (dummy::it::other::Namespace*)>
'__func' has 3 template parameters, the operator and the allocator
@@ -1042,7 +1041,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String lambdaOperator =
dummyNs + "::function(float)::$_2::operator()(" + dummyNsP + ")const::" + lambda;
- String lambdaAllocator = "std::__ndk1::allocator<" + lambda + ">";
+ String lambdaAllocator = "std::__ndk1::allocator<" + lambdaOperator + ">";
String thirdParam = "int(" + dummyNsP + ")";
String infoNs = "std::__ndk1::__function::";
@@ -1092,7 +1091,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String signature = object.getSignature(false);
assertEquals(
- "undefined std::__array_traits,4ul>::_S_ref(LayerDetails::LayerBase::initRandom(long,long) const::{lambda(long&, unsigned int)#1} const &[],unsigned long)",
+ "undefined std::__array_traits,4ul>::_S_ref(LayerDetails::RandomProviderT const &[],unsigned long)",
signature);
}
@@ -1163,6 +1162,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
lambda contents - lambdas in templates and as a parameter
+ Note: the demangled string makes use of the 'auto' parameter keyword
+
bool (***
const* std::
__addressof<
@@ -1196,7 +1197,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String signature = object.getSignature(false);
assertEquals(
- "undefined Bedrock::Threading::TLSDetail::DefaultConstructor::create()::{lambda(bool(***const*std::__addressof::create()::{lambda(bool(***const)(AssertHandlerContext_const&))#1}>(Bedrock::Threading::TLSDetail::DefaultConstructor::create()::{lambda(bool(***const&)(AssertHandlerContext_const&))#1}))(AssertHandlerContext_const&))#1}",
+ "undefined Bedrock::Threading::TLSDetail::DefaultConstructor::create()::{lambda(bool(***const*std::__addressof::create()::{lambda(bool(***const)(AssertHandlerContext_const&))#1}>(auto:1&))(AssertHandlerContext_const&))#1}",
signature);
}
@@ -1997,7 +1998,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String signature = object.getSignature(false);
assertEquals(
- "int LayerDetails::RandomProviderT::operator()(LayerDetails::RandomProviderT::operator() const &[])",
+ "int LayerDetails::RandomProviderT::operator()(int const &[])",
signature);
}
@@ -2140,6 +2141,34 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
new DemangledDataType("fake", "fake", DemangledDataType.LONG_LONG).getDataType(null));
}
+ @Test
+ public void testRustLegacyHashIsIgnored() throws Exception {
+
+ //
+ // Mangled: _ZN3std2io4Read11read_to_end17hb85a0f6802e14499E
+ //
+ // Demangled: std::io::Read::read_to_end::hb85a0f6802e14499
+ //
+ // Parsed: std::io::Read::read_to_end
+ //
+ // Legacy mangled rust symbols:
+ // - start with _ZN
+ // - end withe E or E.
+ // - have a 16 digit hash that starts with 17h
+ //
+ String mangled = "_ZN3std2io4Read11read_to_end17hb85a0f6802e14499E";
+ String demangled = process.demangle(mangled);
+
+ assertEquals(demangled, "std::io::Read::read_to_end::hb85a0f6802e14499");
+
+ DemangledObject object = parser.parse(mangled, demangled);
+ assertNotNull(object);
+ assertType(object, DemangledVariable.class);
+
+ String signature = object.getSignature(false);
+ assertEquals("std::io::Read::read_to_end", signature);
+ }
+
private void assertType(Demangled o, Class> c) {
assertTrue("Wrong demangled type. " + "\nExpected " + c + "; " + "\nfound " + o.getClass(),
c.isInstance(o));