GP-272 - Gnu Demangler - updated to handle a overloaded operator with

excessive templates
This commit is contained in:
dragonmacher 2020-11-09 15:38:02 -05:00
parent 839f9eeac2
commit ef013a0286
3 changed files with 62 additions and 19 deletions

View file

@ -80,7 +80,8 @@ public class DemanglerCmd extends BackgroundCommand {
return true; // no real error
}
setStatusMsg("Unable to demangle symbol: " + mangled + ". Message: " + e.getMessage());
setStatusMsg("Unable to demangle symbol: " + mangled + " at " + addr + ". Message: " +
e.getMessage());
return false; // error
// This produces too many messages for non-demangled symbols. If we could
@ -91,7 +92,8 @@ public class DemanglerCmd extends BackgroundCommand {
}
catch (Exception e) {
// Demangler IndexOutOfBoundsException that we're not sure how to fix
setStatusMsg("Unable to demangle symbol: " + mangled + ". Message: " + e.getMessage());
setStatusMsg("Unable to demangle symbol: " + mangled + " at " + addr + ". Message: " +
e.getMessage());
return false;
}
@ -111,7 +113,7 @@ public class DemanglerCmd extends BackgroundCommand {
}
setStatusMsg(
"Failed to apply mangled symbol at " + addr.toString() + "; name: " + mangled + " (" +
"Failed to apply mangled symbol at " + addr + "; name: " + mangled + " (" +
demangler.getClass().getName() + "/" + demangledObject.getClass().getName() + ")");
return false; // error
}

View file

@ -30,6 +30,7 @@ import ghidra.app.util.SymbolPath;
import ghidra.app.util.demangler.*;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.symbol.Namespace;
import ghidra.util.Msg;
import ghidra.util.StringUtilities;
public class GnuDemanglerParser {
@ -283,6 +284,7 @@ public class GnuDemanglerParser {
String extra = userDefinedLiteral;
alternated += '|' + extra;
// note: this capture group seems to fail with excessive templating
String operatorTemplates = "(<.+>){0,1}";
String operatorPrefix =
".*(.*" + OPERATOR + "(" + alternated + ")\\s*" + operatorTemplates + ".*)\\s*";
@ -1274,14 +1276,8 @@ public class GnuDemanglerParser {
// NS1::operator<(NS1::Coordinate const &,NS1::Coordinate const &)
//
String operatorChars = matcher.group(2);
String templates = matcher.group(3);
int start = matcher.start(2); // operator chars start
int end = matcher.end(3); // templates end
if (templates == null) {
templates = "";
end = matcher.end(2); // no templates; end of the operator chars
}
int end = matcher.end(2); // operator chars start
//
// The 'operator' functions have symbols that confuse our default function parsing.
@ -1289,11 +1285,16 @@ public class GnuDemanglerParser {
// template parsing to fail. To defeat the failure, we will install a temporary
// function name here and then restore it after parsing is finished.
//
String rawPrefix = OPERATOR + demangled.substring(start, end);
String placeholder = "TEMPNAMEPLACEHOLDERVALUE";
String tempName = demangled.replace(rawPrefix, placeholder);
DemangledFunction function = (DemangledFunction) parseFunctionOrVariable(tempName);
String templates = getTemplates(end);
end = end + templates.length();
// a string to replace operator chars; this value will be overwritten the name is set
String placeholder = "TEMPNAMEPLACEHOLDERVALUE";
String baseOperator = OPERATOR + demangled.substring(start, end);
String fixedFunction = demangled.replace(baseOperator, placeholder);
DemangledFunction function = (DemangledFunction) parseFunctionOrVariable(fixedFunction);
function.setOverloadedOperator(true);
String simpleName = OPERATOR + operatorChars;
@ -1309,6 +1310,30 @@ public class GnuDemanglerParser {
return function;
}
private String getTemplates(int start) {
String templates = "";
boolean hasTemplates = nextCharIs(demangled, start, '<');
if (hasTemplates) {
int templateStart = start;
int templateEnd = findTemplateEnd(demangled, templateStart);
if (templateEnd == -1) {
// should not happen
Msg.debug(this, "Unable to find template end for operator: " + demangled);
return templates;
}
templates = demangled.substring(templateStart, templateEnd + 1);
}
return templates;
}
}
private boolean nextCharIs(String text, int index, char c) {
char next = text.charAt(index);
while (next == ' ') {
next = text.charAt(++index);
}
return next == c;
}
private class ConversionOperatorHandler extends OperatorHandler {

View file

@ -1460,15 +1460,31 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
signature);
}
@Test
public void testOperator_Equals_ExcessivelyTemplated() throws Exception {
DemangledObject object = parser.parse(
"__ZN3WTF8FunctionIFvvEEaSIZN7WebCore9IDBClient24TransactionOperationImplIJRKNS4_18IDBObjectStoreInfoEEEC1ERNS4_14IDBTransactionEMSB_FvRKNS4_13IDBResultDataEEMSB_FvRNS5_20TransactionOperationES9_ES9_EUlvE_vEERS2_OT_",
"WTF::Function<void ()>& WTF::Function<void ()>::operator=<WebCore::IDBClient::TransactionOperationImpl<WebCore::IDBObjectStoreInfo const&>::TransactionOperationImpl(WebCore::IDBTransaction&, void (WebCore::IDBTransaction::*)(WebCore::IDBResultData const&), void (WebCore::IDBTransaction::*)(WebCore::IDBClient::TransactionOperation&, WebCore::IDBObjectStoreInfo const&), WebCore::IDBObjectStoreInfo const&)::{lambda()#1}, void>(WebCore::IDBClient::TransactionOperationImpl<WebCore::IDBObjectStoreInfo const&>::TransactionOperationImpl(WebCore::IDBTransaction&, void (WebCore::IDBTransaction::*)(WebCore::IDBResultData const&), void (WebCore::IDBTransaction::*)(WebCore::IDBClient::TransactionOperation&, WebCore::IDBObjectStoreInfo const&), WebCore::IDBObjectStoreInfo const&)::{lambda()#1}&&)");
assertNotNull(object);
assertType(object, DemangledFunction.class);
String name =
"operator=";
assertName(object, name, "WTF", "Function<void()>");
String signature = object.getSignature(false);
assertEquals(
"WTF::Function<void ()> & WTF::Function<void()>::operator=<WebCore::IDBClient::TransactionOperationImpl<WebCore::IDBObjectStoreInfo_const&>::TransactionOperationImpl(WebCore::IDBTransaction&,void(WebCore::IDBTransaction::*)(WebCore::IDBResultData_const &,void ()(WebCore::IDBClient::TransactionOperation &,WebCore::IDBObjectStoreInfo_const &),WebCore::IDBObjectStoreInfo_const&)::{lambda()#1},void>(WebCore::IDBClient::TransactionOperationImpl<WebCore::IDBObjectStoreInfo const&>::TransactionOperationImpl(WebCore::IDBTransaction&, void (WebCore::IDBTransaction::*)(WebCore::IDBResultData const &,void ()(WebCore::IDBClient::TransactionOperation &,WebCore::IDBObjectStoreInfo const &),WebCore::IDBObjectStoreInfo const&)::{lambda()#1} &&)",
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> >&&)");