GP-6515 - MicrosoftDemangler - fix warnings and tests; change default UDT tags; change source of defaults of options panels

This commit is contained in:
ghizard
2026-02-27 13:40:48 -05:00
parent 872d4d2c92
commit 8a8245f8b9
9 changed files with 67 additions and 85 deletions
@@ -20,6 +20,7 @@ import ghidra.app.util.datatype.microsoft.DataValidationOptions;
import ghidra.app.util.datatype.microsoft.MSDataTypeUtils; import ghidra.app.util.datatype.microsoft.MSDataTypeUtils;
import ghidra.app.util.demangler.*; import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.microsoft.MicrosoftDemangler; import ghidra.app.util.demangler.microsoft.MicrosoftDemangler;
import ghidra.app.util.demangler.microsoft.MicrosoftMangledContext;
import ghidra.docking.settings.SettingsImpl; import ghidra.docking.settings.SettingsImpl;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
@@ -624,7 +625,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
Address address) { Address address) {
MicrosoftDemangler demangler = new MicrosoftDemangler(); MicrosoftDemangler demangler = new MicrosoftDemangler();
try { try {
MangledContext mangledContext = MicrosoftMangledContext mangledContext =
demangler.createMangledContext(mangledString, null, program, address); demangler.createMangledContext(mangledString, null, program, address);
DemangledDataType demangledType = demangler.demangleType(mangledContext); DemangledDataType demangledType = demangler.demangleType(mangledContext);
if (isPermittedType(demangledType)) { if (isPermittedType(demangledType)) {
@@ -16,7 +16,8 @@
package ghidra.app.plugin.core.analysis; package ghidra.app.plugin.core.analysis;
import ghidra.app.util.demangler.*; import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.microsoft.*; import ghidra.app.util.demangler.microsoft.MicrosoftDemangler;
import ghidra.app.util.demangler.microsoft.MicrosoftDemanglerOptions;
import ghidra.app.util.demangler.microsoft.options.*; import ghidra.app.util.demangler.microsoft.options.*;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.OptionType; import ghidra.framework.options.OptionType;
@@ -34,40 +35,16 @@ public class MicrosoftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
"After a function is created, this analyzer will attempt to demangle " + "After a function is created, this analyzer will attempt to demangle " +
"the name and apply datatypes to parameters."; "the name and apply datatypes to parameters.";
public static final String OPTION_NAME_APPLY_SIGNATURE = "Apply Function Signatures"; public static final String APPLY_OPTIONS_LABEL = "msdApplyOptions";
private static final String OPTION_DESCRIPTION_APPLY_SIGNATURE =
"Apply any recovered function signature, in addition to the function name";
public static final String OPTION_NAME_APPLY_CALLING_CONVENTION =
"Apply Function Calling Conventions";
private static final String OPTION_DESCRIPTION_APPLY_CALLING_CONVENTION =
"Apply any recovered function signature calling convention";
private static final String OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS =
"Demangle Only Known Mangled Symbols";
private static final String OPTION_DESCRIPTION_USE_KNOWN_PATTERNS =
"Only demangle symbols that follow known compiler mangling patterns. " +
"Leaving this option off may cause non-mangled symbols to get demangled.";
public static final String OPTION_NAME_MS_C_INTERPRETATION =
"C-Style Symbol Interpretation";
private static final String OPTION_DESCRIPTION_MS_C_INTERPRETATION =
"When ambiguous, treat C-Style mangled symbol as: function, variable," +
" or function if a function exists";
private boolean applyFunctionSignature = true;
private boolean applyCallingConvention = true;
private boolean demangleOnlyKnownPatterns = false;
private MsCInterpretation interpretation = MsCInterpretation.FUNCTION_IF_EXISTS;
private static final String APPLY_OPTIONS_LABEL = "msdApplyOptions";
private static final String OUTPUT_OPTIONS_LABEL = "msdOutputOptions"; private static final String OUTPUT_OPTIONS_LABEL = "msdOutputOptions";
private MsdApplyOption applyOption; private MsdApplyOption applyOption;
private MsdOutputOption outputOption; private MsdOutputOption outputOption;
private MicrosoftDemanglerOptions msOptions;
public MicrosoftDemanglerAnalyzer() { public MicrosoftDemanglerAnalyzer() {
super(NAME, DESCRIPTION); super(NAME, DESCRIPTION);
msOptions = new MicrosoftDemanglerOptions();
demangler = new MicrosoftDemangler(); demangler = new MicrosoftDemangler();
setDefaultEnablement(true); setDefaultEnablement(true);
} }
@@ -82,14 +59,18 @@ public class MicrosoftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer"); HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer");
options.registerOption(APPLY_OPTIONS_LABEL, OptionType.CUSTOM_TYPE, options.registerOption(APPLY_OPTIONS_LABEL, OptionType.CUSTOM_TYPE,
new MsdApplyOption(), help, "Configures how demangling is applied", new MsdApplyOption(msOptions.demangleOnlyKnownPatterns(), msOptions.applySignature(),
msOptions.applyCallingConvention(), msOptions.getInterpretation()),
help, "Configures how demangling is applied",
() -> new MsdApplyOptionsEditor()); () -> new MsdApplyOptionsEditor());
applyOption = applyOption =
(MsdApplyOption) options.getCustomOption(APPLY_OPTIONS_LABEL, null); (MsdApplyOption) options.getCustomOption(APPLY_OPTIONS_LABEL, null);
options.registerOption(OUTPUT_OPTIONS_LABEL, OptionType.CUSTOM_TYPE, options.registerOption(OUTPUT_OPTIONS_LABEL, OptionType.CUSTOM_TYPE,
new MsdOutputOption(), help, "Controls demangled output", new MsdOutputOption(msOptions.getUseEncodedAnonymousNamespace(),
() -> new MsdOutputOptionsEditor()); msOptions.getApplyUdtArgumentTypeTag()),
help, "Controls demangled output", () -> new MsdOutputOptionsEditor());
outputOption = (MsdOutputOption) options.getCustomOption(OUTPUT_OPTIONS_LABEL, null); outputOption = (MsdOutputOption) options.getCustomOption(OUTPUT_OPTIONS_LABEL, null);
} }
@@ -98,19 +79,18 @@ public class MicrosoftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
applyOption = (MsdApplyOption) options.getCustomOption(APPLY_OPTIONS_LABEL, applyOption); applyOption = (MsdApplyOption) options.getCustomOption(APPLY_OPTIONS_LABEL, applyOption);
outputOption = outputOption =
(MsdOutputOption) options.getCustomOption(OUTPUT_OPTIONS_LABEL, outputOption); (MsdOutputOption) options.getCustomOption(OUTPUT_OPTIONS_LABEL, outputOption);
msOptions.setApplySignature(applyOption.applySignature());
msOptions.setApplyCallingConvention(applyOption.applyCallingConvention());
msOptions.setDemangleOnlyKnownPatterns(applyOption.demangleOnlyKnownPatterns());
msOptions.setInterpretation(applyOption.getInterpretation());
msOptions.setUseEncodedAnonymousNamespace(outputOption.getUseEncodedAnonymousNamespace());
msOptions.setApplyUdtArgumentTypeTag(outputOption.getApplyUdtArgumentTypeTag());
msOptions.setErrorOnRemainingChars(true);
} }
@Override @Override
protected DemanglerOptions getOptions() { protected DemanglerOptions getOptions() {
MicrosoftDemanglerOptions options = new MicrosoftDemanglerOptions(); return msOptions;
options.setApplySignature(applyOption.applySignature());
options.setApplyCallingConvention(applyOption.applyCallingConvention());
options.setDemangleOnlyKnownPatterns(applyOption.demangleOnlyKnownPatterns());
options.setInterpretation(applyOption.getInterpretation());
options.setUseEncodedAnonymousNamespace(outputOption.getUseEncodedAnonymousNamespace());
options.setApplyUdtArgumentTypeTag(outputOption.getApplyUdtArgumentTypeTag());
options.setErrorOnRemainingChars(true);
return options;
} }
@Override @Override
@@ -69,7 +69,7 @@ public class MicrosoftDemanglerOptions extends DemanglerOptions {
errorOnRemainingChars = true; errorOnRemainingChars = true;
interpretation = MsCInterpretation.FUNCTION_IF_EXISTS; interpretation = MsCInterpretation.FUNCTION_IF_EXISTS;
useEncodedAnonymousNamespace = true; useEncodedAnonymousNamespace = true;
applyUdtArgumentTypeTag = true; applyUdtArgumentTypeTag = false;
} }
/** /**
@@ -38,20 +38,20 @@ public class MsdApplyOption extends DemanglerOptions implements CustomOption {
private static final String APPLY_CALLING_CONVENTION = "applyFunctionCallingConventions"; private static final String APPLY_CALLING_CONVENTION = "applyFunctionCallingConventions";
private static final String MS_C_INTERPRETATION = "C-StyleSymbolInterpretation"; private static final String MS_C_INTERPRETATION = "C-StyleSymbolInterpretation";
private static boolean DEFAULT_DEMANGLE_USE_KNOWN_PATTERNS = false;
private static boolean DEFAULT_APPLY_SIGNATURE = true;
private static boolean DEFAULT_APPLY_CALLING_CONVENTION = true;
private static MsCInterpretation DEFAULT_MS_C_INTERPRETATION =
MsCInterpretation.FUNCTION_IF_EXISTS;
private MsCInterpretation interpretation; private MsCInterpretation interpretation;
public MsdApplyOption() { public MsdApplyOption() {
// required for persistence, but also using for overriding initializations of parent // required for persistence, but must set some initial values even though they will
setDemangleOnlyKnownPatterns(DEFAULT_DEMANGLE_USE_KNOWN_PATTERNS); // get overridden by writeState.
setApplySignature(DEFAULT_APPLY_SIGNATURE); this(false, false, false, MsCInterpretation.FUNCTION_IF_EXISTS);
setApplyCallingConvention(DEFAULT_APPLY_CALLING_CONVENTION); }
interpretation = DEFAULT_MS_C_INTERPRETATION;
public MsdApplyOption(boolean demangleOnlyKnownPatternsArg, boolean applySignatureArg,
boolean applyCallingConventionArg, MsCInterpretation interpretationArg) {
setDemangleOnlyKnownPatterns(demangleOnlyKnownPatternsArg);
setApplySignature(applySignatureArg);
setApplyCallingConvention(applyCallingConventionArg);
interpretation = interpretationArg;
} }
/** /**
@@ -194,11 +194,9 @@ public class MsdApplyOptionsEditor extends PropertyEditorSupport
} }
private MsdApplyOption cloneNamespaceValues() { private MsdApplyOption cloneNamespaceValues() {
MsdApplyOption newOptions = new MsdApplyOption(); MsdApplyOption newOptions = new MsdApplyOption(knownPatternsCb.isSelected(),
newOptions.setApplySignature(signatureCb.isSelected()); signatureCb.isSelected(), callingConventionCb.isSelected(),
newOptions.setApplyCallingConvention(callingConventionCb.isSelected()); (MsCInterpretation) interpretationComboBox.getSelectedItem());
newOptions.setDemangleOnlyKnownPatterns(knownPatternsCb.isSelected());
newOptions.setInterpretation((MsCInterpretation) interpretationComboBox.getSelectedItem());
return newOptions; return newOptions;
} }
@@ -18,6 +18,7 @@ package ghidra.app.util.demangler.microsoft.options;
import java.util.Objects; import java.util.Objects;
import ghidra.app.plugin.core.analysis.MicrosoftDemanglerAnalyzer; import ghidra.app.plugin.core.analysis.MicrosoftDemanglerAnalyzer;
import ghidra.app.util.demangler.microsoft.MicrosoftDemanglerOptions;
import ghidra.framework.options.CustomOption; import ghidra.framework.options.CustomOption;
import ghidra.framework.options.GProperties; import ghidra.framework.options.GProperties;
@@ -33,14 +34,18 @@ public class MsdOutputOption implements CustomOption {
private static final String USE_ENCODED_ANONYMOUS_NAMESPACE = "useEncodedAnonymousNamespace"; private static final String USE_ENCODED_ANONYMOUS_NAMESPACE = "useEncodedAnonymousNamespace";
private static final String APPLY_TEMPLATE_ARG_TAGS = "applyTagsTemplateArgumentTags"; private static final String APPLY_TEMPLATE_ARG_TAGS = "applyTagsTemplateArgumentTags";
private static boolean DEFAULT_USE_ENCODED_ANONYMOUS_NAMESPACE = true; private boolean useEncodedAnonymousNamespace;
private static boolean DEFAULT_APPLY_TEMPLATE_ARG_TAGS = true; private boolean applyUdtArgumentTypeTag;
private boolean useEncodedAnonymousNamespace = DEFAULT_USE_ENCODED_ANONYMOUS_NAMESPACE;
private boolean applyUdtArgumentTypeTag = DEFAULT_APPLY_TEMPLATE_ARG_TAGS;
public MsdOutputOption() { public MsdOutputOption() {
// required for persistence // required for persistence, but must set some initial values even though they will
// get overridden by writeState.
this(false, false);
}
public MsdOutputOption(boolean useEncodedAnonymousNamespace, boolean applyUdtArgumentTypeTag) {
this.useEncodedAnonymousNamespace = useEncodedAnonymousNamespace;
this.applyUdtArgumentTypeTag = applyUdtArgumentTypeTag;
} }
/** /**
@@ -135,9 +135,8 @@ public class MsdOutputOptionsEditor extends PropertyEditorSupport implements Cus
} }
private MsdOutputOption cloneNamespaceValues() { private MsdOutputOption cloneNamespaceValues() {
MsdOutputOption newOption = new MsdOutputOption(); MsdOutputOption newOption =
newOption.setUseEncodedAnonymousNamespace(useEncodedAnonNsCb.isSelected()); new MsdOutputOption(useEncodedAnonNsCb.isSelected(), useUdtTagsCb.isSelected());
newOption.setApplyUdtArgumentTypeTag(useUdtTagsCb.isSelected());
return newOption; return newOption;
} }
@@ -21,6 +21,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import ghidra.app.cmd.label.AddLabelCmd; import ghidra.app.cmd.label.AddLabelCmd;
import ghidra.app.util.demangler.microsoft.options.MsdApplyOption;
import ghidra.app.util.importer.MessageLog; import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.program.database.ProgramBuilder; import ghidra.program.database.ProgramBuilder;
@@ -70,7 +71,7 @@ public class MicrosoftDemanglerAnalyzerTest extends AbstractGhidraHeadedIntegrat
Address addr = addr("0x110"); Address addr = addr("0x110");
createSymbol(addr, mangled); createSymbol(addr, mangled);
setOption(MicrosoftDemanglerAnalyzer.OPTION_NAME_APPLY_SIGNATURE, true); setApplySignatureOption(true);
analyze(); analyze();
@@ -88,7 +89,7 @@ public class MicrosoftDemanglerAnalyzerTest extends AbstractGhidraHeadedIntegrat
Address addr = addr("0x110"); Address addr = addr("0x110");
createSymbol(addr, mangled); createSymbol(addr, mangled);
setOption(MicrosoftDemanglerAnalyzer.OPTION_NAME_APPLY_SIGNATURE, false); setApplySignatureOption(false);
analyze(); analyze();
@@ -129,22 +130,21 @@ public class MicrosoftDemanglerAnalyzerTest extends AbstractGhidraHeadedIntegrat
tx(program, () -> analyzer.added(program, program.getMemory(), TaskMonitor.DUMMY, log)); tx(program, () -> analyzer.added(program, program.getMemory(), TaskMonitor.DUMMY, log));
} }
private void setOption(String optionName, boolean doUse) { private void setApplySignatureOption(boolean doUse) {
String fullOptionName = analyzer.getName() + Options.DELIMITER_STRING + optionName; // Analyzers . Demangler Microsoft . msdApplyOptions . applyFunctionSignatures
Options options = program.getOptions("Analyzers");
for (String name : options.getOptionNames()) { Options analyzerOptions = program.getOptions(
if (name.equals(fullOptionName)) { "Analyzers" + Options.DELIMITER_STRING + MicrosoftDemanglerAnalyzer.NAME);
tx(program, () -> options.setBoolean(optionName, doUse));
// we must call this manually, since we are not using a tool MsdApplyOption applyOption =
analyzer.optionsChanged(options, program); (MsdApplyOption) analyzerOptions
return; .getCustomOption(MicrosoftDemanglerAnalyzer.APPLY_OPTIONS_LABEL, null);
}
}
fail("Could not find option '" + optionName + "'"); tx(program, () -> {
applyOption.setApplySignature(doUse);
});
analyzer.optionsChanged(analyzerOptions, program);
} }
private void registerOptions() { private void registerOptions() {
@@ -164,7 +164,6 @@ public abstract class AbstractComplexTypeApplier extends MsDataTypeApplier {
// type. We did not dig into where it got steered wrong, but presumed it was because of // type. We did not dig into where it got steered wrong, but presumed it was because of
// what we stated above. // what we stated above.
context.getOptions().setUseEncodedAnonymousNamespace(false); context.getOptions().setUseEncodedAnonymousNamespace(false);
context.getOptions().setApplyUdtArgumentTypeTag(false);
try { try {
mdemangler.demangleType(context); mdemangler.demangleType(context);
MDDataType mdDataType = mdemangler.getMdType(); MDDataType mdDataType = mdemangler.getMdType();