mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-272 - Gnu Demangler - updated to handle a lambda function parameter
with templates
This commit is contained in:
@@ -90,6 +90,7 @@ public class DemangledDataType extends DemangledType {
|
||||
private boolean isEnum;
|
||||
private boolean isPointer64;
|
||||
private boolean isReference;
|
||||
private boolean isRValueReference;
|
||||
private boolean isSigned;
|
||||
private boolean isStruct;
|
||||
private boolean isTemplate;
|
||||
@@ -445,6 +446,13 @@ public class DemangledDataType extends DemangledType {
|
||||
isReference = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* rvalue reference; C++11
|
||||
*/
|
||||
public void setRValueReference() {
|
||||
isRValueReference = true;
|
||||
}
|
||||
|
||||
public void setSigned() {
|
||||
isSigned = true;
|
||||
}
|
||||
@@ -671,6 +679,9 @@ public class DemangledDataType extends DemangledType {
|
||||
|
||||
if (isReference) {
|
||||
buffer.append(SPACE + REF_NOTATION);
|
||||
if (isRValueReference) {
|
||||
buffer.append(REF_NOTATION); // &&
|
||||
}
|
||||
}
|
||||
|
||||
// the order of __ptr64 and __restrict can vary--with fuzzing...
|
||||
@@ -703,5 +714,4 @@ public class DemangledDataType extends DemangledType {
|
||||
public String toString() {
|
||||
return getSignature();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -193,17 +193,18 @@ public class GnuDemanglerParser {
|
||||
*
|
||||
* Sample: {lambda(void const*, unsigned int)#1}
|
||||
* {lambda(NS1::Class1 const&, int, int)#1} const&
|
||||
* {lambda(auto:1&&)#1}<NS1::NS2>&&
|
||||
*
|
||||
* Pattern: [optional text] brace lambda([parameters])#digits brace [optional modifiers]
|
||||
* Pattern: [optional text] brace lambda([parameters])#digits brace [trailing text]
|
||||
*
|
||||
* Parts:
|
||||
* -full text without leading characters (capture group 1)
|
||||
* -parameters of the lambda function (capture group 2)
|
||||
* -trailing id (capture group 3)
|
||||
* -trailing modifiers (e.g., const, &) (capture group 4)
|
||||
* -trailing modifiers (e.g., const, &, templates) (capture group 4)
|
||||
*/
|
||||
private static final Pattern LAMBDA_PATTERN =
|
||||
Pattern.compile(".*(\\{" + LAMBDA + "\\((.*)\\)(#\\d+)\\})(\\s*(?:const|\\*|\\&)*){0,1}");
|
||||
Pattern.compile(".*(\\{" + LAMBDA + "\\((.*)\\)(#\\d+)\\})(.*)");
|
||||
|
||||
/*
|
||||
* Sample: {unnamed type#1}
|
||||
@@ -395,8 +396,14 @@ public class GnuDemanglerParser {
|
||||
DemangledFunction function = new DemangledFunction(mangledSource, demangled, null);
|
||||
|
||||
String simpleName = signatureParts.getName();
|
||||
LambdaName lambdaName = getLambdaName(demangled);
|
||||
if (lambdaName != null) {
|
||||
|
||||
if (simpleName.endsWith(LAMBDA_START)) {
|
||||
//
|
||||
// For lambdas, the signature parser will set the name to '{lambda', with the parameters
|
||||
// following that text in the original string. We want the name to be the full lambda
|
||||
// text, without spaces.
|
||||
//
|
||||
LambdaName lambdaName = getLambdaName(demangled);
|
||||
String uniqueName = lambdaName.getFullText();
|
||||
String escapedLambda = removeBadSpaces(uniqueName);
|
||||
simpleName = simpleName.replace(LAMBDA_START, escapedLambda);
|
||||
@@ -706,6 +713,7 @@ public class GnuDemanglerParser {
|
||||
// e.g., short (&)[7]
|
||||
// lambda function
|
||||
// e.g., {lambda(NS1::Class1 const&, int, int)#1} const&
|
||||
// {lambda(auto:1&&)#1}<NS1::NS2>>&&
|
||||
//
|
||||
|
||||
LambdaName lambdaName = getLambdaName(datatype);
|
||||
@@ -724,7 +732,8 @@ public class GnuDemanglerParser {
|
||||
ddt.setName(fullText);
|
||||
int offset = fullText.indexOf('(');
|
||||
int remaining = fullText.length() - offset;
|
||||
i = i + remaining;
|
||||
i = i + remaining; // end of lambda's closing '}'
|
||||
i = i - 1; // back up one space to catch optional templates on next loop pass
|
||||
}
|
||||
else {
|
||||
int startParenCount =
|
||||
@@ -770,7 +779,7 @@ public class GnuDemanglerParser {
|
||||
ddt.setReference();
|
||||
}
|
||||
else {
|
||||
ddt.incrementPointerLevels();
|
||||
ddt.setRValueReference();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1498,18 +1507,19 @@ public class GnuDemanglerParser {
|
||||
}
|
||||
}
|
||||
|
||||
// {lambda(void const*, unsigned int)#1}
|
||||
private class LambdaName {
|
||||
|
||||
private String fullText;
|
||||
private String params;
|
||||
private String id;
|
||||
private String trailing;
|
||||
private String modifiers;
|
||||
|
||||
LambdaName(String fullText, String params, String trailing, String modifiers) {
|
||||
LambdaName(String fullText, String params, String id, String trailing) {
|
||||
this.fullText = fullText;
|
||||
this.params = params;
|
||||
this.trailing = trailing;
|
||||
this.modifiers = modifiers == null ? "" : modifiers;
|
||||
this.id = id;
|
||||
this.trailing = trailing == null ? "" : trailing;
|
||||
}
|
||||
|
||||
String getFullText() {
|
||||
@@ -1521,8 +1531,8 @@ public class GnuDemanglerParser {
|
||||
ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE);
|
||||
return builder.append("fullText", fullText)
|
||||
.append("params", params)
|
||||
.append("id", id)
|
||||
.append("trailing", trailing)
|
||||
.append("modifiers", modifiers)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1233,7 +1233,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
parameters.get(0).getTemplate().toString());
|
||||
|
||||
assertEquals(
|
||||
"undefined Core::AsyncFile::perform(WTF::F<WTF::F<void (Core::FileClient &)> (Core::File &)> * &)",
|
||||
"undefined Core::AsyncFile::perform(WTF::F<WTF::F<void (Core::FileClient &)> (Core::File &)> &&)",
|
||||
object.getSignature(false));
|
||||
|
||||
}
|
||||
@@ -1460,6 +1460,32 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLambdaWithTemplates() throws Exception {
|
||||
|
||||
// _ZN7brigand13for_each_argsIZN7WebCore9ConverterINS1_8IDLUnionIJNS1_12IDLDOMStringENS1_12IDLInterfaceINS1_14CanvasGradientEEENS5_INS1_13CanvasPatternEEEEEEE7convertERN3JSC9ExecStateENSC_7JSValueEEUlOT_E_JNS_5type_IS7_EENSJ_IS9_EEEEESG_SG_DpOT0_
|
||||
|
||||
// {lambda(auto:1&&)#1}
|
||||
|
||||
// {lambda(auto:1&&)#1}<NS1::NS2>>&&
|
||||
|
||||
DemangledObject object = parser.parse(
|
||||
"_ZN3WTF6VectorINS_9RetainPtrI29AVAssetResourceLoadingRequestEELm0ENS_15CrashOnOverflowELm16ENS_10FastMallocEE17removeAllMatchingIZNS6_9removeAllIPS2_EEjRKT_EUlRKS3_E_EEjSC_m",
|
||||
"WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString, WebCore::IDLInterface<WebCore::CanvasGradient>, WebCore::IDLInterface<WebCore::CanvasPattern> > >::convert(JSC::ExecState&, JSC::JSValue)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString, WebCore::IDLInterface<WebCore::CanvasGradient>, WebCore::IDLInterface<WebCore::CanvasPattern> > >::convert(JSC::ExecState&, JSC::JSValue)::{lambda(auto:1&&)#1}, brigand::type_<WebCore::IDLInterface<WebCore::CanvasGradient> >, WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString, WebCore::IDLInterface<WebCore::CanvasGradient>, WebCore::IDLInterface<WebCore::CanvasPattern> > >::convert(JSC::ExecState&, JSC::JSValue)::{lambda(auto:1&&)#1}<WebCore::IDLInterface<WebCore::CanvasPattern> > >(WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString, WebCore::IDLInterface<WebCore::CanvasGradient>, WebCore::IDLInterface<WebCore::CanvasPattern> > >::convert(JSC::ExecState&, JSC::JSValue)::{lambda(auto:1&&)#1}, brigand::type_<WebCore::IDLInterface<WebCore::CanvasGradient> >&&, WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString, WebCore::IDLInterface<WebCore::CanvasGradient>, WebCore::IDLInterface<WebCore::CanvasPattern> > >::convert(JSC::ExecState&, JSC::JSValue)::{lambda(auto:1&&)#1}<WebCore::IDLInterface<WebCore::CanvasPattern> >&&)");
|
||||
|
||||
assertNotNull(object);
|
||||
assertType(object, DemangledFunction.class);
|
||||
|
||||
String name =
|
||||
"for_each_args<WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1},brigand::type_<WebCore::IDLInterface<WebCore::CanvasGradient>>,WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1}<WebCore::IDLInterface<WebCore::CanvasPattern>>>";
|
||||
assertName(object, name, "brigand");
|
||||
|
||||
String signature = object.getSignature(false);
|
||||
assertEquals(
|
||||
"WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1} brigand::for_each_args<WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1},brigand::type_<WebCore::IDLInterface<WebCore::CanvasGradient>>,WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1}<WebCore::IDLInterface<WebCore::CanvasPattern>>>(WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1},brigand::type_<WebCore::IDLInterface<WebCore::CanvasGradient>> &&,WebCore::Converter<WebCore::IDLUnion<WebCore::IDLDOMString,WebCore::IDLInterface<WebCore::CanvasGradient>,WebCore::IDLInterface<WebCore::CanvasPattern>>>::convert(JSC::ExecState&,JSC::JSValue)::{lambda(auto:1&&)#1}<WebCore::IDLInterface<WebCore::CanvasPattern>> &&)",
|
||||
signature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionWithLambdaParameter() throws Exception {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user