mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
parent
443e398bb4
commit
8f1dc3f476
14 changed files with 386 additions and 319 deletions
|
@ -386,10 +386,7 @@
|
||||||
<U><B>Use Deprecated Demangler</B></U> -
|
<U><B>Use Deprecated Demangler</B></U> -
|
||||||
By default, GCC symbols will be demangled using the most up-to-date demangler
|
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
|
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
|
option on will invoke the now deprecated version of the demangler (<B>version 2.24</B>).
|
||||||
(<B>version 2.24</B>) if the preferred demangler cannot demangle a given symbol.
|
|
||||||
This option only has an effect when the demangler format is available in both
|
|
||||||
the deprecated and modern demanglers.
|
|
||||||
</P>
|
</P>
|
||||||
<P>
|
<P>
|
||||||
Support for older demangling styles was removed in <CODE>c++filt (v2.32)</CODE>.
|
Support for older demangling styles was removed in <CODE>c++filt (v2.32)</CODE>.
|
||||||
|
@ -402,10 +399,15 @@
|
||||||
<P>
|
<P>
|
||||||
The available programs are:
|
The available programs are:
|
||||||
<UL>
|
<UL>
|
||||||
<LI><CODE>demangler_gnu_v2_33_1</CODE></LI>
|
<LI><CODE CLASS="path">
|
||||||
<LI><CODE>demangler_gnu_v2_24</CODE></LI>
|
<GHIDRA_INSTALL_DIR>/GPL/DemanglerGnu/os/<OS>/
|
||||||
|
</CODE><CODE>demangler_gnu_v2_33_1</CODE></LI>
|
||||||
|
<LI><CODE CLASS="path">
|
||||||
|
<GHIDRA_INSTALL_DIR>/GPL/DemanglerGnu/os/<OS>/
|
||||||
|
</CODE><CODE>demangler_gnu_v2_24</CODE></LI>
|
||||||
</UL>
|
</UL>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
<P style="background-color: #FFF0E0;">
|
<P style="background-color: #FFF0E0;">
|
||||||
<IMG SRC="../../shared/warning.png" />When using an external GNU demangler,
|
<IMG SRC="../../shared/warning.png" />When using an external GNU demangler,
|
||||||
please understand the risks associated with using that version of the
|
please understand the risks associated with using that version of the
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
package ghidra.app.util.demangler;
|
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 {
|
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() {
|
public boolean applySignature() {
|
||||||
return 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) {
|
public void setApplySignature(boolean applySignature) {
|
||||||
this.applySignature = 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
|
* 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() {
|
public boolean doDisassembly() {
|
||||||
return doDisassembly;
|
return doDisassembly;
|
||||||
|
@ -64,18 +64,18 @@ public class DemanglerOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the option to perform disassembly for known data structures (like functions) when
|
* 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) {
|
public void setDoDisassembly(boolean doDisassembly) {
|
||||||
this.doDisassembly = 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() {
|
public boolean demangleOnlyKnownPatterns() {
|
||||||
return demangleOnlyKnownPatterns;
|
return demangleOnlyKnownPatterns;
|
||||||
|
@ -83,10 +83,15 @@ public class DemanglerOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the option to only demangle known mangled patterns. Setting this to false causes
|
* 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
|
* most symbols to be demangled, which may result in some symbols getting demangled that were
|
||||||
* actually mangled symbols.
|
* 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) {
|
public void setDemangleOnlyKnownPatterns(boolean demangleOnlyKnownPatterns) {
|
||||||
this.demangleOnlyKnownPatterns = demangleOnlyKnownPatterns;
|
this.demangleOnlyKnownPatterns = demangleOnlyKnownPatterns;
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
//@category Examples.Demangler
|
//@category Examples.Demangler
|
||||||
import ghidra.app.script.GhidraScript;
|
import ghidra.app.script.GhidraScript;
|
||||||
import ghidra.app.util.demangler.DemangledObject;
|
import ghidra.app.util.demangler.DemangledObject;
|
||||||
import ghidra.app.util.demangler.gnu.GnuDemangler;
|
import ghidra.app.util.demangler.gnu.*;
|
||||||
import ghidra.app.util.demangler.gnu.GnuDemanglerOptions;
|
|
||||||
import ghidra.program.model.symbol.Symbol;
|
import ghidra.program.model.symbol.Symbol;
|
||||||
|
|
||||||
public class DemangleElfWithOptionScript extends GhidraScript {
|
public class DemangleElfWithOptionScript extends GhidraScript {
|
||||||
|
@ -33,8 +32,8 @@ public class DemangleElfWithOptionScript extends GhidraScript {
|
||||||
GnuDemangler demangler = new GnuDemangler();
|
GnuDemangler demangler = new GnuDemangler();
|
||||||
if (!demangler.canDemangle(currentProgram)) {
|
if (!demangler.canDemangle(currentProgram)) {
|
||||||
String executableFormat = currentProgram.getExecutableFormat();
|
String executableFormat = currentProgram.getExecutableFormat();
|
||||||
println("Cannot use the elf demangling options for executable format: " +
|
println(
|
||||||
executableFormat);
|
"Cannot use the elf demangling options for executable format: " + executableFormat);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,14 +48,12 @@ public class DemangleElfWithOptionScript extends GhidraScript {
|
||||||
|
|
||||||
String mangled = symbol.getName();
|
String mangled = symbol.getName();
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, false);
|
||||||
options.setDoDisassembly(false);
|
options.setDoDisassembly(false);
|
||||||
options.setDemanglerApplicationArguments("-s auto");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// for older formats use the deprecated demangler
|
// for older formats use the deprecated demangler
|
||||||
options.setDemanglerName(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
options = options.withDemanglerFormat(GnuDemanglerFormat.ARM, true);
|
||||||
options.setDemanglerApplicationArguments("-s arm");
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DemangledObject demangledObject = demangler.demangle(mangled, options);
|
DemangledObject demangledObject = demangler.demangle(mangled, options);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import docking.options.editor.BooleanEditor;
|
||||||
import ghidra.app.util.demangler.*;
|
import ghidra.app.util.demangler.*;
|
||||||
import ghidra.app.util.demangler.gnu.*;
|
import ghidra.app.util.demangler.gnu.*;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
@ -26,8 +27,6 @@ import ghidra.framework.options.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
|
|
||||||
import docking.options.editor.BooleanEditor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A version of the demangler analyzer to handle GNU GCC symbols
|
* A version of the demangler analyzer to handle GNU GCC symbols
|
||||||
*/
|
*/
|
||||||
|
@ -91,8 +90,8 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||||
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
|
options.registerOption(OPTION_NAME_USE_DEPRECATED_DEMANGLER, OptionType.BOOLEAN_TYPE,
|
||||||
useDeprecatedDemangler, help, OPTION_DESCRIPTION_DEPRECATED_DEMANGLER, editor);
|
useDeprecatedDemangler, help, OPTION_DESCRIPTION_DEPRECATED_DEMANGLER, editor);
|
||||||
|
|
||||||
options.registerOption(OPTION_NAME_DEMANGLER_FORMAT, OptionType.ENUM_TYPE,
|
options.registerOption(OPTION_NAME_DEMANGLER_FORMAT, OptionType.ENUM_TYPE, demanglerFormat,
|
||||||
demanglerFormat, help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, formatEditor);
|
help, OPTION_DESCRIPTION_DEMANGLER_FORMAT, formatEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -118,7 +117,7 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||||
@Override
|
@Override
|
||||||
protected DemangledObject doDemangle(String mangled, DemanglerOptions demanglerOtions,
|
protected DemangledObject doDemangle(String mangled, DemanglerOptions demanglerOtions,
|
||||||
MessageLog log) throws DemangledException {
|
MessageLog log) throws DemangledException {
|
||||||
return demangler.demangle(mangled, (GnuDemanglerOptions) demanglerOtions);
|
return demangler.demangle(mangled, demanglerOtions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FormatEditor extends EnumEditor implements PropertyChangeListener {
|
private static class FormatEditor extends EnumEditor implements PropertyChangeListener {
|
||||||
|
@ -164,7 +163,8 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||||
if (format.isAvailable(isDeprecatedDemangler())) {
|
if (format.isAvailable(isDeprecatedDemangler())) {
|
||||||
setValue(format);
|
setValue(format);
|
||||||
selector.setFormat(format);
|
selector.setFormat(format);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
setValue(GnuDemanglerFormat.AUTO);
|
setValue(GnuDemanglerFormat.AUTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,18 +178,16 @@ public class GnuDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
private static class FormatSelector extends PropertySelector {
|
private static class FormatSelector extends PropertySelector {
|
||||||
|
|
||||||
public FormatSelector(FormatEditor fe) {
|
public FormatSelector(FormatEditor fe) {
|
||||||
super(fe);
|
super(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
void reset(String[] tags) {
|
void reset(String[] tags) {
|
||||||
removeAllItems();
|
removeAllItems();
|
||||||
for (int i = 0; i < tags.length; i++) {
|
for (String tag : tags) {
|
||||||
addItem(tags[i]);
|
addItem(tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,15 +106,13 @@ public class GnuDemangler implements Demangler {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean onlyKnownPatterns = options.demangleOnlyKnownPatterns();
|
boolean onlyKnownPatterns = options.demangleOnlyKnownPatterns();
|
||||||
DemangledObject demangledObject =
|
DemangledObject demangledObject = parse(mangled, process, demangled, onlyKnownPatterns);
|
||||||
parse(mangled, process, demangled, onlyKnownPatterns);
|
|
||||||
if (demangledObject == null) {
|
if (demangledObject == null) {
|
||||||
return demangledObject;
|
return demangledObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (globalPrefix != null) {
|
if (globalPrefix != null) {
|
||||||
DemangledFunction dfunc =
|
DemangledFunction dfunc = new DemangledFunction(originalMangled, demangled,
|
||||||
new DemangledFunction(originalMangled, demangled,
|
|
||||||
globalPrefix + demangledObject.getName());
|
globalPrefix + demangledObject.getName());
|
||||||
dfunc.setNamespace(demangledObject.getNamespace());
|
dfunc.setNamespace(demangledObject.getNamespace());
|
||||||
demangledObject = dfunc;
|
demangledObject = dfunc;
|
||||||
|
@ -163,6 +161,19 @@ public class GnuDemangler implements Demangler {
|
||||||
applicationOptions);
|
applicationOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
private boolean skip(String mangled, GnuDemanglerOptions options) {
|
||||||
|
|
||||||
// Ignore versioned symbols which are generally duplicated at the same address
|
// Ignore versioned symbols which are generally duplicated at the same address
|
||||||
|
@ -179,13 +190,8 @@ public class GnuDemangler implements Demangler {
|
||||||
return false; // let it go through
|
return false; // let it go through
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO provide some checks specific to the other formats
|
// This is the current list of known demangler start patterns. Add to this list if we
|
||||||
GnuDemanglerFormat format = options.getDemanglerFormat();
|
// find any other known GNU start patterns.
|
||||||
if (format == GnuDemanglerFormat.AUTO) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (format == GnuDemanglerFormat.GNUV3) {
|
|
||||||
// add to this list if we find any other known GNU start patterns
|
|
||||||
if (mangled.startsWith("_Z")) {
|
if (mangled.startsWith("_Z")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -201,14 +207,12 @@ public class GnuDemangler implements Demangler {
|
||||||
if (isGnu2Or3Pattern(mangled)) {
|
if (isGnu2Or3Pattern(mangled)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DemangledObject parse(String mangled, GnuDemanglerNativeProcess process,
|
private DemangledObject parse(String mangled, GnuDemanglerNativeProcess process,
|
||||||
String demangled,
|
String demangled, boolean demangleOnlyKnownPatterns) {
|
||||||
boolean demangleOnlyKnownPatterns) {
|
|
||||||
|
|
||||||
if (demangleOnlyKnownPatterns && !isKnownMangledString(mangled, demangled)) {
|
if (demangleOnlyKnownPatterns && !isKnownMangledString(mangled, demangled)) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -22,36 +22,35 @@ public enum GnuDemanglerFormat {
|
||||||
// OLD: none,auto,gnu,lucid,arm,hp,edg,gnu-v3,java,gnat
|
// OLD: none,auto,gnu,lucid,arm,hp,edg,gnu-v3,java,gnat
|
||||||
// NEW: none,auto,gnu-v3,java,gnat,dlang,rust
|
// NEW: none,auto,gnu-v3,java,gnat,dlang,rust
|
||||||
/** Automatic mangling format detection */
|
/** Automatic mangling format detection */
|
||||||
AUTO("", 0),
|
AUTO("", Version.ALL),
|
||||||
/** GNUv2 mangling format */
|
/** GNUv2 mangling format */
|
||||||
GNU("gnu", -1),
|
GNU("gnu", Version.DEPRECATED),
|
||||||
/** lucid mangling format */
|
/** lucid mangling format */
|
||||||
LUCID("lucid", -1),
|
LUCID("lucid", Version.DEPRECATED),
|
||||||
/** arm mangling format */
|
/** arm mangling format */
|
||||||
ARM("arm", -1),
|
ARM("arm", Version.DEPRECATED),
|
||||||
/** hp mangling format */
|
/** hp mangling format */
|
||||||
HP("hp", -1),
|
HP("hp", Version.DEPRECATED),
|
||||||
/** mangling format used by the Edison Design Group (EDG) compiler */
|
/** mangling format used by the Edison Design Group (EDG) compiler */
|
||||||
EDG("edg", -1),
|
EDG("edg", Version.DEPRECATED),
|
||||||
/** GNUv3 mangling format */
|
/** GNUv3 mangling format */
|
||||||
GNUV3("gnu-v3", 0),
|
GNUV3("gnu-v3", Version.ALL),
|
||||||
/** Java mangling format */
|
/** Java mangling format */
|
||||||
JAVA("java", 0),
|
JAVA("java", Version.ALL),
|
||||||
/** GNAT Ada compiler mangling format */
|
/** GNAT Ada compiler mangling format */
|
||||||
GNAT("gnat", 0),
|
GNAT("gnat", Version.ALL),
|
||||||
/** D mangling format */
|
/** D mangling format */
|
||||||
DLANG("dlang", 1),
|
DLANG("dlang", Version.MODERN),
|
||||||
/** Rust mangling format */
|
/** Rust mangling format */
|
||||||
RUST("rust", 1);
|
RUST("rust", Version.MODERN);
|
||||||
|
|
||||||
/** the format option string */
|
/** the format option string used by the native demangler */
|
||||||
private final String format;
|
private final String format;
|
||||||
/** private sentinal. deprecated = -1, both = 0, new = 1 */
|
private final Version version;
|
||||||
private final byte version;
|
|
||||||
|
|
||||||
private GnuDemanglerFormat(String format, int version) {
|
private GnuDemanglerFormat(String format, Version version) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.version = (byte) version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,20 +58,20 @@ public enum GnuDemanglerFormat {
|
||||||
* @return true 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() {
|
public boolean isDeprecatedFormat() {
|
||||||
return version <= 0;
|
return version == Version.DEPRECATED || version == Version.ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this format is available in a modern version of the gnu demangler
|
* 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.
|
* @return true if this format is available in a modern version of the gnu demangler
|
||||||
*/
|
*/
|
||||||
public boolean isModernFormat() {
|
public boolean isModernFormat() {
|
||||||
return version >= 0;
|
return version == Version.MODERN || version == Version.ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this format is available for the specified demangler
|
* Checks if this format is available for the specified demangler
|
||||||
* @param isDeprecated true for the deprecated demangler, false for the modern demangler.
|
* @param isDeprecated true for the deprecated demangler, false for the modern demangler
|
||||||
* @return true if the format is available
|
* @return true if the format is available
|
||||||
*/
|
*/
|
||||||
public boolean isAvailable(boolean isDeprecated) {
|
public boolean isAvailable(boolean isDeprecated) {
|
||||||
|
@ -86,4 +85,8 @@ public enum GnuDemanglerFormat {
|
||||||
public String getFormat() {
|
public String getFormat() {
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum Version {
|
||||||
|
DEPRECATED, MODERN, ALL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,17 +46,32 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||||
private final GnuDemanglerFormat format;
|
private final GnuDemanglerFormat format;
|
||||||
private final boolean isDeprecated;
|
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() {
|
public GnuDemanglerOptions() {
|
||||||
// use default values
|
|
||||||
this(GnuDemanglerFormat.AUTO);
|
this(GnuDemanglerFormat.AUTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to specify a particular format
|
||||||
|
*
|
||||||
|
* @param format signals to use the given format
|
||||||
|
*/
|
||||||
public GnuDemanglerOptions(GnuDemanglerFormat format) {
|
public GnuDemanglerOptions(GnuDemanglerFormat format) {
|
||||||
this.format = format;
|
this(format, !format.isModernFormat());
|
||||||
// default to the "new" demangler if the format is available in both
|
|
||||||
this.isDeprecated = !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) {
|
public GnuDemanglerOptions(GnuDemanglerFormat format, boolean isDeprecated) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.isDeprecated = isDeprecated;
|
this.isDeprecated = isDeprecated;
|
||||||
|
@ -66,6 +81,10 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) {
|
public GnuDemanglerOptions(DemanglerOptions copy) {
|
||||||
super(copy);
|
super(copy);
|
||||||
|
|
||||||
|
@ -73,7 +92,8 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||||
GnuDemanglerOptions gCopy = (GnuDemanglerOptions) copy;
|
GnuDemanglerOptions gCopy = (GnuDemanglerOptions) copy;
|
||||||
format = gCopy.format;
|
format = gCopy.format;
|
||||||
isDeprecated = gCopy.isDeprecated;
|
isDeprecated = gCopy.isDeprecated;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
format = GnuDemanglerFormat.AUTO;
|
format = GnuDemanglerFormat.AUTO;
|
||||||
isDeprecated = false;
|
isDeprecated = false;
|
||||||
}
|
}
|
||||||
|
@ -97,23 +117,24 @@ public class GnuDemanglerOptions extends DemanglerOptions {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A convenience method to copy the state of this options object, changing the
|
* A convenience method to copy the state of this options object, changing the
|
||||||
* demangler executable name and demangler format to the specified values.
|
* demangler executable name and demangler format to the specified values
|
||||||
* @param format the demangling format to use
|
*
|
||||||
* @param isDeprecated true to use the deprecated gnu demangler, else false
|
* @param demanglerFormat the demangling format to use
|
||||||
|
* @param useDeprecated true to use the deprecated gnu demangler, else false
|
||||||
* @return the new options
|
* @return the new options
|
||||||
* @throws IllegalArgumentException if the current format is not available in the
|
* @throws IllegalArgumentException if the current format is not available in the
|
||||||
* selected demangler.
|
* selected demangler.
|
||||||
*/
|
*/
|
||||||
public GnuDemanglerOptions withDemanglerFormat(GnuDemanglerFormat format, boolean isDeprecated)
|
public GnuDemanglerOptions withDemanglerFormat(GnuDemanglerFormat demanglerFormat,
|
||||||
throws IllegalArgumentException {
|
boolean useDeprecated) throws IllegalArgumentException {
|
||||||
if (this.format == format && this.isDeprecated == isDeprecated) {
|
if (this.format == demanglerFormat && this.isDeprecated == useDeprecated) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (format.isAvailable(isDeprecated)) {
|
if (demanglerFormat.isAvailable(useDeprecated)) {
|
||||||
return new GnuDemanglerOptions(this, format, isDeprecated);
|
return new GnuDemanglerOptions(this, demanglerFormat, useDeprecated);
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
format.name() + " is not available in the "+getDemanglerName());
|
demanglerFormat.name() + " is not available in the " + getDemanglerName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1353,7 +1353,7 @@ public class GnuDemanglerParser {
|
||||||
DemangledObject doBuild(Demangled namespace) {
|
DemangledObject doBuild(Demangled namespace) {
|
||||||
DemangledString demangledString = new DemangledString(mangledSource, demangledSource,
|
DemangledString demangledString = new DemangledString(mangledSource, demangledSource,
|
||||||
"typeinfo-name", type, -1/*unknown length*/, false);
|
"typeinfo-name", type, -1/*unknown length*/, false);
|
||||||
demangledString.setSpecialPrefix("typeinfo name for ");
|
demangledString.setSpecialPrefix(TYPEINFO_NAME_FOR);
|
||||||
String namespaceString = removeBadSpaces(type);
|
String namespaceString = removeBadSpaces(type);
|
||||||
setNamespace(demangledString, namespaceString);
|
setNamespace(demangledString, namespaceString);
|
||||||
return demangledString;
|
return demangledString;
|
||||||
|
|
|
@ -17,12 +17,16 @@ package ghidra.app.plugin.core.analysis;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import docking.options.editor.BooleanEditor;
|
||||||
import ghidra.app.cmd.label.AddLabelCmd;
|
import ghidra.app.cmd.label.AddLabelCmd;
|
||||||
import ghidra.app.util.demangler.gnu.GnuDemanglerFormat;
|
import ghidra.app.util.demangler.gnu.GnuDemanglerFormat;
|
||||||
import ghidra.app.util.importer.MessageLog;
|
import ghidra.app.util.importer.MessageLog;
|
||||||
|
import ghidra.framework.options.EnumEditor;
|
||||||
import ghidra.framework.options.Options;
|
import ghidra.framework.options.Options;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
|
@ -104,6 +108,24 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
assertDemangled(addr, "__dt");
|
assertDemangled(addr, "__dt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMangledString_WithArguments_Valid() {
|
||||||
|
|
||||||
|
//
|
||||||
|
// The below demangles to std::io::Read::read_to_end
|
||||||
|
//
|
||||||
|
String mangled = "_ZN3std2io4Read11read_to_end17hb85a0f6802e14499E";
|
||||||
|
|
||||||
|
Address addr = addr("0x110");
|
||||||
|
createSymbol(addr, mangled);
|
||||||
|
|
||||||
|
setFormat(GnuDemanglerFormat.RUST);
|
||||||
|
|
||||||
|
analyze();
|
||||||
|
|
||||||
|
assertDemangled(addr, "read_to_end");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMangledString_WithArguments_ValidButWrongFormat() {
|
public void testMangledString_WithArguments_ValidButWrongFormat() {
|
||||||
|
|
||||||
|
@ -123,26 +145,13 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUseDeprecatedOptionRemoval_WithDeprecatedFormat() {
|
public void testUseDeprecatedOptionUpdatesAvailableFormats() {
|
||||||
setFormat(GnuDemanglerFormat.GNU);
|
|
||||||
Options options = program.getOptions("Analyzers");
|
|
||||||
assertFalse(options.contains(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
setOption_UseDeprecatedDemangler(false);
|
||||||
public void testUseDeprecatedOptionRemoval_WithRecentFormat() {
|
assertFormatAvailable(GnuDemanglerFormat.RUST, true);
|
||||||
setFormat(GnuDemanglerFormat.RUST);
|
|
||||||
Options options = program.getOptions("Analyzers");
|
|
||||||
assertFalse(options.contains(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
setOption_UseDeprecatedDemangler(true);
|
||||||
public void testUseDeprecatedOptionAddition() {
|
assertFormatAvailable(GnuDemanglerFormat.RUST, false);
|
||||||
// remove it first
|
|
||||||
testUseDeprecatedOptionRemoval_WithDeprecatedFormat();
|
|
||||||
setFormat(GnuDemanglerFormat.AUTO);
|
|
||||||
Options options = program.getOptions("Analyzers");
|
|
||||||
assertTrue(options.contains(GnuDemanglerAnalyzer.OPTION_NAME_USE_DEPRECATED_DEMANGLER));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// things missed:
|
// things missed:
|
||||||
|
@ -181,6 +190,32 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
fail("Unable to find demangled symbol '" + name + "'");
|
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) {
|
private void setOption(String optionName, boolean doUse) {
|
||||||
|
|
||||||
String fullOptionName = analyzer.getName() + Options.DELIMITER_STRING + optionName;
|
String fullOptionName = analyzer.getName() + Options.DELIMITER_STRING + optionName;
|
||||||
|
@ -199,6 +234,18 @@ public class GnuDemanglerAnalyzerTest extends AbstractGhidraHeadlessIntegrationT
|
||||||
fail("Could not find option '" + optionName + "'");
|
fail("Could not find option '" + optionName + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private void setFormat(GnuDemanglerFormat format) {
|
||||||
|
|
||||||
String optionName = GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_FORMAT;
|
String optionName = GnuDemanglerAnalyzer.OPTION_NAME_DEMANGLER_FORMAT;
|
||||||
|
|
|
@ -32,8 +32,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1);
|
||||||
parser = new GnuDemanglerParser();
|
parser = new GnuDemanglerParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,8 +111,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
public void testFunctionPointers() throws Exception {
|
public void testFunctionPointers() throws Exception {
|
||||||
String mangled = "__t6XpsMap2ZlZP14CORBA_TypeCodePFRCl_UlUlUlf";
|
String mangled = "__t6XpsMap2ZlZP14CORBA_TypeCodePFRCl_UlUlUlf";
|
||||||
|
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -564,8 +564,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "CalcPortExposedRect__13LScrollerViewCFR4Rectb";
|
String mangled = "CalcPortExposedRect__13LScrollerViewCFR4Rectb";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -589,8 +589,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "__dt__Q26MsoDAL9VertFrameFv";
|
String mangled = "__dt__Q26MsoDAL9VertFrameFv";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -630,8 +630,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "GetColWidths__13CDataRendererCFRA7_s";
|
String mangled = "GetColWidths__13CDataRendererCFRA7_s";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -655,8 +655,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "GetColWidths__13CDataRendererCFPA7_s";
|
String mangled = "GetColWidths__13CDataRendererCFPA7_s";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -714,8 +714,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "_gmStage2__FP12SECTION_INFOPiPA12_iiPCs";
|
String mangled = "_gmStage2__FP12SECTION_INFOPiPA12_iiPCs";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -749,8 +749,8 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
String mangled = "__ct__Q24CStr6BufferFR4CStrUl";
|
String mangled = "__ct__Q24CStr6BufferFR4CStrUl";
|
||||||
|
|
||||||
// use an older demangler; the current demangler cannot handle this string
|
// use an older demangler; the current demangler cannot handle this string
|
||||||
process = GnuDemanglerNativeProcess.getDemanglerNativeProcess(
|
process = GnuDemanglerNativeProcess
|
||||||
GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
|
||||||
|
|
||||||
String demangled = process.demangle(mangled);
|
String demangled = process.demangle(mangled);
|
||||||
|
|
||||||
|
@ -887,16 +887,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
@Test
|
@Test
|
||||||
public void testOverloadedShiftOperatorTemplated_LeftShift() {
|
public void testOverloadedShiftOperatorTemplated_LeftShift() {
|
||||||
|
|
||||||
String raw =
|
String raw = "std::basic_ostream<char, std::char_traits<char> >& " +
|
||||||
"std::basic_ostream<char, std::char_traits<char> >& " +
|
|
||||||
"std::operator<< <std::char_traits<char> >" +
|
"std::operator<< <std::char_traits<char> >" +
|
||||||
"(std::basic_ostream<char, std::char_traits<char> >&, char const*)";
|
"(std::basic_ostream<char, std::char_traits<char> >&, char const*)";
|
||||||
String formatted = "std::basic_ostream<char,std::char_traits<char>> & " +
|
String formatted = "std::basic_ostream<char,std::char_traits<char>> & " +
|
||||||
"std::operator<<<std::char_traits<char>>" +
|
"std::operator<<<std::char_traits<char>>" +
|
||||||
"(std::basic_ostream<char,std::char_traits<char>> &,char const *)";
|
"(std::basic_ostream<char,std::char_traits<char>> &,char const *)";
|
||||||
DemangledObject object = parser.parse(
|
DemangledObject object =
|
||||||
"_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc",
|
parser.parse("_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc", raw);
|
||||||
raw);
|
|
||||||
String name = object.getName();
|
String name = object.getName();
|
||||||
assertEquals("operator<<", name);
|
assertEquals("operator<<", name);
|
||||||
assertEquals(formatted, object.getSignature());
|
assertEquals(formatted, object.getSignature());
|
||||||
|
@ -1475,13 +1473,9 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
// Incorrect Native Output: uv(double, *__restrict)
|
// Incorrect Native Output: uv(double, *__restrict)
|
||||||
//
|
//
|
||||||
String mangled = "uv__dup";
|
String mangled = "uv__dup";
|
||||||
|
|
||||||
GnuDemangler demangler = new GnuDemangler();
|
GnuDemangler demangler = new GnuDemangler();
|
||||||
try {
|
DemangledObject demangled = demangler.demangle(mangled);
|
||||||
demangler.demangle(mangled);
|
assertNull(demangled);
|
||||||
} catch (DemangledException e) {
|
|
||||||
assertTrue(e.isInvalidMangledName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1551,8 +1545,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
|
|
||||||
String name =
|
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>>>";
|
"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,
|
assertName(object, name, "brigand");
|
||||||
"brigand");
|
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
@ -1673,8 +1666,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
|
||||||
assertNotNull(object);
|
assertNotNull(object);
|
||||||
assertType(object, DemangledFunction.class);
|
assertType(object, DemangledFunction.class);
|
||||||
|
|
||||||
String name =
|
String name = "operator=";
|
||||||
"operator=";
|
|
||||||
assertName(object, name, "WTF", "Function<void()>");
|
assertName(object, name, "WTF", "Function<void()>");
|
||||||
|
|
||||||
String signature = object.getSignature(false);
|
String signature = object.getSignature(false);
|
||||||
|
|
|
@ -57,7 +57,8 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
// this throws an exception with the bug in place
|
// this throws an exception with the bug in place
|
||||||
try {
|
try {
|
||||||
demangler.demangle(mangled);
|
demangler.demangle(mangled);
|
||||||
} catch (DemangledException e) {
|
}
|
||||||
|
catch (DemangledException e) {
|
||||||
assertTrue(e.isInvalidMangledName());
|
assertTrue(e.isInvalidMangledName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,6 +185,22 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
assertNull(result);
|
assertNull(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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(GnuDemanglerFormat.AUTO, true);
|
||||||
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals("undefined MyFunction::~MyFunction(void)", result.getSignature(false));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDemangler_Format_CodeWarrior_MacOS8or9() throws DemangledException {
|
public void testDemangler_Format_CodeWarrior_MacOS8or9() throws DemangledException {
|
||||||
// NOTE: mangled CodeWarrior format symbols with templates will fail
|
// NOTE: mangled CodeWarrior format symbols with templates will fail
|
||||||
|
@ -196,6 +213,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
demangler.canDemangle(program);// this perform initialization
|
demangler.canDemangle(program);// this perform initialization
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, true);
|
GnuDemanglerOptions options = new GnuDemanglerOptions(GnuDemanglerFormat.AUTO, true);
|
||||||
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
DemangledObject result = demangler.demangle(mangled, options);
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals("undefined TTextPanel::scroll(unsigned char,short,int)",
|
assertEquals("undefined TTextPanel::scroll(unsigned char,short,int)",
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,38 +15,26 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.framework.options;
|
package ghidra.framework.options;
|
||||||
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport;
|
import java.beans.PropertyEditorSupport;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
|
||||||
public class EnumEditor extends PropertyEditorSupport {
|
public class EnumEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
private Enum<?> value;
|
private Enum<?> value;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see java.beans.PropertyEditor#setValue(java.lang.Object)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(Object o) {
|
public void setValue(Object o) {
|
||||||
value = (Enum<?>) o;
|
value = (Enum<?>) o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see java.beans.PropertyEditor#getValue()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public Object getValue() {
|
public Object getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see java.beans.PropertyEditor#getTags()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String[] getTags() {
|
public String[] getTags() {
|
||||||
|
|
||||||
|
@ -85,28 +72,20 @@ public class EnumEditor extends PropertyEditorSupport {
|
||||||
return new Enum<?>[] { value };
|
return new Enum<?>[] { value };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see java.beans.PropertyEditor#getAsText()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getAsText() {
|
public String getAsText() {
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @see java.beans.PropertyEditor#setAsText(java.lang.String)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void setAsText(String s) {
|
public void setAsText(String s) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Method m = value.getClass().getMethod("values");
|
Method m = value.getClass().getMethod("values");
|
||||||
Enum<?>[] enums = (Enum<?>[]) m.invoke(null);
|
Enum<?>[] enums = (Enum<?>[]) m.invoke(null);
|
||||||
for (int i = 0; i < enums.length; i++) {
|
for (Enum<?> enum1 : enums) {
|
||||||
if (s.equals(enums[i].toString())) {
|
if (s.equals(enum1.toString())) {
|
||||||
value = enums[i];
|
value = enum1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,19 +16,19 @@
|
||||||
package ghidra.framework.options;
|
package ghidra.framework.options;
|
||||||
|
|
||||||
// Support for PropertyEditors that use tags.
|
// Support for PropertyEditors that use tags.
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
import java.awt.event.*;
|
import java.awt.event.ItemListener;
|
||||||
import java.beans.*;
|
import java.beans.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.JComboBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of a PropertyComponent that is represented as a
|
* An implementation of a PropertyComponent that is represented as a
|
||||||
* combo box.
|
* 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;
|
private boolean notifyEditorOfChanges = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,22 +37,23 @@ public class PropertySelector extends JComboBox implements ItemListener {
|
||||||
* changes in the combo box
|
* changes in the combo box
|
||||||
*/
|
*/
|
||||||
public PropertySelector(PropertyEditor pe) {
|
public PropertySelector(PropertyEditor pe) {
|
||||||
editor = pe;
|
propertyEditor = pe;
|
||||||
String tags[] = editor.getTags();
|
String tags[] = propertyEditor.getTags();
|
||||||
for (int i = 0; i < tags.length; i++) {
|
for (String tag : tags) {
|
||||||
addItem(tags[i]);
|
addItem(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedIndex(0);
|
setSelectedIndex(0);
|
||||||
|
|
||||||
// This is a no-op if the getAsText is not a tag that we set from getTags() above
|
// 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);
|
addItemListener(this);
|
||||||
invalidate();
|
invalidate();
|
||||||
|
|
||||||
editor.addPropertyChangeListener(new PropertyChangeListener() {
|
propertyEditor.addPropertyChangeListener(new PropertyChangeListener() {
|
||||||
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
String value = editor.getAsText();
|
String value = propertyEditor.getAsText();
|
||||||
if (!value.equals(getSelectedItem())) {
|
if (!value.equals(getSelectedItem())) {
|
||||||
notifyEditorOfChanges = false;
|
notifyEditorOfChanges = false;
|
||||||
try {
|
try {
|
||||||
|
@ -67,14 +67,15 @@ public class PropertySelector extends JComboBox implements ItemListener {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* (non-Javadoc)
|
|
||||||
* @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
|
|
||||||
*/
|
|
||||||
public void itemStateChanged(ItemEvent evt) {
|
public void itemStateChanged(ItemEvent evt) {
|
||||||
if (notifyEditorOfChanges) {
|
if (!notifyEditorOfChanges) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String s = (String) getSelectedItem();
|
String s = (String) getSelectedItem();
|
||||||
editor.setAsText(s);
|
if (s != null) {
|
||||||
|
propertyEditor.setAsText(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||||
options.setDemangleOnlyKnownPatterns(false);
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
options = options.withDeprecatedDemangler();
|
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
|
||||||
DemangledObject result = demangler.demangle(mangled, options);
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
|
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
|
||||||
|
@ -86,7 +86,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||||
options.setDemangleOnlyKnownPatterns(false);
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
options = options.withDeprecatedDemangler();
|
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
|
||||||
DemangledObject result = demangler.demangle(mangled, options);
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals("undefined SoloGimbalEKF::{unnamed_type#1}::SoloGimbalEKF(void)",
|
assertEquals("undefined SoloGimbalEKF::{unnamed_type#1}::SoloGimbalEKF(void)",
|
||||||
|
@ -116,7 +116,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||||
options.setDemangleOnlyKnownPatterns(false);
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
options = options.withDeprecatedDemangler();
|
options = options.withDemanglerFormat(GnuDemanglerFormat.AUTO, true);
|
||||||
DemangledObject result = demangler.demangle(mangled, options);
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue