mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-272 - Gnu Demangler - updated to handle a overloaded operator with
excessive templates
This commit is contained in:
parent
839f9eeac2
commit
ef013a0286
3 changed files with 62 additions and 19 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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> >&&)");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue