Merge remote-tracking branch

'origin/GP-94_dragonmacher_PR-2214_astrelsky_GnuDemangler' (fixes #2214)
This commit is contained in:
ghidra1 2021-02-16 13:24:50 -05:00
commit ed1580f4f9
15 changed files with 750 additions and 501 deletions

View file

@ -386,43 +386,28 @@
<U><B>Use Deprecated Demangler</B></U> -
By default, GCC symbols will be demangled using the most up-to-date demangler
that Ghidra contains (<B>version 2.33.1</B> as of this writing). Turning this
option on will also invoke the now deprecated previous version of the demangler
(<B>version 2.24</B>) if the preferred demangler cannot demangle a given symbol.
option on will invoke the now deprecated version of the demangler (<B>version 2.24</B>).
</P>
<P>
Support for older demangling styles was removed in <CODE>c++filt (v2.32)</CODE>.
Specifically, the following formats are no longer supported:
<CODE>Lucid, ARM, HP, and EDG</CODE>. To use these formats, you must enable
usage of the deprecated demangler, which is <B>version 2.24</B>. Further, you
may have to pass the required external demangler options using the Ghidra
option below.
<CODE>Lucid, ARM, HP, GNU, and EDG</CODE>. For these formats, the deprecated
demangler, which is <B>version 2.24</B>, will automatically be used.
</P>
<P>
<U><B>Use External Demangler Options</B></U> -
This allows users to pass settings to the demangler. As an example, you can enter
in this Ghidra option text field the following text to use the <CODE>rust</CODE>
format: <CODE>-s rust</CODE>. This is not needed for
normal operation. To see a full list of supported options, query each demangler
directly using the <CODE>--help</CODE> switch.
</P>
<P>
The GNU demanglers can be found at:
<CODE CLASS="path">
&lt;GHIDRA_INSTALL_DIR&gt;/GPL/DemanglerGnu/build/os/&lt;OS&gt;/
</CODE><BR>
</P>
<BLOCKQUOTE>
<P>
The available programs are:
<UL>
<LI><CODE>demangler_gnu_v2_33_1</CODE></LI>
<LI><CODE>demangler_gnu_v2_24</CODE></LI>
<LI><CODE CLASS="path">
&lt;GHIDRA_INSTALL_DIR&gt;/GPL/DemanglerGnu/os/&lt;OS&gt;/
</CODE><CODE>demangler_gnu_v2_33_1</CODE></LI>
<LI><CODE CLASS="path">
&lt;GHIDRA_INSTALL_DIR&gt;/GPL/DemanglerGnu/os/&lt;OS&gt;/
</CODE><CODE>demangler_gnu_v2_24</CODE></LI>
</UL>
</P>
<P style="background-color: #FFF0E0;">
<IMG SRC="../../shared/warning.png" />When using an external GNU demangler,
please understand the risks associated with using that version of the

View file

@ -16,7 +16,7 @@
package ghidra.app.util.demangler;
/**
* A simple class to contain the various settings for demangling.
* A simple class to contain the various settings for demangling
*/
public class DemanglerOptions {
@ -35,18 +35,18 @@ public class DemanglerOptions {
}
/**
* Checks if the apply signature option is currently set.
* Checks if the apply signature option is currently set
*
* @return true if set to apply function signatures that are demangled.
* @return true if set to apply function signatures that are demangled
*/
public boolean applySignature() {
return applySignature;
}
/**
* Set the option to apply function signatures that are demangled.
* Set the option to apply function signatures that are demangled
*
* @param applySignature true to apply function signatures that are demangled.
* @param applySignature true to apply function signatures that are demangled
*/
public void setApplySignature(boolean applySignature) {
this.applySignature = applySignature;
@ -54,9 +54,9 @@ public class DemanglerOptions {
/**
* Checks if the option to perform disassembly for known data structures (like functions) when
* demangling is set.
* demangling is set
*
* @return true if the option is set.
* @return true if the option is set
*/
public boolean doDisassembly() {
return doDisassembly;
@ -64,18 +64,18 @@ public class DemanglerOptions {
/**
* Sets the option to perform disassembly for known data structures (like functions) when
* demangling.
* demangling
*
* @param doDisassembly true to perform disassembly when demangling.
* @param doDisassembly true to perform disassembly when demangling
*/
public void setDoDisassembly(boolean doDisassembly) {
this.doDisassembly = doDisassembly;
}
/**
* Checks if the option to only demangle known mangled patterns is set.
* Checks if the option to only demangle known mangled patterns is set
*
* @return true if only known mangled patterns will be demangled.
* @return true if only known mangled patterns will be demangled
*/
public boolean demangleOnlyKnownPatterns() {
return demangleOnlyKnownPatterns;
@ -83,10 +83,15 @@ public class DemanglerOptions {
/**
* Sets the option to only demangle known mangled patterns. Setting this to false causes
* all symbols to be demangled, which may result in some symbols getting demangled that were not
* actually mangled symbols.
* most symbols to be demangled, which may result in some symbols getting demangled that were
* not actually mangled symbols.
*
* @param demangleOnlyKnownPatterns true to only demangle known mangled patterns.
* <P>Generally, a demangler will report an error if a symbol fails to demangle. Hence,
* clients can use this flag to prevent such errors, signalling to the demangler to only
* attempt those symbols that have a known start pattern. If the known start pattern list
* becomes comprehensive, then this flag can go away.
*
* @param demangleOnlyKnownPatterns true to only demangle known mangled patterns
*/
public void setDemangleOnlyKnownPatterns(boolean demangleOnlyKnownPatterns) {
this.demangleOnlyKnownPatterns = demangleOnlyKnownPatterns;

View file

@ -21,8 +21,7 @@
//@category Examples.Demangler
import ghidra.app.script.GhidraScript;
import ghidra.app.util.demangler.DemangledObject;
import ghidra.app.util.demangler.gnu.GnuDemangler;
import ghidra.app.util.demangler.gnu.GnuDemanglerOptions;
import ghidra.app.util.demangler.gnu.*;
import ghidra.program.model.symbol.Symbol;
public class DemangleElfWithOptionScript extends GhidraScript {
@ -33,8 +32,8 @@ public class DemangleElfWithOptionScript extends GhidraScript {
GnuDemangler demangler = new GnuDemangler();
if (!demangler.canDemangle(currentProgram)) {
String executableFormat = currentProgram.getExecutableFormat();
println("Cannot use the elf demangling options for executable format: " +
executableFormat);
println(
"Cannot use the elf demangling options for executable format: " + executableFormat);
return;
}
@ -49,14 +48,12 @@ public class DemangleElfWithOptionScript extends GhidraScript {
String mangled = symbol.getName();
GnuDemanglerOptions options = new GnuDemanglerOptions();
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, false);
options.setDoDisassembly(false);
options.setDemanglerApplicationArguments("-s auto");
/*
// for older formats use the deprecated demangler
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
options.setDemanglerApplicationArguments("-s arm");
options = options.withDemanglerFormat(GnuDemanglerFormat.ARM, true);
*/
DemangledObject demangledObject = demangler.demangle(mangled, options);

View file

@ -15,14 +15,15 @@
*/
package ghidra.app.plugin.core.analysis;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import docking.options.editor.BooleanEditor;
import ghidra.app.util.demangler.*;
import ghidra.app.util.demangler.gnu.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options;
import ghidra.framework.options.*;
import ghidra.program.model.listing.Program;
import ghidra.util.HelpLocation;
@ -51,15 +52,14 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
"Signals to use the deprecated demangler when the modern demangler cannot demangle a " +
"given string";
static final String OPTION_NAME_DEMANGLER_PARAMETERS =
"Use External Demangler Options";
private static final String OPTION_DESCRIPTION_DEMANGLER_PARAMETERS =
"Signals to use pass the given parameters to the demangler program";
static final String OPTION_NAME_DEMANGLER_FORMAT = "Demangler Format";
private static final String OPTION_DESCRIPTION_DEMANGLER_FORMAT =
"The demangling format to use";
private boolean doSignatureEnabled = true;
private boolean demangleOnlyKnownPatterns = false;
private GnuDemanglerFormat demanglerFormat = GnuDemanglerFormat.AUTO;
private boolean useDeprecatedDemangler = false;
private String demanglerParameters = "";
private GnuDemangler demangler = new GnuDemangler();
@ -75,20 +75,23 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
@Override
public void registerOptions(Options options, Program program) {
BooleanEditor editor = new BooleanEditor();
editor.setValue(Boolean.valueOf(useDeprecatedDemangler));
FormatEditor formatEditor = new FormatEditor(demanglerFormat, editor);
editor.addPropertyChangeListener(formatEditor);
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer");
options.registerOption(OPTION_NAME_APPLY_SIGNATURE, doSignatureEnabled, help,
OPTION_DESCRIPTION_APPLY_SIGNATURE);
options.registerOption(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns,
help,
OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
help, OPTION_DESCRIPTION_USE_KNOWN_PATTERNS);
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler, help,
OPTION_DESCRIPTION_DEPRECATED_DEMANGLER);
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
useDeprecatedDemangler, help, OPTION_DESCRIPTION_DEPRECATED_DEMANGLER, editor);
options.registerOption(OPTION_NAME_DEMANGLER_PARAMETERS, demanglerParameters, help,
OPTION_DESCRIPTION_DEMANGLER_PARAMETERS);
options.registerOption(OPTION_NAME_DEMANGLER_FORMAT, OptionType.ENUM_TYPE, demanglerFormat,
help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, formatEditor);
}
@Override
@ -96,94 +99,105 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
doSignatureEnabled = options.getBoolean(OPTION_NAME_APPLY_SIGNATURE, doSignatureEnabled);
demangleOnlyKnownPatterns =
options.getBoolean(OPTION_NAME_DEMANGLE_USE_KNOWN_PATTERNS, demangleOnlyKnownPatterns);
demanglerFormat = options.getEnum(OPTION_NAME_DEMANGLER_FORMAT, GnuDemanglerFormat.AUTO);
useDeprecatedDemangler =
options.getBoolean(OPTION_NAME_USE_DEPRECATED_DEMANGLER, useDeprecatedDemangler);
demanglerParameters =
options.getString(OPTION_NAME_DEMANGLER_PARAMETERS, demanglerParameters);
}
@Override
protected DemanglerOptions getOptions() {
GnuDemanglerOptions options = new GnuDemanglerOptions();
GnuDemanglerOptions options =
new GnuDemanglerOptions(demanglerFormat, useDeprecatedDemangler);
options.setDoDisassembly(true);
options.setApplySignature(doSignatureEnabled);
options.setDemangleOnlyKnownPatterns(demangleOnlyKnownPatterns);
options.setDemanglerApplicationArguments(demanglerParameters);
return options;
}
@Override
protected boolean validateOptions(DemanglerOptions demanglerOtions, MessageLog log) {
GnuDemanglerOptions options = (GnuDemanglerOptions) demanglerOtions;
String applicationArguments = options.getDemanglerApplicationArguments();
if (StringUtils.isBlank(applicationArguments)) {
return true;
}
// Check that the supplied arguments will work with at least one of the requested
// demanglers. (Different versions of the GNU demangler support different arguments.)
String demanglerName = options.getDemanglerName();
try {
GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName,
applicationArguments);
return true;
}
catch (IOException e) {
log.appendMsg(getName(), "Invalid options for GNU dangler '" + demanglerName +
"': " + applicationArguments);
log.appendException(e);
}
if (useDeprecatedDemangler) {
// see if the options work in the deprecated demangler
GnuDemanglerOptions deprecatedOptions = options.withDeprecatedDemangler();
String deprecatedName = deprecatedOptions.getDemanglerName();
try {
GnuDemanglerNativeProcess.getDemanglerNativeProcess(deprecatedName,
applicationArguments);
return true;
}
catch (IOException e) {
log.appendMsg(getName(),
"Invalid options for GNU dangler '" + deprecatedName + "': " +
applicationArguments);
log.appendException(e);
}
}
return false;
protected DemangledObject doDemangle(String mangled, DemanglerOptions demanglerOtions,
MessageLog log) throws DemangledException {
return demangler.demangle(mangled, demanglerOtions);
}
@Override
protected DemangledObject doDemangle(String mangled, DemanglerOptions demanglerOtions,
MessageLog log)
throws DemangledException {
private static class FormatEditor extends EnumEditor implements PropertyChangeListener {
GnuDemanglerOptions options = (GnuDemanglerOptions) demanglerOtions;
DemangledObject demangled = null;
try {
demangled = demangler.demangle(mangled, options);
private final FormatSelector selector;
private final BooleanEditor isDeprecated;
FormatEditor(GnuDemanglerFormat value, BooleanEditor isDeprecated) {
setValue(value);
this.isDeprecated = isDeprecated;
this.selector = new FormatSelector(this);
}
catch (DemangledException e) {
if (!useDeprecatedDemangler) {
throw e; // let our parent handle this
@Override
public boolean supportsCustomEditor() {
return true;
}
@Override
public FormatSelector getCustomEditor() {
return selector;
}
@Override
public GnuDemanglerFormat[] getEnums() {
return Arrays.stream(GnuDemanglerFormat.values())
.filter(this::filter)
.toArray(GnuDemanglerFormat[]::new);
}
@Override
public String[] getTags() {
return Arrays.stream(GnuDemanglerFormat.values())
.filter(this::filter)
.map(GnuDemanglerFormat::name)
.toArray(String[]::new);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
GnuDemanglerFormat format = selector.getFormat();
selector.reset(getTags());
if (format.isAvailable(isDeprecatedDemangler())) {
setValue(format);
selector.setFormat(format);
}
else {
setValue(GnuDemanglerFormat.AUTO);
}
}
if (demangled != null) {
return demangled;
private boolean isDeprecatedDemangler() {
return (Boolean) isDeprecated.getValue();
}
if (useDeprecatedDemangler) {
GnuDemanglerOptions newOptions = options.withDeprecatedDemangler();
demangled = demangler.demangle(mangled, newOptions);
private boolean filter(GnuDemanglerFormat f) {
return f.isAvailable(isDeprecatedDemangler());
}
}
private static class FormatSelector extends PropertySelector {
public FormatSelector(FormatEditor fe) {
super(fe);
}
void reset(String[] tags) {
removeAllItems();
for (String tag : tags) {
addItem(tag);
}
}
GnuDemanglerFormat getFormat() {
return GnuDemanglerFormat.valueOf((String) getSelectedItem());
}
void setFormat(GnuDemanglerFormat format) {
setSelectedItem(format.name());
}
return demangled;
}
}

View file

@ -72,11 +72,11 @@ public class GnuDemangler implements Demangler {
public DemangledObject demangle(String mangled, DemanglerOptions demanglerOtions)
throws DemangledException {
if (skip(mangled, demanglerOtions)) {
GnuDemanglerOptions options = getGnuOptions(demanglerOtions);
if (skip(mangled, options)) {
return null;
}
GnuDemanglerOptions options = getGnuOptions(demanglerOtions);
String originalMangled = mangled;
String globalPrefix = null;
if (mangled.startsWith(GLOBAL_PREFIX)) {
@ -106,16 +106,14 @@ public class GnuDemangler implements Demangler {
}
boolean onlyKnownPatterns = options.demangleOnlyKnownPatterns();
DemangledObject demangledObject =
parse(mangled, process, demangled, onlyKnownPatterns);
DemangledObject demangledObject = parse(mangled, process, demangled, onlyKnownPatterns);
if (demangledObject == null) {
return demangledObject;
}
if (globalPrefix != null) {
DemangledFunction dfunc =
new DemangledFunction(originalMangled, demangled,
globalPrefix + demangledObject.getName());
DemangledFunction dfunc = new DemangledFunction(originalMangled, demangled,
globalPrefix + demangledObject.getName());
dfunc.setNamespace(demangledObject.getNamespace());
demangledObject = dfunc;
}
@ -163,7 +161,20 @@ public class GnuDemangler implements Demangler {
applicationOptions);
}
private boolean skip(String mangled, DemanglerOptions options) {
/**
* Determines if the given mangled string should not be demangled. There are a couple
* patterns that will always be skipped.
* If {@link GnuDemanglerOptions#demangleOnlyKnownPatterns()} is true, then only mangled
* symbols matching a list of known start patters will not be skipped.
*
* <P>This demangler class will default to demangling most patterns, since we do not yet
* have a comprehensive list of known start patterns.
*
* @param mangled the mangled string
* @param options the options
* @return true if the string should not be demangled
*/
private boolean skip(String mangled, GnuDemanglerOptions options) {
// Ignore versioned symbols which are generally duplicated at the same address
if (mangled.indexOf("@") > 0) { // do not demangle versioned symbols
@ -179,20 +190,21 @@ public class GnuDemangler implements Demangler {
return false; // let it go through
}
// add to this list if we find any other known GNU start patterns
// This is the current list of known demangler start patterns. Add to this list if we
// find any other known GNU start patterns.
if (mangled.startsWith("_Z")) {
return false;
}
else if (mangled.startsWith("__Z")) {
if (mangled.startsWith("__Z")) {
return false;
}
else if (mangled.startsWith("h__")) {
if (mangled.startsWith("h__")) {
return false; // not sure about this one
}
else if (mangled.startsWith("?")) {
if (mangled.startsWith("?")) {
return false; // not sure about this one
}
else if (isGnu2Or3Pattern(mangled)) {
if (isGnu2Or3Pattern(mangled)) {
return false;
}
@ -200,8 +212,7 @@ public class GnuDemangler implements Demangler {
}
private DemangledObject parse(String mangled, GnuDemanglerNativeProcess process,
String demangled,
boolean demangleOnlyKnownPatterns) {
String demangled, boolean demangleOnlyKnownPatterns) {
if (demangleOnlyKnownPatterns && !isKnownMangledString(mangled, demangled)) {
return null;

View file

@ -0,0 +1,92 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.demangler.gnu;
/**
* Enum representation of the available GnuDemangler formats
*/
public enum GnuDemanglerFormat {
// OLD: none,auto,gnu,lucid,arm,hp,edg,gnu-v3,java,gnat
// NEW: none,auto,gnu-v3,java,gnat,dlang,rust
/** Automatic mangling format detection */
AUTO("", Version.ALL),
/** GNUv2 mangling format */
GNU("gnu", Version.DEPRECATED),
/** lucid mangling format */
LUCID("lucid", Version.DEPRECATED),
/** arm mangling format */
ARM("arm", Version.DEPRECATED),
/** hp mangling format */
HP("hp", Version.DEPRECATED),
/** mangling format used by the Edison Design Group (EDG) compiler */
EDG("edg", Version.DEPRECATED),
/** GNUv3 mangling format */
GNUV3("gnu-v3", Version.ALL),
/** Java mangling format */
JAVA("java", Version.ALL),
/** GNAT Ada compiler mangling format */
GNAT("gnat", Version.ALL),
/** D mangling format */
DLANG("dlang", Version.MODERN),
/** Rust mangling format */
RUST("rust", Version.MODERN);
/** the format option string used by the native demangler */
private final String format;
private final Version version;
private GnuDemanglerFormat(String format, Version version) {
this.format = format;
this.version = version;
}
/**
* Checks if this format is available in the deprecated gnu demangler
* @return true if this format is available in the deprecated gnu demangler
*/
public boolean isDeprecatedFormat() {
return version == Version.DEPRECATED || version == Version.ALL;
}
/**
* Checks if this format is available in a modern version of the gnu demangler
* @return true if this format is available in a modern version of the gnu demangler
*/
public boolean isModernFormat() {
return version == Version.MODERN || version == Version.ALL;
}
/**
* Checks if this format is available for the specified demangler
* @param isDeprecated true for the deprecated demangler, false for the modern demangler
* @return true if the format is available
*/
public boolean isAvailable(boolean isDeprecated) {
return isDeprecated ? isDeprecatedFormat() : isModernFormat();
}
/**
* Gets the format option to be passed to the demangler via the <code>-s</code> option
* @return the format option to be passed to the demangler
*/
public String getFormat() {
return format;
}
private enum Version {
DEPRECATED, MODERN, ALL
}
}

View file

@ -43,21 +43,67 @@ public class GnuDemanglerOptions extends DemanglerOptions {
*/
public static final String GNU_DEMANGLER_DEFAULT = GNU_DEMANGLER_V2_33_1;
private String demanglerName = GNU_DEMANGLER_DEFAULT;
private String demanglerApplicationArguments;
private final GnuDemanglerFormat format;
private final boolean isDeprecated;
/**
* Default constructor to use the modern demangler with auto-detect for the format. This
* constructor will limit demangling to only known symbols.
*/
public GnuDemanglerOptions() {
// use default values
this(GnuDemanglerFormat.AUTO);
}
/**
* Constructor to specify a particular format
*
* @param format signals to use the given format
*/
public GnuDemanglerOptions(GnuDemanglerFormat format) {
this(format, !format.isModernFormat());
}
/**
* Constructor to specify the format to use and whether to prefer the deprecated format when
* both deprecated and modern are available
*
* @param format the format
* @param isDeprecated true if the format is not available in the modern demangler
* @throws IllegalArgumentException if the given format is not available in the deprecated
* demangler
*/
public GnuDemanglerOptions(GnuDemanglerFormat format, boolean isDeprecated) {
this.format = format;
this.isDeprecated = isDeprecated;
if (!format.isAvailable(isDeprecated)) {
throw new IllegalArgumentException(
format.name() + " is not available in the " + getDemanglerName());
}
}
/**
* Copy constructor to create a version of this class from a more generic set of options
* @param copy the options to copy
*/
public GnuDemanglerOptions(DemanglerOptions copy) {
super(copy);
if (copy instanceof GnuDemanglerOptions) {
GnuDemanglerOptions gCopy = (GnuDemanglerOptions) copy;
demanglerName = gCopy.demanglerName;
demanglerApplicationArguments = gCopy.demanglerApplicationArguments;
format = gCopy.format;
isDeprecated = gCopy.isDeprecated;
}
else {
format = GnuDemanglerFormat.AUTO;
isDeprecated = false;
}
}
private GnuDemanglerOptions(GnuDemanglerOptions copy, GnuDemanglerFormat format,
boolean deprecated) {
super(copy);
this.format = format;
this.isDeprecated = deprecated;
}
/**
@ -66,15 +112,29 @@ public class GnuDemanglerOptions extends DemanglerOptions {
* @return the name
*/
public String getDemanglerName() {
return demanglerName;
return isDeprecated ? GNU_DEMANGLER_V2_24 : GNU_DEMANGLER_V2_33_1;
}
/**
* Sets the external demangler executable name to be used for demangling
* @param name the name
* A convenience method to copy the state of this options object, changing the
* demangler executable name and demangler format to the specified values
*
* @param demanglerFormat the demangling format to use
* @param useDeprecated true to use the deprecated gnu demangler, else false
* @return the new options
* @throws IllegalArgumentException if the current format is not available in the
* selected demangler.
*/
public void setDemanglerName(String name) {
this.demanglerName = name;
public GnuDemanglerOptions withDemanglerFormat(GnuDemanglerFormat demanglerFormat,
boolean useDeprecated) throws IllegalArgumentException {
if (this.format == demanglerFormat && this.isDeprecated == useDeprecated) {
return this;
}
if (demanglerFormat.isAvailable(useDeprecated)) {
return new GnuDemanglerOptions(this, demanglerFormat, useDeprecated);
}
throw new IllegalArgumentException(
demanglerFormat.name() + " is not available in the " + getDemanglerName());
}
/**
@ -82,26 +142,19 @@ public class GnuDemanglerOptions extends DemanglerOptions {
* @return the arguments
*/
public String getDemanglerApplicationArguments() {
return demanglerApplicationArguments;
if (format == GnuDemanglerFormat.AUTO) {
// no format argument
return "";
}
return "-s " + format.getFormat();
}
/**
* Sets the arguments to be passed to the external demangler executable
* @param args the arguments
* Gets the current demangler format
* @return the demangler format
*/
public void setDemanglerApplicationArguments(String args) {
this.demanglerApplicationArguments = args;
}
/**
* A convenience method to copy the state of this options object, changing the
* demangler executable name to the deprecated demangler
* @return the new options
*/
public GnuDemanglerOptions withDeprecatedDemangler() {
GnuDemanglerOptions newOptions = new GnuDemanglerOptions(this);
newOptions.setDemanglerName(GNU_DEMANGLER_V2_24);
return newOptions;
public GnuDemanglerFormat getDemanglerFormat() {
return format;
}
@Override
@ -111,8 +164,8 @@ public class GnuDemanglerOptions extends DemanglerOptions {
"\tdoDisassembly: " + doDisassembly() + ",\n" +
"\tapplySignature: " + applySignature() + ",\n" +
"\tdemangleOnlyKnownPatterns: " + demangleOnlyKnownPatterns() + ",\n" +
"\tdemanglerName: " + demanglerName + ",\n" +
"\tdemanglerApplicationArguments: " + demanglerApplicationArguments + ",\n" +
"\tdemanglerName: " + getDemanglerName() + ",\n" +
"\tdemanglerApplicationArguments: " + getDemanglerApplicationArguments() + ",\n" +
"}";
//@formatter:on
}

View file

@ -43,12 +43,8 @@ public class GnuDemanglerParser {
private static final String TYPEINFO_FOR = "typeinfo for ";
private static final String COVARIANT_RETURN_THUNK = "covariant return thunk";
private static final Set<String> ADDRESS_TABLE_PREFIXES = Set.of(
CONSTRUCTION_VTABLE_FOR,
VTT_FOR,
VTABLE_FOR,
TYPEINFO_FN_FOR,
TYPEINFO_FOR);
private static final Set<String> ADDRESS_TABLE_PREFIXES =
Set.of(CONSTRUCTION_VTABLE_FOR, VTT_FOR, VTABLE_FOR, TYPEINFO_FN_FOR, TYPEINFO_FOR);
private static final String OPERATOR = "operator";
private static final String LAMBDA = "lambda";
@ -1357,7 +1353,7 @@ public class GnuDemanglerParser {
DemangledObject doBuild(Demangled namespace) {
DemangledString demangledString = new DemangledString(mangledSource, demangledSource,
"typeinfo-name", type, -1/*unknown length*/, false);
demangledString.setSpecialPrefix("typeinfo name for ");
demangledString.setSpecialPrefix(TYPEINFO_NAME_FOR);
String namespaceString = removeBadSpaces(type);
setNamespace(demangledString, namespaceString);
return demangledString;

View file

@ -22,9 +22,11 @@ import java.util.Arrays;
import org.junit.Before;
import org.junit.Test;
import docking.options.editor.BooleanEditor;
import ghidra.app.cmd.label.AddLabelCmd;
import ghidra.app.util.demangler.gnu.GnuDemanglerOptions;
import ghidra.app.util.demangler.gnu.GnuDemanglerFormat;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.EnumEditor;
import ghidra.framework.options.Options;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB;
@ -34,7 +36,6 @@ import ghidra.program.model.symbol.*;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
import ghidra.test.ToyProgramBuilder;
import ghidra.util.Msg;
import ghidra.util.StringUtilities;
import ghidra.util.task.TaskMonitor;
public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationTest {
@ -99,6 +100,7 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
Address addr = addr("0x110");
createSymbol(addr, mangled);
setFormat(GnuDemanglerFormat.AUTO);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER, true);
analyze();
@ -117,7 +119,7 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_PARAMETERS, "-s rust");
setFormat(GnuDemanglerFormat.RUST);
analyze();
@ -135,7 +137,7 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_PARAMETERS, "-s dlang");
setFormat(GnuDemanglerFormat.DLANG);
analyze();
@ -143,105 +145,23 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
}
@Test
public void testMangledString_WithArguments_Invalid() {
public void testUseDeprecatedOptionUpdatesAvailableFormats() {
//
// The below demangles to std::io::Read::read_to_end
//
String mangled = "_ZN3std2io4Read11read_to_end17hb85a0f6802e14499E";
setOption_UseDeprecatedDemangler(false);
assertFormatAvailable(GnuDemanglerFormat.RUST, true);
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_PARAMETERS, "-s badformatname");
analyze();
assertNotDemangled(addr, "read_to_end");
assertMessageLogLine("java.io.IOException: Error starting demangler with command");
assertMessageLogLine("Invalid options", GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
}
@Test
public void testDeprecatedMangledString_WithArguments_Invalid() {
//
// The below demangles to std::io::Read::read_to_end
//
String mangled = "_ZN3std2io4Read11read_to_end17hb85a0f6802e14499E";
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER, true);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_PARAMETERS, "-s badformatname");
analyze();
assertNotDemangled(addr, "read_to_end");
assertMessageLogLine("java.io.IOException: Error starting demangler with command");
assertMessageLogLine("Invalid options", GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
assertMessageLogLine("Invalid options", GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
}
@Test
public void testDeprecatedMangledString_WithArguments_InvalidModernArguments_ValidDeprecatedArguments() {
//
// The below demangles to std::io::Read::read_to_end
//
String mangled = "_ZN3std2io4Read11read_to_end17hb85a0f6802e14499E";
Address addr = addr("0x110");
createSymbol(addr, mangled);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER, true);
setOption(GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_PARAMETERS, "-s arm");
analyze();
assertNotDemangled(addr, "read_to_end");
assertMessageLogLine("java.io.IOException: Error starting demangler with command");
assertMessageLogLine("Invalid options", GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
assertMessageNotInLogLine("Invalid options", GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
setOption_UseDeprecatedDemangler(true);
assertFormatAvailable(GnuDemanglerFormat.RUST, false);
}
// things missed:
// -demangle error case in base class...this is OK
// -error case in applyTo method in base class
// -use deprecated demangler case in validateOptions
//==================================================================================================
// Private Methods
//==================================================================================================
private void assertMessageLogLine(String... expected) {
String allMessages = log.toString();
String[] logLines = allMessages.split("\n");
for (String line : logLines) {
if (StringUtilities.containsAllIgnoreCase(line, expected)) {
return;
}
}
fail("The folllowing source text did not have a line containing:\n" +
Arrays.toString(expected) + "\n\nActual Text:\n" + allMessages);
}
private void assertMessageNotInLogLine(String... expected) {
String allMessages = log.toString();
String[] logLines = allMessages.split("\n");
for (String line : logLines) {
if (StringUtilities.containsAllIgnoreCase(line, expected)) {
fail("The folllowing source text unexpectedly has a line containing:\n" +
Arrays.toString(expected) + "\n\nActual Text:\n" + allMessages);
}
}
}
private void analyze() {
tx(program, () -> analyzer.added(program, program.getMemory(), TaskMonitor.DUMMY, log));
}
@ -270,6 +190,32 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
fail("Unable to find demangled symbol '" + name + "'");
}
private void assertFormatAvailable(GnuDemanglerFormat format, boolean isAvailable) {
Options options = program.getOptions("Analyzers");
Options analyzerOptions = options.getOptions(analyzer.getName());
EnumEditor enumEditor =
(EnumEditor) runSwing(() -> analyzerOptions.getPropertyEditor("Demangler Format"));
assertNotNull(enumEditor);
Enum<?>[] values = enumEditor.getEnums();
for (Enum<?> enum1 : values) {
if (format.equals(enum1)) {
if (isAvailable) {
return;
}
fail("Found bad enum in list of choices: " + format + ".\nFound: " +
Arrays.toString(values));
}
}
if (isAvailable) {
fail("Did not find enum in list of choices: " + format + ".\nInstead found: " +
Arrays.toString(values));
}
}
private void setOption(String optionName, boolean doUse) {
String fullOptionName = analyzer.getName() + Options.DELIMITER_STRING + optionName;
@ -288,14 +234,27 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
fail("Could not find option '" + optionName + "'");
}
private void setOption(String optionName, String value) {
private void setOption_UseDeprecatedDemangler(boolean use) {
Options options = program.getOptions("Analyzers");
Options analyzerOptions = options.getOptions(analyzer.getName());
BooleanEditor enumEditor = (BooleanEditor) runSwing(
() -> analyzerOptions.getPropertyEditor("Use Deprecated Demangler"));
assertNotNull(enumEditor);
runSwing(() -> enumEditor.setValue(use));
}
private void setFormat(GnuDemanglerFormat format) {
String optionName = GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_FORMAT;
String fullOptionName = analyzer.getName() + Options.DELIMITER_STRING + optionName;
Options options = program.getOptions("Analyzers");
for (String name : options.getOptionNames()) {
if (name.equals(fullOptionName)) {
tx(program, () -> options.setString(optionName, value));
tx(program, () -> options.setEnum(optionName, format));
// we must call this manually, since we are not using a tool
analyzer.optionsChanged(options, program);

View file

@ -32,8 +32,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
parser = new GnuDemanglerParser();
}
@ -111,8 +111,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
public void testFunctionPointers() throws Exception {
String mangled = "__t6XpsMap2ZlZP14CORBA_TypeCodePFRCl_UlUlUlf";
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -564,8 +564,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "CalcPortExposedRect__13LScrollerViewCFR4Rectb";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -589,8 +589,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "__dt__Q26MsoDAL9VertFrameFv";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -630,8 +630,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "GetColWidths__13CDataRendererCFRA7_s";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -655,8 +655,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "GetColWidths__13CDataRendererCFPA7_s";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -714,8 +714,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "_gmStage2__FP12SECTION_INFOPiPA12_iiPCs";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -749,8 +749,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String mangled = "__ct__Q24CStr6BufferFR4CStrUl";
// use an older demangler; the current demangler cannot handle this string
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
String demangled = process.demangle(mangled);
@ -887,16 +887,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
@Test
public void testOverloadedShiftOperatorTemplated_LeftShift() {
String raw =
"std::basic_ostream<char, std::char_traits<char> >& " +
"std::operator<< <std::char_traits<char> >" +
"(std::basic_ostream<char, std::char_traits<char> >&, char const*)";
String raw = "std::basic_ostream<char, std::char_traits<char> >& " +
"std::operator<< <std::char_traits<char> >" +
"(std::basic_ostream<char, std::char_traits<char> >&, char const*)";
String formatted = "std::basic_ostream<char,std::char_traits<char>> & " +
"std::operator<<<std::char_traits<char>>" +
"(std::basic_ostream<char,std::char_traits<char>> &,char const *)";
DemangledObject object = parser.parse(
"_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc",
raw);
DemangledObject object =
parser.parse("_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc", raw);
String name = object.getName();
assertEquals("operator<<", name);
assertEquals(formatted, object.getSignature());
@ -1475,10 +1473,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
// Incorrect Native Output: uv(double, *__restrict)
//
String mangled = "uv__dup";
GnuDemangler demangler = new GnuDemangler();
DemangledObject res = demangler.demangle(mangled);
assertNull(res);
DemangledObject demangled = demangler.demangle(mangled);
assertNull(demangled);
}
@Test
@ -1548,8 +1545,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
String name =
"for_each_args<WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1},brigand::type_<std::__1::integral_constant<long,0l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,1l>>,WebCore::JSConverter<WebCore::IDLUnion<WebCore::IDLNull,WebCore::IDLDOMString,WebCore::IDLUnrestrictedDouble>>::convert(JSC::ExecState&,WebCore::JSDOMGlobalObject&,WTF::Variant<decltype(nullptr),WTF::String,double>const&)::{lambda(auto:1&&)#1}<std::__1<long,2l>>>";
assertName(object, name,
"brigand");
assertName(object, name, "brigand");
String signature = object.getSignature(false);
assertEquals(
@ -1670,8 +1666,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
assertNotNull(object);
assertType(object, DemangledFunction.class);
String name =
"operator=";
String name = "operator=";
assertName(object, name, "WTF", "Function<void()>");
String signature = object.getSignature(false);

View file

@ -0,0 +1,160 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.util.demangler.gnu;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
import org.junit.Test;
import static ghidra.app.util.demangler.gnu.GnuDemanglerFormat.*;
import java.io.IOException;
public class GnuDemanglerOptionsTest extends AbstractGhidraHeadlessIntegrationTest {
@Test
public void testAuto_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(AUTO, true);
getNativeProcess(options);
}
@Test
public void testAuto_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(AUTO, false);
getNativeProcess(options);
}
@Test
public void testGnu_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(GNU, true);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testGnu_withModern() {
new GnuDemanglerOptions(GNU, false);
}
@Test
public void testLucid_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(LUCID, true);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testLucid_withModern() {
new GnuDemanglerOptions(LUCID, false);
}
@Test
public void testArm_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(ARM, true);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testArm_withModern() {
new GnuDemanglerOptions(ARM, false);
}
@Test
public void testHp_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(HP, true);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testHp_withModern() {
new GnuDemanglerOptions(HP, false);
}
@Test
public void testEdg_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(EDG, true);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testEdg_withModern() {
new GnuDemanglerOptions(EDG, false);
}
@Test
public void testGnuV3_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(GNUV3, true);
getNativeProcess(options);
}
@Test
public void testGnuV3_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(GNUV3, false);
getNativeProcess(options);
}
@Test
public void testJava_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(JAVA, true);
getNativeProcess(options);
}
@Test
public void testJava_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(JAVA, false);
getNativeProcess(options);
}
@Test
public void testGnat_withDeprecated() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(GNAT, true);
getNativeProcess(options);
}
@Test
public void testGnat_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(GNAT, false);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testDlang_withDeprecated() {
new GnuDemanglerOptions(DLANG, true);
}
@Test
public void testDlang_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(DLANG, false);
getNativeProcess(options);
}
@Test(expected = IllegalArgumentException.class)
public void testRust_withDeprecated() {
new GnuDemanglerOptions(RUST, true);
}
@Test
public void testRust_withModern() throws IOException {
GnuDemanglerOptions options = new GnuDemanglerOptions(RUST, false);
getNativeProcess(options);
}
private static GnuDemanglerNativeProcess getNativeProcess(GnuDemanglerOptions options)
throws IOException {
String demanglerName = options.getDemanglerName();
String applicationOptions = options.getDemanglerApplicationArguments();
return GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName,
applicationOptions);
}
}

View file

@ -55,7 +55,12 @@ public class GnuDemanglerTest extends AbstractGenericTest {
demangler.canDemangle(program);// this perform initialization
// this throws an exception with the bug in place
demangler.demangle(mangled);
try {
demangler.demangle(mangled);
}
catch (DemangledException e) {
assertTrue(e.isInvalidMangledName());
}
}
@Test
@ -157,23 +162,6 @@ public class GnuDemanglerTest extends AbstractGenericTest {
assertEquals("ABC", d.getValue());
}
@Test
public void testDemangler_Format_EDG_DemangleOnlyKnownPatterns_False()
throws DemangledException {
String mangled = "_$_10MyFunction";
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined MyFunction::~MyFunction(void)", result.getSignature(false));
}
@Test
public void testDemangler_Format_EDG_DemangleOnlyKnownPatterns_True()
throws DemangledException {
@ -192,16 +180,31 @@ public class GnuDemanglerTest extends AbstractGenericTest {
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(true); // do not try
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.EDG);
DemangledObject result = demangler.demangle(mangled, options);
assertNull(result);
}
@Test
public void testDemangler_Format_CodeWarrior_MacOS8or9() throws DemangledException {
public void testDemangler_Format_EDG_DemangleOnlyKnownPatterns_False()
throws DemangledException {
String mangled = "_$_10MyFunction";
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, true);
options.setDemangleOnlyKnownPatterns(false);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined MyFunction::~MyFunction(void)", result.getSignature(false));
}
@Test
public void testDemangler_Format_CodeWarrior_MacOS8or9() throws DemangledException {
// NOTE: mangled CodeWarrior format symbols with templates will fail
// This is because the GNU demangler does not support CodeWarrior
// .scroll__10TTextPanelFUcsi
String mangled = ".scroll__10TTextPanelFUcsi";
@ -209,9 +212,8 @@ public class GnuDemanglerTest extends AbstractGenericTest {
GnuDemangler demangler = new GnuDemangler();
demangler.canDemangle(program);// this perform initialization
GnuDemanglerOptions options = new GnuDemanglerOptions();
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, true);
options.setDemangleOnlyKnownPatterns(false);
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined TTextPanel::scroll(unsigned char,short,int)",

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,38 +15,26 @@
*/
package ghidra.framework.options;
import ghidra.util.Msg;
import java.beans.PropertyEditorSupport;
import java.lang.reflect.Method;
import java.util.HashSet;
import ghidra.util.Msg;
public class EnumEditor extends PropertyEditorSupport {
private Enum<?> value;
/**
*
* @see java.beans.PropertyEditor#setValue(java.lang.Object)
*/
@Override
public void setValue(Object o) {
value = (Enum<?>) o;
}
/**
*
* @see java.beans.PropertyEditor#getValue()
*/
@Override
public Object getValue() {
return value;
}
/**
*
* @see java.beans.PropertyEditor#getTags()
*/
@Override
public String[] getTags() {
@ -85,28 +72,20 @@ public class EnumEditor extends PropertyEditorSupport {
return new Enum<?>[] { value };
}
/**
*
* @see java.beans.PropertyEditor#getAsText()
*/
@Override
public String getAsText() {
return value.toString();
}
/**
*
* @see java.beans.PropertyEditor#setAsText(java.lang.String)
*/
@Override
public void setAsText(String s) {
try {
Method m = value.getClass().getMethod("values");
Enum<?>[] enums = (Enum<?>[]) m.invoke(null);
for (int i = 0; i < enums.length; i++) {
if (s.equals(enums[i].toString())) {
value = enums[i];
for (Enum<?> enum1 : enums) {
if (s.equals(enum1.toString())) {
value = enum1;
break;
}
}

View file

@ -1,6 +1,5 @@
/* ###
* IP: GHIDRA
* REVIEWED: YES
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,19 +16,19 @@
package ghidra.framework.options;
// Support for PropertyEditors that use tags.
import java.awt.event.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.*;
import javax.swing.*;
import javax.swing.JComboBox;
/**
* An implementation of a PropertyComponent that is represented as a
* combo box.
*/
public class PropertySelector extends JComboBox implements ItemListener {
public class PropertySelector extends JComboBox<String> implements ItemListener {
private PropertyEditor editor;
private PropertyEditor propertyEditor;
private boolean notifyEditorOfChanges = true;
/**
@ -38,22 +37,23 @@ public class PropertySelector extends JComboBox implements ItemListener {
* changes in the combo box
*/
public PropertySelector(PropertyEditor pe) {
editor = pe;
String tags[] = editor.getTags();
for (int i = 0; i < tags.length; i++) {
addItem(tags[i]);
propertyEditor = pe;
String tags[] = propertyEditor.getTags();
for (String tag : tags) {
addItem(tag);
}
setSelectedIndex(0);
// This is a no-op if the getAsText is not a tag that we set from getTags() above
setSelectedItem(editor.getAsText());
setSelectedItem(propertyEditor.getAsText());
addItemListener(this);
invalidate();
editor.addPropertyChangeListener(new PropertyChangeListener() {
propertyEditor.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String value = editor.getAsText();
String value = propertyEditor.getAsText();
if (!value.equals(getSelectedItem())) {
notifyEditorOfChanges = false;
try {
@ -67,14 +67,15 @@ public class PropertySelector extends JComboBox implements ItemListener {
});
}
/*
* (non-Javadoc)
* @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
*/
@Override
public void itemStateChanged(ItemEvent evt) {
if (notifyEditorOfChanges) {
String s = (String) getSelectedItem();
editor.setAsText(s);
if (!notifyEditorOfChanges) {
return;
}
String s = (String) getSelectedItem();
if (s != null) {
propertyEditor.setAsText(s);
}
}
}

View file

@ -61,7 +61,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
options = options.withDeprecatedDemangler();
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
@ -86,7 +86,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
options = options.withDeprecatedDemangler();
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals("undefined SoloGimbalEKF::{unnamed_type#1}::SoloGimbalEKF(void)",
@ -116,7 +116,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
GnuDemanglerOptions options = new GnuDemanglerOptions();
options.setDemangleOnlyKnownPatterns(false);
options = options.withDeprecatedDemangler();
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
DemangledObject result = demangler.demangle(mangled, options);
assertNotNull(result);
assertEquals(