Merge remote-tracking branch 'origin/GP-7291-dragonmacher-gnu-demangler-global-init-function'

This commit is contained in:
Ryan Kurtz
2026-09-18 13:37:31 -04:00
5 changed files with 51 additions and 17 deletions

View File

@@ -17,6 +17,7 @@ package ghidra.app.util.demangler;
import java.util.Objects; import java.util.Objects;
import generic.json.Json;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@@ -77,4 +78,8 @@ public class MangledContext {
return address; return address;
} }
@Override
public String toString() {
return Json.toString(this);
}
} }

View File

@@ -120,12 +120,13 @@ public class GnuDemangler implements Demangler {
DemangledObject demangledObject = DemangledObject demangledObject =
parse(originalMangled, process, demangled, options); parse(originalMangled, process, demangled, options);
if (demangledObject == null) { if (demangledObject == null) {
return demangledObject; return null;
} }
if (globalPrefix != null) { if (globalPrefix != null) {
String prefix = translateGlobalPrefix(globalPrefix);
DemangledFunction dfunc = new DemangledFunction(originalMangled, demangled, DemangledFunction dfunc = new DemangledFunction(originalMangled, demangled,
globalPrefix + demangledObject.getName()); prefix + demangledObject.getName());
dfunc.setNamespace(demangledObject.getNamespace()); dfunc.setNamespace(demangledObject.getNamespace());
demangledObject = dfunc; demangledObject = dfunc;
} }
@@ -152,6 +153,17 @@ public class GnuDemangler implements Demangler {
} }
} }
private String translateGlobalPrefix(String globalPrefix) {
return switch (globalPrefix) {
case "_GLOBAL__sub_I_" -> "global_init_constructor_";
case "_GLOBAL__sub_D_" -> "global_destructor_";
// case "_GLOBAL__N_" // anonymous namespace; only seen inside mangled text
// case "_GLOBAL__sub_G__" // debugging info; not seen in the wild
default -> globalPrefix;
};
}
private GnuDemanglerOptions getGnuOptions(DemanglerOptions options) { private GnuDemanglerOptions getGnuOptions(DemanglerOptions options) {
if (options instanceof GnuDemanglerOptions) { if (options instanceof GnuDemanglerOptions) {

View File

@@ -15,6 +15,7 @@
*/ */
package ghidra.app.util.demangler.gnu; package ghidra.app.util.demangler.gnu;
import generic.json.Json;
import ghidra.app.util.demangler.DemanglerOptions; import ghidra.app.util.demangler.DemanglerOptions;
/** /**
@@ -83,7 +84,7 @@ public class GnuDemanglerOptions extends DemanglerOptions {
public GnuDemanglerOptions(GnuDemanglerFormat format, boolean isDeprecated) { public GnuDemanglerOptions(GnuDemanglerFormat format, boolean isDeprecated) {
this(format, isDeprecated, GnuDemanglerOptions.DEFAULT_TIMEOUT_SECONDS); this(format, isDeprecated, GnuDemanglerOptions.DEFAULT_TIMEOUT_SECONDS);
} }
/** /**
* Constructor to specify the format to use, whether to prefer the deprecated format when * Constructor to specify the format to use, whether to prefer the deprecated format when
* both deprecated and modern are available, and the timeout * both deprecated and modern are available, and the timeout
@@ -219,16 +220,6 @@ public class GnuDemanglerOptions extends DemanglerOptions {
@Override @Override
public String toString() { public String toString() {
//@formatter:off return Json.toString(this);
return "{\n" +
"\tdoDisassembly: " + doDisassembly() + ",\n" +
"\tapplySignature: " + applySignature() + ",\n" +
"\tuseStandardReplacements: " + useStandardReplacements + ",\n" +
"\tdemangleOnlyKnownPatterns: " + demangleOnlyKnownPatterns() + ",\n" +
"\ttimeout (sec): " + timeout + ",\n" +
"\tdemanglerName: " + getDemanglerName() + ",\n" +
"\tdemanglerApplicationArguments: " + getDemanglerApplicationArguments() + ",\n" +
"}";
//@formatter:on
} }
} }

View File

@@ -1410,7 +1410,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
// //
// //
// Mangled: _ZN12_GLOBAL__N_120decode_charset_iconvEPKc // Mangled: _ZNK17GCC_IndicationPDUcvRK31GCC_ApplicationInvokeIndicationEv
// //
// Demangled: GCC_IndicationPDU::operator GCC_ApplicationInvokeIndication const&() const // Demangled: GCC_IndicationPDU::operator GCC_ApplicationInvokeIndication const&() const
// //

View File

@@ -150,7 +150,9 @@ public class GnuDemanglerTest extends AbstractGenericTest {
GnuDemanglerOptions options = new GnuDemanglerOptions(); GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setUseStandardReplacements(true); options.setUseStandardReplacements(true);
DemangledFunction dobj = (DemangledFunction) demangler.demangle(mangled, options); MangledContext context = new MangledContext(program, options, mangled, null);
DemangledFunction dobj = (DemangledFunction) demangler.demangle(context);
assertNotNull(dobj); assertNotNull(dobj);
String signature = dobj.getSignature(); String signature = dobj.getSignature();
@@ -172,7 +174,8 @@ public class GnuDemanglerTest extends AbstractGenericTest {
// Now disable demangled string replacement // Now disable demangled string replacement
// //
options.setUseStandardReplacements(false); options.setUseStandardReplacements(false);
dobj = (DemangledFunction) demangler.demangle(mangled, options); context = new MangledContext(program, options, mangled, null);
dobj = (DemangledFunction) demangler.demangle(context);
assertNotNull(dobj); assertNotNull(dobj);
String fullSignature = dobj.getSignature(); String fullSignature = dobj.getSignature();
@@ -233,6 +236,29 @@ public class GnuDemanglerTest extends AbstractGenericTest {
assertTrue(d.isPointer()); assertTrue(d.isPointer());
} }
@Test
public void testGlobalInitializationFunction() throws Exception {
/*
Mangled: _GLOBAL__sub_I__ZN6ghidra8ATTRIB_AE
We parse this as a DemangledVariable. We then us the '_GLOBAL__sub_I_' prefix as
a signal that the symbol represents a global initialization constructor. We then
convert the variable to a DemangledFunction.
Signature: ghidra::global_init_constructor_ATTRIB_A(void)
*/
String mangled = "_GLOBAL__sub_I__ZN6ghidra8ATTRIB_AE";
GnuDemangler demangler = new GnuDemangler();
DemangledFunction obj = (DemangledFunction) demangler.demangle(mangled);
String signature = obj.getSignature();
assertEquals("ghidra::global_init_constructor_ATTRIB_A(void)", signature);
}
@Test @Test
public void testDemangleTypeInfoName() throws Exception { public void testDemangleTypeInfoName() throws Exception {