mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-272 - Gnu Demangler - fixed demangler failure related to function
parameters with RValue varargs
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user