mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 13:52:06 +08:00
Merge remote-tracking branch
'origin/GP-4071_dragonmacher_demangler-array-fix--SQUASHED' (Closes #5987)
This commit is contained in:
+72
-2
@@ -213,7 +213,7 @@ public class GnuDemanglerParser {
|
||||
* {lambda(NS1::Class1 const&, int, int)#1} const&
|
||||
* {lambda(auto:1&&)#1}<NS1::NS2>&&
|
||||
*
|
||||
* Pattern: [optional text] brace lambda([parameters])#digits brace [trailing text]
|
||||
* Pattern: [optional text] { lambda([parameters])#digits } [trailing text]
|
||||
*
|
||||
* Parts:
|
||||
* -full text without leading characters (capture group 1)
|
||||
@@ -227,13 +227,24 @@ public class GnuDemanglerParser {
|
||||
/*
|
||||
* Sample: {unnamed type#1}
|
||||
*
|
||||
* Pattern: [optional text] brace unnamed type#digits brace
|
||||
* Pattern: [optional text] { unnamed type#digits }
|
||||
*
|
||||
* Parts:
|
||||
* -full text without leading characters (capture group 1)
|
||||
*/
|
||||
private static final Pattern UNNAMED_TYPE_PATTERN = Pattern.compile("(\\{unnamed type#\\d+})");
|
||||
|
||||
/**
|
||||
* Sample: template parameter object for namespace::StringLiteral<38ul>{char [38]{(char)69, (char)101, ... }}
|
||||
*
|
||||
* Pattern: (text) { (array type) [size] { array contents } }
|
||||
*
|
||||
* Parts:
|
||||
* -non-array definition prefix, which is the type (capture group 1)
|
||||
*/
|
||||
private static final Pattern ARRAY_DATA_PATTERN =
|
||||
Pattern.compile("(.+)\\{(.+)\\[\\d*\\]\\{.*\\}\\}");
|
||||
|
||||
/*
|
||||
* Sample: covariant return thunk to Foo::Bar::copy(Foo::CoolStructure*) const
|
||||
*
|
||||
@@ -430,6 +441,11 @@ public class GnuDemanglerParser {
|
||||
return new TypeInfoNameHandler(demangled, TYPEINFO_NAME_FOR);
|
||||
}
|
||||
|
||||
Matcher arrayMatcher = ARRAY_DATA_PATTERN.matcher(type);
|
||||
if (arrayMatcher.matches()) {
|
||||
return new ArrayHandler(demangled, prefix, type);
|
||||
}
|
||||
|
||||
return new ItemInNamespaceHandler(demangled, prefix, type);
|
||||
}
|
||||
|
||||
@@ -780,6 +796,14 @@ public class GnuDemanglerParser {
|
||||
for (int i = 0; i < datatype.length(); ++i) {
|
||||
char ch = datatype.charAt(i);
|
||||
|
||||
//
|
||||
// Hack: Not sure what this is, but we have seen template parameter values that start
|
||||
// with an '&'
|
||||
//
|
||||
if (ch == '&' && i == 0) {
|
||||
continue; // for now, let the '&' through to be part of the name
|
||||
}
|
||||
|
||||
if (!finishedName && isDataTypeNameCharacter(ch)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1518,6 +1542,52 @@ public class GnuDemanglerParser {
|
||||
}
|
||||
}
|
||||
|
||||
private class ArrayHandler extends SpecialPrefixHandler {
|
||||
|
||||
private String arrayType;
|
||||
|
||||
ArrayHandler(String demangled, String prefix, String item) {
|
||||
super(demangled);
|
||||
this.demangled = demangled;
|
||||
this.prefix = prefix;
|
||||
this.type = item;
|
||||
|
||||
//
|
||||
// Handle array data definitions here for now. If we see this in non-specialized prefix
|
||||
// cases, then we can extract this code.
|
||||
//
|
||||
Matcher arrayMatcher = ARRAY_DATA_PATTERN.matcher(type);
|
||||
if (arrayMatcher.matches()) {
|
||||
// keep only the type information, dropping the array definition
|
||||
type = arrayMatcher.group(1);
|
||||
arrayType = arrayMatcher.group(2).trim();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
DemangledObject doBuild(Demangled namespace) {
|
||||
DemangledObject demangledObject = parseItemInNamespace(type);
|
||||
if (demangledObject instanceof DemangledVariable variable) {
|
||||
|
||||
//
|
||||
// Creating a DemangledString here will correctly create the string data when this
|
||||
// demangled type is applied.
|
||||
//
|
||||
if ("char".equals(arrayType) && type.contains("StringLiteral")) {
|
||||
// treat a char[] as a string
|
||||
DemangledString ds =
|
||||
new DemangledString(variable.getMangledString(), demangled, type, type,
|
||||
-1 /*unknown length*/, false);
|
||||
ds.setSpecialPrefix(prefix);
|
||||
return ds;
|
||||
}
|
||||
|
||||
}
|
||||
return demangledObject;
|
||||
}
|
||||
}
|
||||
|
||||
private class ThunkHandler extends SpecialPrefixHandler {
|
||||
|
||||
ThunkHandler(String demangled, String prefix, String item) {
|
||||
|
||||
+56
-1
@@ -2169,8 +2169,63 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
assertEquals("std::io::Read::read_to_end", signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateParameterObectWithArrayDefinition() throws Exception {
|
||||
|
||||
//
|
||||
// mangled: _ZTAXtlN9envHelper13StringLiteralILm38EEEtlA38_cLc67ELc111ELc114ELc101ELc65ELc117ELc100ELc105ELc111ELc95ELc67ELc97ELc112ELc116ELc117ELc114ELc101ELc67ELc111ELc110ELc118ELc101ELc114ELc116ELc101ELc114ELc67ELc104ELc97ELc105ELc110ELc95ELc73ELc110ELc112ELc117ELc116EEEE
|
||||
//
|
||||
// demangled: template parameter object for envHelper::StringLiteral<38ul>{char [38]{(char)67, (char)111, (char)114, (char)101, (char)65, (char)117, (char)100, (char)105, (char)111, (char)95, (char)67, (char)97, (char)112, (char)116, (char)117, (char)114, (char)101, (char)67, (char)111, (char)110, (char)118, (char)101, (char)114, (char)116, (char)101, (char)114, (char)67, (char)104, (char)97, (char)105, (char)110, (char)95, (char)73, (char)110, (char)112, (char)117, (char)116}}
|
||||
//
|
||||
// Note: this object ends in a char array definition:
|
||||
//
|
||||
// ...{char [38]{(char)67, .... }}
|
||||
//
|
||||
|
||||
String mangled =
|
||||
"_ZTAXtlN9envHelper13StringLiteralILm38EEEtlA38_cLc67ELc111ELc114ELc101ELc65ELc117ELc100ELc105ELc111ELc95ELc67ELc97ELc112ELc116ELc117ELc114ELc101ELc67ELc111ELc110ELc118ELc101ELc114ELc116ELc101ELc114ELc67ELc104ELc97ELc105ELc110ELc95ELc73ELc110ELc112ELc117ELc116EEEE";
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertNotNull(object);
|
||||
assertType(object, DemangledString.class);
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals("template parameter object for envHelper::StringLiteral<38ul>", signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllocatorTraits_AlocateAtLeast() throws Exception {
|
||||
|
||||
//
|
||||
// mangled: _ZNSt3__119__allocate_at_leastB7v160006INS_9allocatorINS_10unique_ptrIvN10applesauce4raii2v16detail23opaque_deletion_functorIPvXadL_Z27VPTimeFreqConverter_DisposeEEEEEEEEEENS_19__allocation_resultINS_16allocator_traitsIT_E7pointerEEERSE_m
|
||||
//
|
||||
// demangled: std::__1::__allocation_result<std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<void, applesauce::raii::v1::detail::opaque_deletion_functor<void*, &VPTimeFreqConverter_Dispose> > > >::pointer> std::__1::__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void, applesauce::raii::v1::detail::opaque_deletion_functor<void*, &VPTimeFreqConverter_Dispose> > > >(std::__1::allocator<std::__1::unique_ptr<void, applesauce::raii::v1::detail::opaque_deletion_functor<void*, &VPTimeFreqConverter_Dispose> > >&, unsigned long)
|
||||
//
|
||||
// Note: __allocate_at_least is a C++23 feature
|
||||
//
|
||||
|
||||
String mangled =
|
||||
"_ZNSt3__119__allocate_at_leastB7v160006INS_9allocatorINS_10unique_ptrIvN10applesauce4raii2v16detail23opaque_deletion_functorIPvXadL_Z27VPTimeFreqConverter_DisposeEEEEEEEEEENS_19__allocation_resultINS_16allocator_traitsIT_E7pointerEEERSE_m";
|
||||
String demangled = process.demangle(mangled);
|
||||
|
||||
DemangledObject object = parser.parse(mangled, demangled);
|
||||
assertNotNull(object);
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
assertName(object,
|
||||
"__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>",
|
||||
"std",
|
||||
"__1");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"std::__1::__allocation_result<std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>::pointer> std::__1::__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>(std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void *,&VPTimeFreqConverter_Dispose>>> &,unsigned long)",
|
||||
signature);
|
||||
}
|
||||
|
||||
private void assertType(Demangled o, Class<?> c) {
|
||||
assertTrue("Wrong demangled type. " + "\nExpected " + c + "; " + "\nfound " + o.getClass(),
|
||||
assertTrue("Wrong demangled type. \nExpected " + c + "; \nfound " + o.getClass(),
|
||||
c.isInstance(o));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user