GP-272 - Gnu Demangler - fixed demangler failure related to function

parameters with RValue varargs
This commit is contained in:
dragonmacher
2020-11-10 13:11:39 -05:00
parent 0e6c7a6859
commit e664fd518a
3 changed files with 82 additions and 12 deletions

View File

@@ -77,7 +77,7 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
Address address = symbol.getAddress();
String mangled = cleanSymbol(address, symbol.getName());
DemangledObject demangled = demangle(mangled, options, log);
DemangledObject demangled = demangle(mangled, address, options, log);
if (demangled != null) {
apply(program, address, demangled, options, log, monitor);
}
@@ -172,11 +172,13 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
* handled.
*
* @param mangled the mangled string
* @param address the symbol address
* @param options the demangler options
* @param log the error log
* @return the demangled object; null if unsuccessful
*/
protected DemangledObject demangle(String mangled, DemanglerOptions options, MessageLog log) {
protected DemangledObject demangle(String mangled, Address address, DemanglerOptions options,
MessageLog log) {
DemangledObject demangled = null;
try {
@@ -192,7 +194,8 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer {
}
log.appendMsg(getName(),
"Unable to demangle symbol: " + mangled + ". Message: " + e.getMessage());
"Unable to demangle symbol: " + mangled + " at " + address + ". Message: " +
e.getMessage());
return null;
}

View File

@@ -65,8 +65,8 @@ public class GnuDemanglerParser {
* Pattern: name(([const] [params]))
*
* Parts: -optional spaces
* -optional (const) (non-capture group)
* -followed by '()' with optional parameter text (capture group 1)
* -optional (const) (non-capture group)
* -followed by '()' with optional parameter text (capture group 1)
*
* Note: this pattern is used for matching the arguments string, in the above examples it
* would be:
@@ -78,6 +78,22 @@ public class GnuDemanglerParser {
private static final Pattern UNNECESSARY_PARENS_PATTERN =
Pattern.compile("\\s*(?:const){0,1}\\((.*)\\)\\s*");
/**
* Captures the contents of a varargs parameter that is inside of parentheses.
*
* Sample: (NS1::type&&)...
*
* Pattern: (namespace::name[modifiers])...
*
* Parts: -open paren
* -contents (capture group 1)
* -close paren
* -varargs
*
*/
private static final Pattern VARARGS_IN_PARENS =
Pattern.compile("\\((.*)\\)" + Pattern.quote("..."));
/*
* Sample: bob(short (&)[7])
* bob(int const[8] (*) [12])
@@ -452,7 +468,7 @@ public class GnuDemanglerParser {
return;
}
function.setReturnType(parseDataType(returnType));
function.setReturnType(parseReturnType(returnType));
}
private LambdaName getLambdaName(String name) {
@@ -630,23 +646,40 @@ public class GnuDemanglerParser {
List<DemangledDataType> parameters = new ArrayList<>();
for (String parameter : parameterStrings) {
DemangledDataType ddt = parseDataType(parameter);
DemangledDataType ddt = parseParameter(parameter);
parameters.add(ddt);
}
return parameters;
}
private DemangledDataType parseDataType(String fullDatatype) {
private DemangledDataType parseParameter(String parameter) {
Matcher castMatcher = CAST_PATTERN.matcher(fullDatatype);
Matcher castMatcher = CAST_PATTERN.matcher(parameter);
if (castMatcher.matches()) {
// special case: template parameter with a cast (just make the datatype
// be the name of the template parameter, since it will just be a display
// attribute for the templated type)
return new DemangledDataType(mangledSource, demangledSource, fullDatatype);
return new DemangledDataType(mangledSource, demangledSource, parameter);
}
Matcher matcher = VARARGS_IN_PARENS.matcher(parameter);
if (matcher.matches()) {
String inside = matcher.group(1);
DemangledDataType ddt = parseDataType(inside);
ddt.setVarArgs();
return ddt;
}
return parseDataType(parameter);
}
private DemangledDataType parseReturnType(String returnType) {
return parseDataType(returnType);
}
private DemangledDataType parseDataType(String fullDatatype) {
DemangledDataType ddt = createTypeInNamespace(fullDatatype);
String datatype = ddt.getDemangledName();
boolean finishedName = false;
@@ -1028,7 +1061,7 @@ public class GnuDemanglerParser {
List<DemangledDataType> parameters = parseParameters(paramerterString);
DemangledFunctionPointer dfp = new DemangledFunctionPointer(mangledSource, demangledSource);
DemangledDataType returnDataType = parseDataType(returnType);
DemangledDataType returnDataType = parseReturnType(returnType);
dfp.setReturnType(returnDataType);
for (DemangledDataType parameter : parameters) {
dfp.addParameter(parameter);
@@ -1364,7 +1397,7 @@ public class GnuDemanglerParser {
DemangledFunction method =
new DemangledFunction(mangledSource, demangledSource, (String) null);
DemangledDataType returnType = parseDataType(fullReturnType);
DemangledDataType returnType = parseReturnType(fullReturnType);
if (isConst) {
returnType.setConst();
}

View File

@@ -1502,6 +1502,40 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
signature);
}
@Test
public void testFunctionWithVarargsRvalueParameter() throws Exception {
// __ZN3WTF15__visit_helper2ILl1ELm1EJEE7__visitINS_7VisitorIZNKS_17TextBreakIterator9followingEjEUlRKT_E_JEEEJRKNS_7VariantIJNS_20TextBreakIteratorICUENS_19TextBreakIteratorCFEEEEEEENS_27__multi_visitor_return_typeIS5_JDpT0_EE6__typeERS5_DpOSH_
//
// this demangled string introduces a new construct:
//
// (WTF::__multi_visitor_return_type&&)...
//
// where the above is a parameter to function, where the params look like:
// (
// WTF::Visitor<WTF::TextBreakIterator::following(unsigned int) const::{lambda(auto:1 const&)#1}>&,
// (WTF::__multi_visitor_return_type&&)...
// )
//
DemangledObject object = parser.parse(
"__ZN3WTF15__visit_helper2ILl1ELm1EJEE7__visitINS_7VisitorIZNKS_17TextBreakIterator9followingEjEUlRKT_E_JEEEJRKNS_7VariantIJNS_20TextBreakIteratorICUENS_19TextBreakIteratorCFEEEEEEENS_27__multi_visitor_return_typeIS5_JDpT0_EE6__typeERS5_DpOSH_",
"WTF::__multi_visitor_return_type<WTF::Visitor<WTF::TextBreakIterator::following(unsigned int) const::{lambda(auto:1 const&)#1}>, WTF::Variant<WTF::TextBreakIteratorICU, WTF::TextBreakIteratorCF> const&>::__type WTF::__visit_helper2<1l, 1ul>::__visit<WTF::Visitor<WTF::TextBreakIterator::following(unsigned int) const::{lambda(auto:1 const&)#1}>, WTF::Variant<WTF::TextBreakIteratorICU, WTF::TextBreakIteratorCF> const&>(WTF::Visitor<WTF::TextBreakIterator::following(unsigned int) const::{lambda(auto:1 const&)#1}>&, (WTF::__multi_visitor_return_type&&)...)");
assertNotNull(object);
assertType(object, DemangledFunction.class);
String name =
"__visit<WTF::Visitor<WTF::TextBreakIterator::following(unsigned_int)const::{lambda(auto:1_const&)#1}>,WTF::Variant<WTF::TextBreakIteratorICU,WTF::TextBreakIteratorCF>const&>";
assertName(object, name, "WTF", "__visit_helper2<1l,1ul>");
String signature = object.getSignature(false);
assertEquals(
"WTF::__multi_visitor_return_type<WTF::Visitor<WTF::TextBreakIterator::following(unsigned_int)const::{lambda(auto:1_const&)#1}>,WTF::Variant<WTF::TextBreakIteratorICU,WTF::TextBreakIteratorCF>const&>::__type WTF::__visit_helper2<1l,1ul>::__visit<WTF::Visitor<WTF::TextBreakIterator::following(unsigned_int)const::{lambda(auto:1_const&)#1}>,WTF::Variant<WTF::TextBreakIteratorICU,WTF::TextBreakIteratorCF>const&>(WTF::Visitor<WTF::TextBreakIterator::following(unsigned_int) const::{lambda(auto:1 const&)#1}> &,WTF::__multi_visitor_return_type &&)",
signature);
}
@Test
public void testOperator_Equals_ExcessivelyTemplated() throws Exception {