diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java index 651f19e842..f79e4c607a 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java @@ -22,6 +22,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import ghidra.app.util.NamespaceUtils; +import ghidra.app.util.SymbolPath; import ghidra.app.util.demangler.*; import ghidra.program.model.lang.CompilerSpec; import ghidra.util.StringUtilities; @@ -373,9 +374,9 @@ public class GnuDemanglerParser implements DemanglerParser { } // this will yield: - // fullNamespace: NS1::Foo::operator + // fullName: NS1::Foo::operator // fullReturnType: std::string - String fullNamespace = matcher.group(1);// group 0 is the entire match string + String fullName = matcher.group(1);// group 0 is the entire match string String fullReturnType = matcher.group(2); boolean isConst = false; @@ -393,14 +394,17 @@ public class GnuDemanglerParser implements DemanglerParser { method.setReturnType(returnType); // 'conversion operator' syntax is operator () + // assume fullName endsWith '::operator' + int operatorIndex = fullName.lastIndexOf("::operator"); + String namespace = fullName.substring(0, operatorIndex); - String templatelessNamespace = stripOffTemplates(fullNamespace); + String templatelessNamespace = stripOffTemplates(namespace); setNamespace(method, templatelessNamespace); // shortReturnType: string String templatelessReturnType = stripOffTemplates(fullReturnType); - List names = NamespaceUtils.splitNamespacePath(templatelessReturnType); - String shortReturnTypeName = names.get(names.size() - 1); + SymbolPath path = new SymbolPath(templatelessReturnType); + String shortReturnTypeName = path.getName(); // // The preferred name: 'operator basic_string()' @@ -410,7 +414,7 @@ public class GnuDemanglerParser implements DemanglerParser { // method.setName("operator.cast.to." + shortReturnTypeName); - method.setSignature(fullNamespace + " " + fullReturnType); + method.setSignature(fullName + " " + fullReturnType); method.setOverloadedOperator(true); return method; @@ -481,17 +485,24 @@ public class GnuDemanglerParser implements DemanglerParser { } private String stripOffTemplates(String string) { - int templateStart = string.indexOf("<"); - if (templateStart == -1) { - return string; - } + StringBuilder buffy = new StringBuilder(); + int templateCount = 0; + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (c == '<') { + templateCount++; + continue; + } + else if (c == '>') { + templateCount--; + continue; + } - int templateEnd = string.lastIndexOf(">"); - if (templateEnd == -1) { - return string;// shouldn't happen + if (templateCount == 0) { + buffy.append(c); + } } - - return string.substring(0, templateStart); + return buffy.toString(); } private DemangledObject parseGuardVariableOrReferenceTemporary(String demangled, diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java index 6f9e613d31..d0d8b4c1ae 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java @@ -37,10 +37,6 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { parser = new GnuDemanglerParser(process); } - /** - * This method just tries to demangled a bunch o' - * mangled names just checking for stack traces. - */ @Test public void test() throws Exception { long start = System.currentTimeMillis(); @@ -341,48 +337,6 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { assertEquals("float", parameters.get(0).toSignature()); } - @Test - public void testOperator() throws Exception { - String mangled = "_ZN6MagickltERKNS_10CoordinateES2_"; - - String demangled = process.demangle(mangled); - - DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); - assertName(object, "operator<", "Magick"); - - DemangledMethod method = (DemangledMethod) object; - assertEquals( - "undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)", - method.getSignature(false)); - - List parameters = method.getParameters(); - assertEquals(2, parameters.size()); - assertEquals("Magick::Coordinate const &", parameters.get(0).toSignature()); - assertEquals("Magick::Coordinate const &", parameters.get(1).toSignature()); - } - - @Test - public void testOperatorCastTo() throws Exception { - // - // Mangled: _ZNKSt17integral_constantIbLb0EEcvbEv - // - // Demangled: std::integral_constant::operator bool() const - - String mangled = "_ZNKSt17integral_constantIbLb0EEcvbEv"; - - String demangled = process.demangle(mangled); - - DemangledObject object = parser.parse(mangled, demangled); - assertNotNull(object); - assertTrue(object instanceof DemangledFunction); - - String signature = object.getSignature(false); - assertEquals( - "bool std::integral_constant::operator.cast.to.bool(void)", - signature); - } - @Test public void testFunctions() throws Exception { String mangled = "_Z7toFloatidcls"; @@ -713,6 +667,48 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { object.getSignature(false)); } + @Test + public void testOperator() throws Exception { + String mangled = "_ZN6MagickltERKNS_10CoordinateES2_"; + + String demangled = process.demangle(mangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertTrue(object instanceof DemangledMethod); + assertName(object, "operator<", "Magick"); + + DemangledMethod method = (DemangledMethod) object; + assertEquals( + "undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)", + method.getSignature(false)); + + List parameters = method.getParameters(); + assertEquals(2, parameters.size()); + assertEquals("Magick::Coordinate const &", parameters.get(0).toSignature()); + assertEquals("Magick::Coordinate const &", parameters.get(1).toSignature()); + } + + @Test + public void testOperatorCastTo() throws Exception { + // + // Mangled: _ZNKSt17integral_constantIbLb0EEcvbEv + // + // Demangled: std::integral_constant::operator bool() const + + String mangled = "_ZNKSt17integral_constantIbLb0EEcvbEv"; + + String demangled = process.demangle(mangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertNotNull(object); + assertTrue(object instanceof DemangledFunction); + + String signature = object.getSignature(false); + assertEquals( + "bool std::integral_constant::operator.cast.to.bool(void)", + signature); + } + @Test public void testConversionOperator() throws Exception { @@ -738,6 +734,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { @Test public void testConversionOperatorWithConst() throws Exception { + // + // + // Mangled: _ZN12_GLOBAL__N_120decode_charset_iconvEPKc + // + // Demangled: GCC_IndicationPDU::operator GCC_ApplicationInvokeIndication const&() const + // + // // Converts the object upon which it is overridden to the given value. //