mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-3577 - Demangler - Updated the Gnu Demangler to version 2.41
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<dummy::it::other::Namespace::function(float)::$_2::operator()(dummy::it::other::Namespace*) const::{lambda(dummy::it::other::Namespace*)#1}>,
|
||||
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<LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>,4ul>::_S_ref(LayerDetails::LayerBase::initRandom(long,long) const::{lambda(long&, unsigned int)#1} const &[],unsigned long)",
|
||||
"undefined std::__array_traits<LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>,4ul>::_S_ref(LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long, long) const::{lambda(long&, unsigned int)#1}> 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<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const*std::__addressof<Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const)(AssertHandlerContext_const&))#1}>(Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const&)(AssertHandlerContext_const&))#1}))(AssertHandlerContext_const&))#1}",
|
||||
"undefined Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::create()::{lambda(bool(***const*std::__addressof<Bedrock::Threading::TLSDetail::DefaultConstructor<bool(**)(AssertHandlerContext_const&),void>::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<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>::operator()<int,2ul>(LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>::operator() const &[])",
|
||||
"int LayerDetails::RandomProviderT<LayerDetails::LayerBase::initRandom(long,long)const::{lambda(long&,unsigned_int)#1}>::operator()<int,2ul>(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));
|
||||
|
||||
Reference in New Issue
Block a user