GP-4825 - Gnu Demangler - Update parser for some special global constructor/destructor symbols

This commit is contained in:
dragonmacher 2024-08-07 18:59:49 -04:00
parent 95573ed834
commit 518860f0d6
3 changed files with 143 additions and 28 deletions

View file

@ -76,7 +76,7 @@ public abstract class DemangledObject implements Demangled {
*/ */
protected final String mangled; // original mangled string protected final String mangled; // original mangled string
protected final String originalDemangled; // raw demangled string protected String originalDemangled; // raw demangled string
private String demangledName; // updated demangled string private String demangledName; // updated demangled string
private String name; // version of demangled name suitable for symbols private String name; // version of demangled name suitable for symbols
@ -240,6 +240,17 @@ public abstract class DemangledObject implements Demangled {
return originalDemangled; return originalDemangled;
} }
/**
* Sets the original demangled string. This is useful for clients that reuse constructed
* demangled objects for special case constructs.
* <p>
* Note: this method is not on the interface
* @param originalDemangled the new original demangled string
*/
public void setOriginalDemangled(String originalDemangled) {
this.originalDemangled = originalDemangled;
}
@Override @Override
public Demangled getNamespace() { public Demangled getNamespace() {
return namespace; return namespace;

View file

@ -271,6 +271,19 @@ public class GnuDemanglerParser {
private static final Pattern DESCRIPTIVE_PREFIX_PATTERN = private static final Pattern DESCRIPTIVE_PREFIX_PATTERN =
Pattern.compile("((.+ )(for|to) )(.+)"); Pattern.compile("((.+ )(for|to) )(.+)");
/*
* Sample: global constructors keyed to cyg_libc_stdio_altout
*
* Pattern: global (constructors|destructors) keyed to text
*
* Parts:
* -global (constructors|destructors) keyed to (group 1)
* -text (group 3)
*
*/
private static final Pattern GLOBAL_CTOR_DTOR_FOR_PATTERN =
Pattern.compile("(global (constructors|destructors) keyed to )(.+)");
/** /**
* The c 'decltype' keyword pattern * The c 'decltype' keyword pattern
*/ */
@ -446,6 +459,13 @@ public class GnuDemanglerParser {
return new ArrayHandler(demangled, prefix, type); return new ArrayHandler(demangled, prefix, type);
} }
Matcher globalCtorMatcher = GLOBAL_CTOR_DTOR_FOR_PATTERN.matcher(demangled);
if (globalCtorMatcher.matches()) {
prefix = globalCtorMatcher.group(1);
type = globalCtorMatcher.group(3);
return new GlobalCtorDtorHandler(demangled, prefix, type);
}
return new ItemInNamespaceHandler(demangled, prefix, type); return new ItemInNamespaceHandler(demangled, prefix, type);
} }
@ -1524,13 +1544,11 @@ public class GnuDemanglerParser {
ItemInNamespaceHandler(String demangled) { ItemInNamespaceHandler(String demangled) {
super(demangled); super(demangled);
this.demangled = demangled;
this.type = demangled; this.type = demangled;
} }
ItemInNamespaceHandler(String demangled, String prefix, String item) { ItemInNamespaceHandler(String demangled, String prefix, String item) {
super(demangled); super(demangled);
this.demangled = demangled;
this.prefix = prefix; this.prefix = prefix;
this.type = item; this.type = item;
} }
@ -1542,6 +1560,40 @@ public class GnuDemanglerParser {
} }
} }
private class GlobalCtorDtorHandler extends SpecialPrefixHandler {
GlobalCtorDtorHandler(String demangled, String prefix, String item) {
super(demangled);
this.prefix = prefix;
this.type = item;
}
@Override
DemangledObject doBuild(Demangled namespace) {
//
// Since we are for constructors/destructors, assume each item is function
//
String functionName = type;
if (!functionName.contains("(")) {
// add parens so the type will be parsed as a function
functionName += "()";
}
DemangledObject demangledFunction = parseFunctionOrVariable(functionName);
demangledFunction.setOriginalDemangled(demangled);
// e.g., global.constructors.keyed.to.functionName
String parsedFunctionName = demangledFunction.getName();
String prefixNoSpaces = prefix.replaceAll("\s", "\\.");
String fullName = prefixNoSpaces + parsedFunctionName;
demangledFunction.setName(fullName);
demangledFunction.setBackupPlateComment(demangled);
return demangledFunction;
}
}
private class ArrayHandler extends SpecialPrefixHandler { private class ArrayHandler extends SpecialPrefixHandler {
private String arrayType; private String arrayType;
@ -1576,9 +1628,8 @@ public class GnuDemanglerParser {
// //
if ("char".equals(arrayType) && type.contains("StringLiteral")) { if ("char".equals(arrayType) && type.contains("StringLiteral")) {
// treat a char[] as a string // treat a char[] as a string
DemangledString ds = DemangledString ds = new DemangledString(variable.getMangledString(), demangled,
new DemangledString(variable.getMangledString(), demangled, type, type, type, type, -1 /*unknown length*/, false);
-1 /*unknown length*/, false);
ds.setSpecialPrefix(prefix); ds.setSpecialPrefix(prefix);
return ds; return ds;
} }

View file

@ -2216,8 +2216,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
assertName(object, assertName(object,
"__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>", "__allocate_at_least[abi:v160006]<std::__1::allocator<std::__1::unique_ptr<void,applesauce::raii::v1::detail::opaque_deletion_functor<void*,&VPTimeFreqConverter_Dispose>>>>",
"std", "std", "__1");
"__1");
String signature = object.getSignature(false); String signature = object.getSignature(false);
assertEquals( assertEquals(
@ -2225,6 +2224,60 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
signature); signature);
} }
@Test
public void testGlobalConstructor() throws Exception {
//
// mangled: _GLOBAL__I_cyg_libc_stdio_altout
//
// demangled: global constructors keyed to cyg_libc_stdio_altout
//
// updated name: global.constructors.keyed.to.cyg_libc_stdio_altout
//
String mangled = "_GLOBAL__I_cyg_libc_stdio_altout";
String demangled = process.demangle(mangled);
DemangledObject object = parser.parse(mangled, demangled);
assertNotNull(object);
assertType(object, DemangledFunction.class);
assertEquals("global constructors keyed to cyg_libc_stdio_altout",
object.getOriginalDemangled());
assertName(object, "global.constructors.keyed.to.cyg_libc_stdio_altout");
String signature = object.getSignature(false);
assertEquals("undefined global.constructors.keyed.to.cyg_libc_stdio_altout(void)",
signature);
}
@Test
public void testGlobalDestructor() throws Exception {
//
// mangled: _GLOBAL__D_cyg_libc_stdio_altout
//
// demangled: global destructors keyed to cyg_libc_stdio_altout
//
// updated name: global.destructors.keyed.to.cyg_libc_stdio_altout
//
String mangled = "_GLOBAL__D_cyg_libc_stdio_altout";
String demangled = process.demangle(mangled);
DemangledObject object = parser.parse(mangled, demangled);
assertNotNull(object);
assertType(object, DemangledFunction.class);
assertEquals("global destructors keyed to cyg_libc_stdio_altout",
object.getOriginalDemangled());
assertName(object, "global.destructors.keyed.to.cyg_libc_stdio_altout");
String signature = object.getSignature(false);
assertEquals("undefined global.destructors.keyed.to.cyg_libc_stdio_altout(void)",
signature);
}
private void assertType(Demangled o, Class<?> c) { private void assertType(Demangled o, Class<?> c) {
assertTrue("Wrong demangled type. \nExpected " + c + "; \nfound " + o.getClass(), assertTrue("Wrong demangled type. \nExpected " + c + "; \nfound " + o.getClass(),
c.isInstance(o)); c.isInstance(o));