diff --git a/Ghidra/Features/Base/build.gradle b/Ghidra/Features/Base/build.gradle index e7b5fcd547..da72748bd1 100644 --- a/Ghidra/Features/Base/build.gradle +++ b/Ghidra/Features/Base/build.gradle @@ -24,7 +24,6 @@ dependencies { compile project(':Graph') compile project(':SoftwareModeling') compile project(':DB') - compile project(':Demangler') compile project(':Help') compileOnly "junit:junit:4.12" diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java index 0fd6ba6fa7..f6d85ab822 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/AbstractDemanglerAnalyzer.java @@ -233,7 +233,7 @@ public abstract class AbstractDemanglerAnalyzer extends AbstractAnalyzer { log.appendMsg(getName(), "Failed to apply mangled symbol at " + address + "; name: " + - demangled.getMangledName() + failMessage); + demangled.getMangledString() + failMessage); } protected String cleanSymbol(Address address, String name) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/AbstractDemangledFunctionDefinitionDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/AbstractDemangledFunctionDefinitionDataType.java new file mode 100644 index 0000000000..ffe54bdd7f --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/AbstractDemangledFunctionDefinitionDataType.java @@ -0,0 +1,330 @@ +/* ### + * 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; + +import java.util.ArrayList; +import java.util.List; + +import ghidra.program.model.data.*; +import ghidra.program.model.symbol.Namespace; + +/** + * Parent base class for types that represent things that refer to functions + */ +public abstract class AbstractDemangledFunctionDefinitionDataType extends DemangledDataType { + + protected static final String DEFAULT_NAME_PREFIX = "FuncDef"; + protected static final String EMPTY_STRING = ""; + protected static int ID = 0; + protected DemangledDataType returnType; + protected String callingConvention;// __cdecl, __thiscall, etc. + protected List parameters = new ArrayList<>(); + protected String modifier;// namespace::, etc. + protected boolean isConstPointer; + + protected String parentName; + protected boolean isTrailingPointer64; + protected boolean isTrailingUnaligned; + protected boolean isTrailingRestrict; + + /** display parens in front of parameter list */ + protected boolean displayFunctionPointerParens = true; + + AbstractDemangledFunctionDefinitionDataType(String mangled, String originalDemangled) { + super(mangled, originalDemangled, DEFAULT_NAME_PREFIX + nextId()); + } + + private synchronized static int nextId() { + return ID++; + } + + /** + * Returns the string for this type of reference (e.g., * or &) + * @return the string + */ + abstract protected String getTypeString(); + + @Override + public String getSignature() { + return toSignature(null); + } + + /** + * Sets the return type + * @param returnType the return type + */ + public void setReturnType(DemangledDataType returnType) { + this.returnType = returnType; + } + + /** + * Returns the return type + * @return the return type + */ + public DemangledDataType getReturnType() { + return returnType; + } + + /** + * Sets the function calling convention. For example, "__cdecl" + * @param callingConvention the function calling convention + */ + public void setCallingConvention(String callingConvention) { + this.callingConvention = callingConvention; + } + + /** + * Returns the calling convention or null, if unspecified + * @return the calling convention or null, if unspecified + */ + public String getCallingConvention() { + return callingConvention; + } + + /** + * Sets the function __ modifier. For example, "namespace::". + * @param modifier the function modifier + */ + public void setModifier(String modifier) { + this.modifier = modifier; + } + + public boolean isConstPointer() { + return isConstPointer; + } + + public void setConstPointer() { + isConstPointer = true; + } + + public boolean isTrailingPointer64() { + return isTrailingPointer64; + } + + public void setTrailingPointer64() { + isTrailingPointer64 = true; + } + + public boolean isTrailingUnaligned() { + return isTrailingUnaligned; + } + + public void setTrailingUnaligned() { + isTrailingUnaligned = true; + } + + public boolean isTrailingRestrict() { + return isTrailingRestrict; + } + + public void setTrailingRestrict() { + isTrailingRestrict = true; + } + + public void setDisplayFunctionPointerParens(boolean b) { + this.displayFunctionPointerParens = b; + } + + /** + * Adds a parameters to the end of the parameter list for this demangled function + * @param parameter the new parameter to add + */ + public void addParameter(DemangledDataType parameter) { + parameters.add(parameter); + } + + /** + * Returns a list of the parameters for this demangled functions. + * @return a list of the parameters for this demangled functions + */ + public List getParameters() { + return new ArrayList<>(parameters); + } + + public String toSignature(String name) { + StringBuilder buffer = new StringBuilder(); + StringBuilder buffer1 = new StringBuilder(); + String s = getConventionPointerNameString(name); + if (s.contains(" ") || s.isEmpty()) { + // spaces--add parens + addFunctionPointerParens(buffer1, s); + } + else { // this allows the '__cdecl' in templates to not have parens + buffer1.append(s); + } + + buffer1.append('('); + for (int i = 0; i < parameters.size(); ++i) { + buffer1.append(parameters.get(i).getSignature()); + if (i < parameters.size() - 1) { + buffer1.append(','); + } + } + buffer1.append(')'); + + if (returnType instanceof DemangledFunctionPointer) { + DemangledFunctionPointer dfp = (DemangledFunctionPointer) returnType; + buffer.append(dfp.toSignature(buffer1.toString())).append(SPACE); + } + else if (returnType instanceof DemangledFunctionReference) { + DemangledFunctionReference dfr = (DemangledFunctionReference) returnType; + buffer.append(dfr.toSignature(buffer1.toString())).append(SPACE); + } + else if (returnType instanceof DemangledFunctionIndirect) { + DemangledFunctionIndirect dfi = (DemangledFunctionIndirect) returnType; + buffer.append(dfi.toSignature(buffer1.toString())).append(SPACE); + } + else { + buffer.append(returnType.getSignature()).append(SPACE); + buffer.append(buffer1); + } + + if (isConst()) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(CONST); + } + + if (isVolatile()) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(VOLATILE); + } + + if (isTrailingUnaligned) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(UNALIGNED); + } + + if (isTrailingPointer64) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(PTR64); + } + + if (isTrailingRestrict) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(RESTRICT); + } + + return buffer.toString(); + } + + protected String getConventionPointerNameString(String name) { + StringBuilder buffer = new StringBuilder(); + buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention); + + int pointerLevels = getPointerLevels(); + if (pointerLevels > 0) { + if (callingConvention != null) { + buffer.append(SPACE); + } + + addParentName(buffer); + + for (int i = 0; i < pointerLevels; ++i) { + buffer.append(getTypeString()); + } + } + + if ((modifier != null) && (modifier.length() != 0)) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(modifier); + } + + if (isConstPointer) { + buffer.append(CONST); + } + + if (isPointer64()) { + if (buffer.length() > 2) { + buffer.append(SPACE); + } + buffer.append(PTR64); + } + + if (name != null) { + if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) { + buffer.append(SPACE); + } + buffer.append(name); + } + + return buffer.toString(); + } + + protected void addFunctionPointerParens(StringBuilder buffer, String s) { + if (!displayFunctionPointerParens) { + return; + } + + buffer.append('(').append(s).append(')'); + } + + protected void addParentName(StringBuilder buffer) { + if (parentName == null) { + return; + } + + if (parentName.startsWith(DEFAULT_NAME_PREFIX)) { + return; + } + + if (buffer.length() > 2) { + char lastChar = buffer.charAt(buffer.length() - 1); + if (SPACE != lastChar) { + buffer.append(SPACE); + } + } + buffer.append(parentName).append(Namespace.DELIMITER); + } + + @Override + public DataType getDataType(DataTypeManager dataTypeManager) { + + FunctionDefinitionDataType fddt = new FunctionDefinitionDataType(getName()); + + if (returnType != null) { + fddt.setReturnType(returnType.getDataType(dataTypeManager)); + } + + if (parameters.size() != 1 || + !(parameters.get(0).getDataType(dataTypeManager) instanceof VoidDataType)) { + ParameterDefinition[] params = new ParameterDefinition[parameters.size()]; + for (int i = 0; i < parameters.size(); ++i) { + params[i] = new ParameterDefinitionImpl(null, + parameters.get(i).getDataType(dataTypeManager), null); + } + fddt.setArguments(params); + } + + DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName()); + if (dt == null || !(dt instanceof FunctionDefinitionDataType)) { + dt = fddt; + } + + return new PointerDataType(dt, dataTypeManager); + } +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangled.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangled.java new file mode 100644 index 0000000000..212f401ab7 --- /dev/null +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/Demangled.java @@ -0,0 +1,162 @@ +/* ### + * 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; + +/** + * A unifying top-level interface for all {@link DemangledObject}s and {@link DemangledType}s + * + *

This class and its children have many overlapping concepts that we wish to refine at a + * future date. Below is a listing of known uses: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
MethodDescription
+ * {@link #getName()} + * + * A 'safe' name that is the {@link #getDemangledName()}, but with some characters + * changed to be valid for use within Ghidra. + *
+ * {@link #getDemangledName()} + * + * The unmodified name that was set upon this object. + *
+ * {@link #getNamespaceName()} + * + * The 'safe' name of this object when it is used as a namespace name. This usually has + * parameter and template information. Further, some characters within templates and + * function signatures are replaced, such as spaces and namespace separators. + *

+ * Given this full demangled string: {@code Foo::Bar::Baz}, this method will return + * {@code Baz}. + *

+ * {@link #getNamespaceString()} + * + * This returns the unmodified name of this item, along with any unmodified parent + * namespace names, all separated by a namespace delimiter. Unlike + * {@link #getNamespaceName()}, the spaces and internal namespace tokens will not be + * replaced. + *

+ * Given this full demangled string: {@code Foo::Bar::Baz}, this method will return + * {@code Foo::Bar::Baz}. + *

+ * {@link #getSignature()} + * + * Returns the complete string form of this object, with most known attributes. For + * functions, this will be a complete signature. + *
+ * {@link #getOriginalDemangled()} + * + * The original unmodified demangled string. This is the full demangled string returned + * from the demangling service. + *
+ */ +public interface Demangled { + + /** + * Returns the original mangled string + * @return the string + */ + public String getMangledString(); + + /** + * Returns the original demangled string returned by the demangling service + * @return the original demangled string + */ + public String getOriginalDemangled(); + + /** + * Returns the demangled name of this object. + * NOTE: unsupported symbol characters, like whitespace, will be converted to an underscore. + * @return name of this DemangledObject with unsupported characters converted to underscore + * @see #getDemangledName() + */ + public String getName(); + + /** + * Sets the name for this object + * @param name the name + */ + public void setName(String name); + + /** + * Returns the unmodified demangled name of this object. This name may contain whitespace + * and other characters not supported for symbol or data type creation. See {@link #getName()} + * for the same name modified for use within Ghidra. + * @return name of this DemangledObject + */ + public String getDemangledName(); + + /** + * Returns the namespace containing this demangled object + * @return the namespace containing this demangled object + */ + public Demangled getNamespace(); + + /** + * Sets the namespace of this demangled object + * @param ns the namespace + */ + public void setNamespace(Demangled ns); + + /** + * Returns a representation of this object as fully-qualified namespace. The + * value returned here may have had some special characters replaced, such as ' ' replaced + * with '_' and '::' replaced with '--'. + * @return the full namespace + */ + public String getNamespaceString(); + + /** + * Returns this object's namespace name without the fully-qualified parent path. The + * value returned here may have had some special characters replaced, such as ' ' replaced + * with '_' and '::' replaced with '--'. + * + * @return the name + */ + public String getNamespaceName(); + + /** + * Generates a complete representation of this object to include all know attributes of this + * object + * @return the signature + */ + public String getSignature(); +} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledAddressTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledAddressTable.java index 68880d3555..e129d26cbd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledAddressTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledAddressTable.java @@ -23,21 +23,26 @@ import ghidra.program.model.mem.*; import ghidra.program.model.symbol.*; import ghidra.util.Msg; import ghidra.util.task.TaskMonitor; -import util.demangler.GenericDemangledAddressTable; public class DemangledAddressTable extends DemangledObject { + private boolean calculateLength; private int length; - public DemangledAddressTable(String name, int length) { + /** + * Constructor + * + * @param mangled the source mangled string + * @param originalDemangled the original demangled string + * @param name the name of the address table + * @param calculateLength true if the length of this address table should be calculdated at + * analysis time + */ + public DemangledAddressTable(String mangled, String originalDemangled, String name, + boolean calculateLength) { + super(mangled, originalDemangled); setName(name); - this.length = length; - } - - DemangledAddressTable(GenericDemangledAddressTable generic) { - super(generic); - - length = generic.getLength(); + this.calculateLength = calculateLength; } /** @@ -57,7 +62,7 @@ public class DemangledAddressTable extends DemangledObject { buffer.append(specialPrefix); buffer.append(' '); } - String namespaceStr = namespace.toSignature(); + String namespaceStr = namespace.getNamespaceString(); buffer.append(namespaceStr); if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) { buffer.append(NAMESPACE_SEPARATOR); @@ -83,15 +88,16 @@ public class DemangledAddressTable extends DemangledObject { return false; } + Listing listing = program.getListing(); if (MemoryBlock.isExternalBlockAddress(address, program)) { - program.getListing().setComment(address, CodeUnit.EOL_COMMENT, + listing.setComment(address, CodeUnit.EOL_COMMENT, "WARNING: Unable to apply demangled Address Table"); return true; // don't complain } - if (length == -1) { + if (calculateLength) { // determine length of address table - Data d = program.getListing().getDefinedDataAt(address); + Data d = listing.getDefinedDataAt(address); if (d != null && Undefined.isUndefinedArray(d.getDataType())) { // use length of Undefined array at start of table to indicate length length = d.getLength(); @@ -102,6 +108,7 @@ public class DemangledAddressTable extends DemangledObject { return false; } } + calculateLength = false; } if (isUndefinedInRange(program, address, address.add(length - 1))) { @@ -115,7 +122,7 @@ public class DemangledAddressTable extends DemangledObject { /** * Perform a best guess at the length of an address table assuming that * another label (or end of block) can be used to identify the end. - * @param program + * @param program the program * @param address start of address table * @return maximum length of table or -1 if address does not reside * within an initialized memory block diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java index 503b48fe3d..86cd6c4f9c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledDataType.java @@ -16,13 +16,14 @@ package ghidra.app.util.demangler; import java.util.ArrayList; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import ghidra.program.database.data.DataTypeUtilities; import ghidra.program.model.data.*; import ghidra.program.model.data.Enum; -import util.demangler.*; +import ghidra.program.model.symbol.Namespace; /** * A class to represent a demangled data type. @@ -57,7 +58,7 @@ public class DemangledDataType extends DemangledType { public final static String WCHAR_T = "wchar_t"; public final static String SHORT = "short"; public final static String INT = "int"; - public final static String INT0_T = "int0_t";//TODO + public final static String INT0_T = "int0_t"; public final static String LONG = "long"; public final static String LONG_LONG = "long long"; public final static String FLOAT = "float"; @@ -66,8 +67,8 @@ public class DemangledDataType extends DemangledType { public final static String INT16 = "__int16"; public final static String INT32 = "__int32"; public final static String INT64 = "__int64"; - public final static String INT128 = "__int128";//TODO - public final static String FLOAT128 = "__float128";//TODO + public final static String INT128 = "__int128"; + public final static String FLOAT128 = "__float128"; public final static String LONG_DOUBLE = "long double"; public final static String PTR64 = "__ptr64"; public final static String STRING = "string"; @@ -75,6 +76,11 @@ public class DemangledDataType extends DemangledType { public static final String UNALIGNED = "__unaligned"; public static final String RESTRICT = "__restrict"; + private static final String UNSIGNED_CHAR = "unsigned char"; + private static final String UNSIGNED_SHORT = "unsigned short"; + private static final String UNSIGNED_INT = "unsigned int"; + private static final String UNSIGNED_LONG = "unsigned long"; + public final static String[] PRIMITIVES = { VOID, BOOL, CHAR, WCHAR_T, SHORT, INT, INT0_T, LONG, LONG_LONG, FLOAT, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, }; @@ -84,14 +90,13 @@ public class DemangledDataType extends DemangledType { private boolean isEnum; private boolean isPointer64; private boolean isReference; - private boolean isSigned;//explicitly signed! + private boolean isSigned; private boolean isStruct; private boolean isTemplate; private boolean isUnaligned; private boolean isUnion; private boolean isUnsigned; private boolean isVarArgs; -// private boolean isVolatile; private int pointerLevels = 0; private String enumType; private boolean isRestrict; @@ -100,101 +105,13 @@ public class DemangledDataType extends DemangledType { private boolean isCoclass; private boolean isCointerface; - /** - * Constructs a new demangled datatype. - * @param name the name of the datatype - */ - public DemangledDataType(String name) { - super(name); - } - - DemangledDataType(GenericDemangledDataType source) { - super(source); - - if (source.isArray()) { - // TODO GenericDemangledDataType should go away; if so, we don't need to worry - // about array dimension impedance - arrayDimensions = 1; - } - - isClass = source.isClass(); - isComplex = source.isComplex(); - isEnum = source.isEnum(); - isPointer64 = source.isPointer64(); - isReference = source.isReference(); - isSigned = source.isSigned(); - isStruct = source.isStruct(); - isTemplate = source.isTemplate(); - isUnaligned = source.isUnaligned(); - isUnion = source.isUnion(); - isUnsigned = source.isUnsigned(); - isVarArgs = source.isVarArgs(); -// isVolatile = source.isVolatile(); - pointerLevels = source.getPointerLevels(); - //enumType = source.getEnumType(); - isRestrict = source.isRestrict(); - basedName = source.getBasedName(); - memberScope = source.getMemberScope(); - isCoclass = source.isCoclass(); - isCointerface = source.isCointerface(); - - GenericDemangledType otherNamespace = source.getNamespace(); - if (otherNamespace != null) { - namespace = DemangledType.convertToNamespace(source.getNamespace()); - } - - GenericDemangledTemplate otherTemplate = source.getTemplate(); - if (otherTemplate != null) { - template = new DemangledTemplate(otherTemplate); - } - - if (source.isConst()) { - setConst(); - } - } - - public DemangledDataType copy() { - DemangledDataType copy = new DemangledDataType(getName()); - copy(this, copy); - return copy; - } - - protected void copy(DemangledDataType source, DemangledDataType destination) { - destination.arrayDimensions = source.arrayDimensions; - destination.isClass = source.isClass; - destination.isComplex = source.isComplex; - destination.isEnum = source.isEnum; - destination.isPointer64 = source.isPointer64; - destination.isReference = source.isReference; - destination.isSigned = source.isSigned; - destination.isStruct = source.isStruct; - destination.isTemplate = source.isTemplate; - destination.isUnion = source.isUnion; - destination.isUnsigned = source.isUnsigned; - destination.isVarArgs = source.isVarArgs; -// destination.isVolatile = source.isVolatile; - destination.pointerLevels = source.pointerLevels; - //destination.enumType = source.enumType; - - destination.isUnaligned = source.isUnaligned(); - destination.isRestrict = source.isRestrict(); - destination.basedName = source.getBasedName(); - destination.memberScope = source.getMemberScope(); - - destination.setNamespace(source.getNamespace()); - destination.setTemplate(source.getTemplate()); - destination.isCoclass = source.isCoclass; - destination.isCointerface = source.isCointerface; - - if (source.isConst()) { - destination.setConst(); - } + public DemangledDataType(String mangled, String originaDemangled, String name) { + super(mangled, originaDemangled, name); } /** - * Converts this demangled datatype into the corresponding Ghidra datatype. - * @param dataTypeManager the data type manager to be searched and whose data organization - * should be used + * Converts this demangled datatype into the corresponding Ghidra datatype + * @param dataTypeManager the manager to search and whose data organization should be used * @return the Ghidra datatype corresponding to the demangled datatype */ public DataType getDataType(DataTypeManager dataTypeManager) { @@ -210,11 +127,6 @@ public class DemangledDataType extends DemangledType { } if (dt == null) { - - // If custom type, look for it first - // TODO: this find method could be subject to name mismatch, although - // presence of namespace could help this if it existing and contained within - // an appropriate namespace category dt = findDataType(dataTypeManager, namespace, name); DataType baseType = dt; @@ -235,25 +147,23 @@ public class DemangledDataType extends DemangledType { } else if (isEnum()) { if (baseType == null || !(baseType instanceof Enum)) { - // TODO: Can't tell how big an enum is, - // Just use the size of a pointer - // 20170522: Modified following code to allow "some" sizing from MSFT. - if ((enumType == null) || "int".equals(enumType) || - "unsigned int".equals(enumType)) { + + if (enumType == null || INT.equals(enumType) || UNSIGNED_INT.equals(enumType)) { + // Can't tell how big an enum is, just use the size of a pointer dt = new EnumDataType(getDemanglerCategoryPath(name, getNamespace()), name, dataTypeManager.getDataOrganization().getIntegerSize()); } - else if ("char".equals(enumType) || "unsigned char".equals(enumType)) { + else if (CHAR.equals(enumType) || UNSIGNED_CHAR.equals(enumType)) { dt = new EnumDataType(getDemanglerCategoryPath(name, getNamespace()), name, dataTypeManager.getDataOrganization().getCharSize()); } - else if ("short".equals(enumType) || "unsigned short".equals(enumType)) { + else if (SHORT.equals(enumType) || UNSIGNED_SHORT.equals(enumType)) { dt = new EnumDataType(getDemanglerCategoryPath(name, getNamespace()), name, dataTypeManager.getDataOrganization().getShortSize()); } - else if ("long".equals(enumType) || "unsigned long".equals(enumType)) { + else if (LONG.equals(enumType) || UNSIGNED_LONG.equals(enumType)) { dt = new EnumDataType(getDemanglerCategoryPath(name, getNamespace()), name, dataTypeManager.getDataOrganization().getLongSize()); } @@ -263,13 +173,13 @@ public class DemangledDataType extends DemangledType { } } } - else if (isClass() || name.equals(STRING)) {//TODO - class datatypes?? + else if (isClass() || name.equals(STRING)) { if (baseType == null || !(baseType instanceof Structure)) { // try creating empty structures for unknown types instead. dt = createPlaceHolderStructure(name, getNamespace()); } } - else if (dt == null) { // TODO: Is using whatever was found OK ?? + else if (dt == null) { // I don't know what this is // If it isn't pointed to, or isn't a referent, then assume typedef. @@ -298,7 +208,7 @@ public class DemangledDataType extends DemangledType { private DataType getBuiltInType(DataTypeManager dataTypeManager) { DataType dt = null; - String name = getName(); + String name = getDemangledName(); if (BOOL.equals(name)) { dt = BooleanDataType.dataType; } @@ -351,6 +261,9 @@ public class DemangledDataType extends DemangledType { else if (FLOAT.equals(name)) { dt = FloatDataType.dataType; } + else if (FLOAT128.equals(name)) { + dt = new TypedefDataType(FLOAT128, Float16DataType.dataType); + } else if (DOUBLE.equals(name)) { dt = DoubleDataType.dataType; } @@ -397,6 +310,16 @@ public class DemangledDataType extends DemangledType { AbstractIntegerDataType.getSignedDataType(8, dataTypeManager)); } } + else if (INT128.equals(name)) { + if (isUnsigned()) { + dt = new TypedefDataType("__uint128", + AbstractIntegerDataType.getUnsignedDataType(16, dataTypeManager)); + } + else { + dt = new TypedefDataType(INT128, + AbstractIntegerDataType.getSignedDataType(16, dataTypeManager)); + } + } else if (UNDEFINED.equals(name)) { dt = DataType.DEFAULT; } @@ -408,49 +331,51 @@ public class DemangledDataType extends DemangledType { * @param dataTypeManager data type manager to be searched * @param dtName name of data type * @param namespace namespace associated with dtName or null if not applicable. If specified, - * a namespace-base category path will be given precendence. + * a namespace-base category path will be given precedence. * @return data type if found, otherwise null. * @see DataTypeUtilities#findDataType(DataTypeManager, ghidra.program.model.symbol.Namespace, String, Class) for similar namespace * based search. */ - static DataType findDataType(DataTypeManager dataTypeManager, DemangledType namespace, + static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace, String dtName) { - // TODO: Should be able to search archives somehow - ArrayList list = new ArrayList<>(); + + List list = new ArrayList<>(); dataTypeManager.findDataTypes(dtName, list); - if (!list.isEmpty()) { - //use the datatype that exists in the root category, - //otherwise just pick the first one... - DataType anyDt = null; - DataType preferredDataType = null; - for (DataType existingDT : list) { - if (existingDT instanceof BuiltIn) { - continue; // TODO: not sure if this is good - built-ins handled explicitly - // by DemangledDataType.getDataType method - } - if (namespace == null) { - if (existingDT.getCategoryPath().equals(CategoryPath.ROOT)) { - return existingDT; - } - anyDt = existingDT; - } - if (isNamespaceCategoryMatch(existingDT, namespace)) { - preferredDataType = existingDT; - } - } - if (preferredDataType != null) { - return preferredDataType; - } - return anyDt; + if (list.isEmpty()) { + return null; } - return null; + + //use the datatype that exists in the root category, + //otherwise just pick the first one... + DataType anyDt = null; + DataType preferredDataType = null; + for (DataType existingDT : list) { + if (existingDT instanceof BuiltIn) { + // not sure if this is good - built-ins handled explicitly by getDataType() + continue; + } + if (namespace == null) { + if (existingDT.getCategoryPath().equals(CategoryPath.ROOT)) { + return existingDT; + } + anyDt = existingDT; + } + if (isNamespaceCategoryMatch(existingDT, namespace)) { + preferredDataType = existingDT; + } + } + if (preferredDataType != null) { + return preferredDataType; + } + return anyDt; } - private static boolean isNamespaceCategoryMatch(DataType dt, DemangledType namespace) { + private static boolean isNamespaceCategoryMatch(DataType dt, Demangled namespace) { if (namespace == null) { return true; } - DemangledType ns = namespace; + + Demangled ns = namespace; CategoryPath categoryPath = dt.getCategoryPath(); while (ns != null) { if (categoryPath.equals(CategoryPath.ROOT) || @@ -463,8 +388,8 @@ public class DemangledDataType extends DemangledType { return true; } - private static String getNamespacePath(String dtName, DemangledType namespace) { - DemangledType ns = namespace; + private static String getNamespacePath(String dtName, Demangled namespace) { + Demangled ns = namespace; String namespacePath = ""; while (ns != null) { namespacePath = "/" + ns.getName() + namespacePath; @@ -473,15 +398,14 @@ public class DemangledDataType extends DemangledType { return namespacePath; } - private static CategoryPath getDemanglerCategoryPath(String dtName, DemangledType namespace) { + private static CategoryPath getDemanglerCategoryPath(String dtName, Demangled namespace) { return new CategoryPath("/Demangler" + getNamespacePath(dtName, namespace)); } - static Structure createPlaceHolderStructure(String dtName, DemangledType namespace) { + static Structure createPlaceHolderStructure(String dtName, Demangled namespace) { StructureDataType structDT = new StructureDataType(dtName, 0); structDT.setDescription("PlaceHolder Structure"); structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace)); - return structDT; } @@ -561,10 +485,6 @@ public class DemangledDataType extends DemangledType { isVarArgs = true; } -// public void setVolatile() { -// isVolatile = true; -// } -// public void setEnumType(String enumType) { this.enumType = enumType; } @@ -669,10 +589,6 @@ public class DemangledDataType extends DemangledType { boolean isPrimitiveDT = !isArray() && !isClass && !isComplex && !isEnum && !isPointer() && !isPointer64 && !isSigned && !isTemplate && !isUnion && !isCoclass && !isCointerface && !isVarArgs; -// boolean isPrimitiveDT = !isArray && !isClass && !isComplex && !isEnum && !isPointer() && -// !isPointer64 && !isSigned && !isTemplate && !isUnion && !isVarArgs; -// boolean isPrimitiveDT = !isArray && !isClass && !isComplex && !isEnum && !isPointer() && -// !isPointer64 && !isSigned && !isTemplate && !isUnion && !isVarArgs && !isVolatile; if (isPrimitiveDT) { for (String primitiveNames : PRIMITIVES) { if (getName().equals(primitiveNames)) { @@ -684,8 +600,8 @@ public class DemangledDataType extends DemangledType { } @Override - public String toSignature() { - StringBuffer buffer = new StringBuffer(); + public String getSignature() { + StringBuilder buffer = new StringBuilder(); if (isUnion) { buffer.append(UNION + SPACE); @@ -711,9 +627,6 @@ public class DemangledDataType extends DemangledType { if (isComplex) { buffer.append(COMPLEX + SPACE); } -// if (isVolatile) { -// buffer.append(VOLATILE + SPACE); -// } if (isSigned) { buffer.append(SIGNED + SPACE); } @@ -722,7 +635,8 @@ public class DemangledDataType extends DemangledType { } if (getNamespace() != null) { - buffer.append(getNamespace().toNamespace()); + buffer.append(getNamespace().getNamespaceString()); + buffer.append(Namespace.DELIMITER); } buffer.append(getDemangledName()); @@ -735,7 +649,6 @@ public class DemangledDataType extends DemangledType { buffer.append(SPACE + CONST); } - // TODO: The output of volatile belongs here, not above, so I put the commented code here for now. if (isVolatile()) { buffer.append(SPACE + VOLATILE); } @@ -760,7 +673,8 @@ public class DemangledDataType extends DemangledType { buffer.append(SPACE + REF_NOTATION); } - //Order of __ptr64 and __restrict can vary--with fuzzing... but what is the natural "real symbol" order? + // the order of __ptr64 and __restrict can vary--with fuzzing... + // but what is the natural "real symbol" order? if (isPointer64) { buffer.append(SPACE + PTR64); } @@ -787,7 +701,7 @@ public class DemangledDataType extends DemangledType { @Override public String toString() { - return toSignature(); + return getSignature(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java index 0fceadea59..ec4e6b8b5a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunction.java @@ -21,22 +21,23 @@ import org.apache.commons.lang3.StringUtils; import ghidra.app.cmd.disassemble.DisassembleCommand; import ghidra.app.cmd.function.*; +import ghidra.app.util.NamespaceUtils; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.data.*; import ghidra.program.model.lang.PrototypeModel; import ghidra.program.model.listing.*; -import ghidra.program.model.symbol.SourceType; -import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.*; import ghidra.program.model.util.CodeUnitInsertionException; +import ghidra.util.Msg; +import ghidra.util.exception.AssertException; import ghidra.util.exception.InvalidInputException; import ghidra.util.task.TaskMonitor; -import util.demangler.*; /** * A class to represent a demangled function. */ -public class DemangledFunction extends DemangledObject implements ParameterReceiver { +public class DemangledFunction extends DemangledObject { public static final String VOLATILE = "volatile"; public static final String CONST = "const"; @@ -64,36 +65,11 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei private boolean isTypeCast; private String throwAttribute; - /** - * Constructs a new demangled function. - * @param name the name of the function - */ - public DemangledFunction(String name) { + public DemangledFunction(String mangled, String originalDemangled, String name) { + super(mangled, originalDemangled); setName(name); } - DemangledFunction(GenericDemangledFunction other) { - super(other); - - GenericDemangledDataType otherReturnType = other.getReturnType(); - if (otherReturnType != null) { - returnType = (DemangledDataType) DemangledObjectFactory.convert(otherReturnType); - } - callingConvention = other.getCallingConvention(); - thisPassedOnStack = other.isPassedOnStack(); - - GenericDemangledTemplate otherTemplate = other.getTemplate(); - if (otherTemplate != null) { - template = new DemangledTemplate(otherTemplate); - } - isOverloadedOperator = other.isOverloadedOperator(); - - List otherParams = other.getParameters(); - for (GenericDemangledDataType parameter : otherParams) { - parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter)); - } - } - /** * Sets the function return type. * @param returnType the function return type @@ -127,18 +103,10 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei this.isOverloadedOperator = isOverloadedOperator; } - /** - * @see ghidra.app.util.demangler.ParameterReceiver - */ - @Override public void addParameter(DemangledDataType parameter) { parameters.add(parameter); } - /** - * @see ghidra.app.util.demangler.ParameterReceiver - */ - @Override public List getParameters() { return new ArrayList<>(parameters); } @@ -159,7 +127,10 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei return callingConvention; } - /** Special constructor where it has a templated type before the parameter list */ + /** + * Special constructor where it has a templated type before the parameter list + * @param type the type + */ public void setTemplatedConstructorType(String type) { this.templatedConstructorType = type; } @@ -218,7 +189,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei @Override public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); if (!(returnType instanceof DemangledFunctionPointer)) { buffer.append(specialPrefix == null ? "" : specialPrefix + " "); @@ -227,7 +198,6 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei } buffer.append( visibility == null || "global".equals(visibility) ? "" : visibility + " "); -// if (virtual) { if (isVirtual) { buffer.append("virtual "); } @@ -235,37 +205,26 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei buffer.append("static "); } if (!isTypeCast()) { - buffer.append(returnType == null ? "" : returnType.toSignature() + " "); + buffer.append(returnType == null ? "" : returnType.getSignature() + " "); } // buffer.append(returnType == null ? "" : returnType.toSignature() + " "); } buffer.append(callingConvention == null ? "" : callingConvention + " "); if (namespace != null) { - buffer.append(namespace.toNamespace()); + buffer.append(namespace.getNamespaceString()); + buffer.append(NAMESPACE_SEPARATOR); } buffer.append(getDemangledName()); if (isTypeCast()) { - buffer.append(returnType == null ? "" : " " + returnType.toSignature() + " "); + buffer.append(returnType == null ? "" : " " + returnType.getSignature() + " "); } if (template != null) { buffer.append(template.toTemplate()); } - if (specialMidfix != null) { - buffer.append('[').append(specialMidfix).append(']'); - } - - // check for special case of 'conversion operator' where we only want to display '()' and - // not (void) -// if (name.endsWith("()")) { -// if (name.equals("operator")) { -// buffer.append("()"); -// } -// } -// else { if (templatedConstructorType != null) { buffer.append('<').append(templatedConstructorType).append('>'); } @@ -278,7 +237,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei } while (paramIterator.hasNext()) { - buffer.append(paramIterator.next().toSignature()); + buffer.append(paramIterator.next().getSignature()); if (paramIterator.hasNext()) { buffer.append(','); if (format) { @@ -290,26 +249,19 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei buffer.append(')'); buffer.append(storageClass == null ? "" : " " + storageClass); -// } if (returnType instanceof DemangledFunctionPointer) { DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) returnType; String partialSig = funcPtr.toSignature(buffer.toString()); - buffer = new StringBuffer(); + buffer = new StringBuilder(); buffer.append(specialPrefix == null ? "" : specialPrefix + " "); buffer.append( visibility == null || "global".equals(visibility) ? "" : visibility + " "); - //if (virtual || super.isVirtual) { if (isVirtual) { buffer.append("virtual "); } buffer.append(partialSig); } - else { - if (specialSuffix != null) { - buffer.append(specialSuffix); - } - } if (isTrailingConst()) { if (buffer.length() > 2) { @@ -351,12 +303,17 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei return buffer.toString(); } + @Override + public String getNamespaceName() { + return getName() + getParameterString(); + } + public String getParameterString() { StringBuffer buffer = new StringBuffer(); buffer.append('('); Iterator dditer = parameters.iterator(); while (dditer.hasNext()) { - buffer.append(dditer.next().toSignature()); + buffer.append(dditer.next().getSignature()); if (dditer.hasNext()) { buffer.append(','); } @@ -467,13 +424,13 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei for (int i = 0; i < args.size(); i++) { if (args.get(i).getLength() > pointerSize) { bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler", - "Couldn't Apply demangled signature - probably due to datatype that is too " + + "Couldn't apply demangled signature - probably due to datatype that is too " + "large to fit in a parameter"); } } bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler", - "Couldn't Apply demangled signature - bad parameter number match (" + args.size() + + "Couldn't apply demangled signature - bad parameter number match (" + args.size() + ") in a function in a namespace"); } @@ -503,7 +460,8 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei } } - private DataType resolveReturnType(Program program, Function func, Structure classDataType) { + private DataType resolveReturnType(Program program, Function function, + Structure classDataType) { // If something is returned as a Union, Structure, or Class return. // It appears that is passed as an additional parameter. Essentially, it accesses // the stack assuming there is reserved space. @@ -512,7 +470,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei } // If returnType is null check for constructor or destructor names - if (THIS_CALL.equals(func.getCallingConventionName())) { + if (THIS_CALL.equals(function.getCallingConventionName())) { String n = getName(); if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) { // constructor && destructor @@ -522,45 +480,50 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei return null; } - private Structure maybeUpdateCallingConventionAndCreateClass(Program program, Function func) { - try { - // If the calling convention is known, should use it! - if (callingConvention != null) { - if (program.getCompilerSpec().getCallingConvention(callingConvention) == null) { - // warn that calling convention not found. Datatypes are still good, - // the real calling convention can be figured out later - // For example X64 can have __cdecl, __fastcall, __stdcall, that are accepted but ignored - program.getBookmarkManager().setBookmark(func.getEntryPoint(), - BookmarkType.ANALYSIS, "Demangler", "Warning calling convention \"" + - callingConvention + "\" not defined in Compiler Spec (.cspec)"); - } - else { - func.setCallingConvention(callingConvention); - if (THIS_CALL.equals(callingConvention)) { - return createClassStructure(program, func); - } - return null; - } - } + private Structure maybeUpdateCallingConventionAndCreateClass(Program program, + Function function) { - if (isThisCall(func)) { - func.setCallingConvention(THIS_CALL); - return createClassStructure(program, func); + String convention = validateCallingConvention(program, function); + if (convention == null) { + if (!isThisCall(function)) { + return null; } -// Leave the calling convention to someone else to figure out -// else { -// String defaultConvention = getDefaultCallingConvention(program); -// if (defaultConvention != null) { -// func.setCallingConvention(defaultConvention); -// } -// } + convention = THIS_CALL; + } + + try { + function.setCallingConvention(convention); + return maybeCreateClassStructure(program, function, convention); } catch (InvalidInputException e) { - e.printStackTrace(); + Msg.error(this, "Unexpected exception setting calling convention", e); } + return null; } + private String validateCallingConvention(Program program, Function function) { + + if (callingConvention == null) { + return null; + } + + if (program.getCompilerSpec().getCallingConvention(callingConvention) == null) { + // warn that calling convention not found. Datatypes are still good, + // the real calling convention can be figured out later + // For example X64 can have __cdecl, __fastcall, __stdcall, that + // are accepted but ignored + BookmarkManager bm = program.getBookmarkManager(); + Address entry = function.getEntryPoint(); + bm.setBookmark(entry, BookmarkType.ANALYSIS, "Demangler", + "Could not apply calling convention \"" + callingConvention + + "\" not defined in Compiler Spec (.cspec)"); + return null; + } + + return callingConvention; + } + private List convertMangledToParamDef(Program program) { List args = new ArrayList<>(); @@ -674,7 +637,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei } // if the function name is the same name as it's namespace -// TODO: this seems too flexible - why not use equals? + // TODO: this seems too flexible - why not use equals? if (n.startsWith(namespace.getName())) { return true; } @@ -699,7 +662,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei return true; } - // TODO: It STILL COULD be a this call, we just don't know! + // It STILL COULD be a this call, we just don't know! // But is also could be a static member function! // The only way to really tell is compare the number of detected parameters // to the number of parameters we have, OR, to detect the calling convention @@ -714,19 +677,64 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei * @return true if it is in the std namespace */ private boolean isInStdNameSpace() { - DemangledType ns = namespace; + Demangled ns = namespace; // if my immediate namespace is "std", then I am just a function in the std namespace. if (ns == null) { return false; } - if (ns.getName().toLowerCase().equals(STD_NAMESPACE)) { + if (ns.getName().equalsIgnoreCase(STD_NAMESPACE)) { return true; } return false; } - static Function createFunction(Program prog, Address addr, boolean doDisassembly, + protected Structure maybeCreateClassStructure(Program program, Function function, + String convention) { + + if (!THIS_CALL.equals(convention)) { + return null; + } + + if (namespace == null) { + return null; + } + + String className = namespace.getName(); + Symbol parentSymbol = function.getSymbol().getParentSymbol(); + if (parentSymbol.getSymbolType() == SymbolType.NAMESPACE) { + try { + NamespaceUtils.convertNamespaceToClass((Namespace) parentSymbol.getObject()); + } + catch (InvalidInputException e) { + throw new AssertException(e); // unexpected condition + } + } + + // Store class structure in parent namespace + Demangled classNamespace = namespace.getNamespace(); + DataTypeManager dataTypeManager = program.getDataTypeManager(); + DataType existingType = + DemangledDataType.findDataType(dataTypeManager, classNamespace, className); + if (existingType != null && !(existingType instanceof Structure)) { + BookmarkManager bm = program.getBookmarkManager(); + Address entry = function.getEntryPoint(); + bm.setBookmark(entry, BookmarkType.ANALYSIS, "Demangler", + "Could not create class structure, data type already exists: " + existingType); + return null; + } + + Structure structure = (Structure) existingType; + if (structure == null) { + structure = DemangledDataType.createPlaceHolderStructure(className, + classNamespace); + } + structure = (Structure) dataTypeManager.resolve(structure, + DataTypeConflictHandler.DEFAULT_HANDLER); + return structure; + } + + protected Function createFunction(Program prog, Address addr, boolean doDisassembly, TaskMonitor monitor) { Listing listing = prog.getListing(); Function func = listing.getFunctionAt(addr); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionIndirect.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionIndirect.java index 140a79da35..88a782f433 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionIndirect.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionIndirect.java @@ -15,11 +15,6 @@ */ package ghidra.app.util.demangler; -import java.util.ArrayList; -import java.util.List; - -import ghidra.program.model.data.*; - /** * A class to represent a demangled function indirect. A function indirect is * similar to a function pointer or a function reference except that it does @@ -27,352 +22,14 @@ import ghidra.program.model.data.*; * is still an indirect definition (not a regular function definition). The * function indirect is prevalent in the Microsoft model, if not other models. */ -public class DemangledFunctionIndirect extends DemangledDataType implements ParameterReceiver { +public class DemangledFunctionIndirect extends AbstractDemangledFunctionDefinitionDataType { - private static final String DEFAULT_NAME_PREFIX = "FuncDef"; - private static final String NAMESPACE_DELIMITER = "::"; - private static final String EMPTY_STRING = ""; - private static int ID = 0; - private DemangledDataType returnType; - protected String callingConvention;// __cdecl, __thiscall, etc. - private List parameters = new ArrayList<>(); - protected String modifier;// namespace::, etc. - protected boolean isConstPointer; - - private String parentName; - private boolean isTrailingPointer64; - private boolean isTrailingUnaligned; - private boolean isTrailingRestrict; - - /** display parens in front of parameter list */ - private boolean displayFunctionPointerParens = true; - - /** - * Constructs a new demangled function definition. - */ - public DemangledFunctionIndirect() { - super("FuncDef" + nextID()); - } - - private synchronized static int nextID() { - return ID++; - } - -// DemangledFunctionDefinition(GenericDemangledFunctionDefinition generic) { -// super(generic); -// -// ID = generic.getID(); -// returnType = (DemangledDataType) DemangledObjectFactory.convert(generic.getReturnType()); -// callingConvention = generic.getCallingConvention(); -// isConstPointer = generic.isConstPointer(); -// -// parentName = generic.getParentName(); -// isTrailingPointer64 = generic.isTrailingPointer64(); -// -// List genericParameters = generic.getParameters(); -// for (GenericDemangledDataType parameter : genericParameters) { -// parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter)); -// } -// } - - /** - * Returns the return type. - * @return the return type - */ - public DemangledDataType getReturnType() { - return returnType; - } - - /** - * Sets the return type. - * @param returnType the return type - */ - public void setReturnType(DemangledDataType returnType) { - this.returnType = returnType; - } - - /** - * Returns the calling convention or null, if unspecified. - * @return the calling convention or null, if unspecified - */ - public String getCallingConvention() { - return callingConvention; - } - - /** - * Sets the function calling convention. For example, "__cdecl". - * @param callingConvention the function calling convention - */ - public void setCallingConvention(String callingConvention) { - this.callingConvention = callingConvention; - } - - /** - * Sets the function __ modifier. For example, "namespace::". - * @param modifier the function modifier - */ - public void setModifier(String modifier) { - this.modifier = modifier; - } - - public boolean isConstPointer() { - return isConstPointer; - } - - public void setConstPointer() { - isConstPointer = true; - } - - public boolean isTrailingPointer64() { - return isTrailingPointer64; - } - - public void setTrailingPointer64() { - isTrailingPointer64 = true; - } - - public boolean isTrailingUnaligned() { - return isTrailingUnaligned; - } - - public void setTrailingUnaligned() { - isTrailingUnaligned = true; - } - - public boolean isTrailingRestrict() { - return isTrailingRestrict; - } - - public void setTrailingRestrict() { - isTrailingRestrict = true; - } - - public void setDisplayFunctionPointerParens(boolean b) { - this.displayFunctionPointerParens = b; - } - - /** - * Adds a parameters to the end of the parameter list for - * this demangled function. - * @param parameter the new parameter to add - */ - @Override - public void addParameter(DemangledDataType parameter) { - parameters.add(parameter); - } - - /** - * Returns a list of the parameters for this demangled functions. - * @return a list of the parameters for this demangled functions - */ - @Override - public List getParameters() { - return new ArrayList<>(parameters); + public DemangledFunctionIndirect(String mangled, String originalDemangled) { + super(mangled, originalDemangled); } @Override - public DemangledDataType copy() { - DemangledFunctionIndirect copy = new DemangledFunctionIndirect(); - copy(this, copy); - return copy; - } - - @Override - protected void copy(DemangledDataType source, DemangledDataType destination) { - super.copy(source, destination); - if ((source instanceof DemangledFunctionIndirect) && - (destination instanceof DemangledFunctionIndirect)) { - DemangledFunctionIndirect copySource = (DemangledFunctionIndirect) source; - DemangledFunctionIndirect copyDestination = (DemangledFunctionIndirect) destination; - - copyDestination.returnType = copySource.returnType.copy(); - for (DemangledDataType parameter : copySource.parameters) { - copyDestination.parameters.add(parameter.copy()); - } - - copyDestination.callingConvention = copySource.callingConvention; - } - } - - @Override - public String toSignature() { - return toSignature(null); - } - - public String toSignature(String name) { - StringBuffer buffer = new StringBuffer(); - StringBuffer buffer1 = new StringBuffer(); - String s = getConventionPointerNameString(name); - if (s.contains(" ") || s.isEmpty()) { - // spaces--add parens - addFunctionPointerParens(buffer1, s); - } - else { // this allows the '__cdecl' in templates to not have parens - buffer1.append(s); - } - - buffer1.append('('); - for (int i = 0; i < parameters.size(); ++i) { - buffer1.append(parameters.get(i).toSignature()); - if (i < parameters.size() - 1) { - buffer1.append(','); - } - } - buffer1.append(')'); - - if (returnType instanceof DemangledFunctionPointer) { - buffer.append( - ((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionReference) { - buffer.append( - ((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionIndirect) { - buffer.append( - ((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else { - buffer.append(returnType.toSignature()).append(SPACE); - buffer.append(buffer1); - } - - if (isConst()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(CONST); - } - - if (isVolatile()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(VOLATILE); - } - - if (isTrailingUnaligned) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(UNALIGNED); - } - - if (isTrailingPointer64) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (isTrailingRestrict) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(RESTRICT); - } - - return buffer.toString(); - } - - private void addFunctionPointerParens(StringBuffer buffer, String s) { - if (!displayFunctionPointerParens) { - return; - } - - buffer.append('(').append(s).append(')'); - } - - private String getConventionPointerNameString(String name) { - StringBuilder buffer = new StringBuilder(); - buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention); - - int pointerLevels = getPointerLevels(); - if (pointerLevels > 0) { -// if (callingConvention != null) { -// buffer.append(SPACE); -// } - - addParentName(buffer); - -// for (int i = 0; i < pointerLevels; ++i) { -// buffer.append('*'); -// } - } - - if ((modifier != null) && (modifier.length() != 0)) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(modifier); - } - - if (isConstPointer) { - buffer.append(CONST); - } - - if (isPointer64()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (name != null) { -// if (buffer.length() > 2) { -// buffer.append(SPACE); -// } - if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) { - buffer.append(SPACE); - } - buffer.append(name); - } - - return buffer.toString(); - } - - private void addParentName(StringBuilder buffer) { - if (parentName == null) { - return; - } - - if (parentName.startsWith(DEFAULT_NAME_PREFIX)) { - return; - } - - if (buffer.length() > 2) { - char lastChar = buffer.charAt(buffer.length() - 1); - if (SPACE != lastChar) { - buffer.append(SPACE); - } - } - buffer.append(parentName).append(NAMESPACE_DELIMITER); - } - - @Override - public DataType getDataType(DataTypeManager dataTypeManager) { - - FunctionDefinitionDataType fddt = new FunctionDefinitionDataType(getName()); - fddt.setReturnType(returnType.getDataType(dataTypeManager)); - - if (parameters.size() != 1 || - !(parameters.get(0).getDataType(dataTypeManager) instanceof VoidDataType)) { - ParameterDefinition[] params = new ParameterDefinition[parameters.size()]; - for (int i = 0; i < parameters.size(); ++i) { - params[i] = new ParameterDefinitionImpl(null, - parameters.get(i).getDataType(dataTypeManager), null); - } - fddt.setArguments(params); - } - - DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName()); - if (dt == null || !(dt instanceof FunctionDefinitionDataType)) { - dt = fddt; - } - - return new PointerDataType(dt, dataTypeManager); + protected String getTypeString() { + return EMPTY_STRING; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionPointer.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionPointer.java index d4f8ef1838..f6519bef42 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionPointer.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionPointer.java @@ -15,362 +15,17 @@ */ package ghidra.app.util.demangler; -import java.util.ArrayList; -import java.util.List; - -import ghidra.program.model.data.*; -import util.demangler.GenericDemangledDataType; -import util.demangler.GenericDemangledFunctionPointer; - /** - * A class to represent a demangled function pointer. + * A class to represent a demangled function pointer */ -public class DemangledFunctionPointer extends DemangledDataType implements ParameterReceiver { +public class DemangledFunctionPointer extends AbstractDemangledFunctionDefinitionDataType { - private static final String DEFAULT_NAME_PREFIX = "FuncDef"; - private static final Object NAMESPACE_DELIMITER = "::"; - private static final String EMPTY_STRING = ""; - private static int ID = 0; - private DemangledDataType returnType; - protected String callingConvention;// __cdecl, __thiscall, etc. - private List parameters = new ArrayList<>(); - protected String modifier;// namespace::, etc. - protected boolean isConstPointer; - - private String parentName; - private boolean isTrailingPointer64; - private boolean isTrailingUnaligned; - private boolean isTrailingRestrict; - - /** display parens in front of parameter list */ - private boolean displayFunctionPointerParens = true; - - /** - * Constructs a new demangled function pointer. - */ - public DemangledFunctionPointer() { - super("FuncDef" + nextID()); - } - - private synchronized static int nextID() { - return ID++; - } - - DemangledFunctionPointer(GenericDemangledFunctionPointer generic) { - super(generic); - - ID = generic.getID(); - returnType = (DemangledDataType) DemangledObjectFactory.convert(generic.getReturnType()); - callingConvention = generic.getCallingConvention(); - isConstPointer = generic.isConstPointer(); - - parentName = generic.getParentName(); - isTrailingPointer64 = generic.isTrailingPointer64(); - - List genericParameters = generic.getParameters(); - for (GenericDemangledDataType parameter : genericParameters) { - parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter)); - } - } - - /** - * Returns the return type. - * @return the return type - */ - public DemangledDataType getReturnType() { - return returnType; - } - - /** - * Sets the return type. - * @param returnType the return type - */ - public void setReturnType(DemangledDataType returnType) { - this.returnType = returnType; - } - - /** - * Returns the calling convention or null, if unspecified. - * @return the calling convention or null, if unspecified - */ - public String getCallingConvention() { - return callingConvention; - } - - /** - * Sets the function calling convention. For example, "__cdecl". - * @param callingConvention the function calling convention - */ - public void setCallingConvention(String callingConvention) { - this.callingConvention = callingConvention; - } - - /** - * Sets the function __ modifier. For example, "namespace::". - * @param modifier the function modifier - */ - public void setModifier(String modifier) { - this.modifier = modifier; - } - - public boolean isConstPointer() { - return isConstPointer; - } - - public void setConstPointer() { - isConstPointer = true; - } - - public boolean isTrailingPointer64() { - return isTrailingPointer64; - } - - public void setTrailingPointer64() { - isTrailingPointer64 = true; - } - - public boolean isTrailingUnaligned() { - return isTrailingUnaligned; - } - - public void setTrailingUnaligned() { - isTrailingUnaligned = true; - } - - public boolean isTrailingRestrict() { - return isTrailingRestrict; - } - - public void setTrailingRestrict() { - isTrailingRestrict = true; - } - - public void setDisplayFunctionPointerParens(boolean b) { - this.displayFunctionPointerParens = b; - } - - /** - * Adds a parameters to the end of the parameter list for - * this demangled function. - * @param parameter the new parameter to add - */ - @Override - public void addParameter(DemangledDataType parameter) { - parameters.add(parameter); - } - - /** - * Returns a list of the parameters for this demangled functions. - * @return a list of the parameters for this demangled functions - */ - @Override - public List getParameters() { - return new ArrayList<>(parameters); + public DemangledFunctionPointer(String mangled, String originalDemangled) { + super(mangled, originalDemangled); } @Override - public DemangledDataType copy() { - DemangledFunctionPointer copy = new DemangledFunctionPointer(); - copy(this, copy); - return copy; - } - - @Override - protected void copy(DemangledDataType source, DemangledDataType destination) { - super.copy(source, destination); - if ((source instanceof DemangledFunctionPointer) && - (destination instanceof DemangledFunctionPointer)) { - DemangledFunctionPointer copySource = (DemangledFunctionPointer) source; - DemangledFunctionPointer copyDestination = (DemangledFunctionPointer) destination; - - copyDestination.returnType = copySource.returnType.copy(); - for (DemangledDataType parameter : copySource.parameters) { - copyDestination.parameters.add(parameter.copy()); - } - - copyDestination.callingConvention = copySource.callingConvention; - } - } - - @Override - public String toSignature() { - return toSignature(null); - } - - public String toSignature(String name) { - StringBuffer buffer = new StringBuffer(); - StringBuffer buffer1 = new StringBuffer(); - String s = getConventionPointerNameString(name); - if (s.contains(" ") || s.isEmpty()) { - // spaces--add parens - addFunctionPointerParens(buffer1, s); - } - else { // this allows the '__cdecl' in templates to not have parens - buffer1.append(s); - } - - buffer1.append('('); - for (int i = 0; i < parameters.size(); ++i) { - buffer1.append(parameters.get(i).toSignature()); - if (i < parameters.size() - 1) { - buffer1.append(','); - } - } - buffer1.append(')'); - - if (returnType instanceof DemangledFunctionPointer) { - buffer.append( - ((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionReference) { - buffer.append( - ((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionIndirect) { - buffer.append( - ((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else { - buffer.append(returnType.toSignature()).append(SPACE); - buffer.append(buffer1); - } - - if (isConst()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(CONST); - } - - if (isVolatile()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(VOLATILE); - } - - if (isTrailingUnaligned) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(UNALIGNED); - } - - if (isTrailingPointer64) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (isTrailingRestrict) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(RESTRICT); - } - - return buffer.toString(); - } - - private void addFunctionPointerParens(StringBuffer buffer, String s) { - if (!displayFunctionPointerParens) { - return; - } - - buffer.append('(').append(s).append(')'); - } - - private String getConventionPointerNameString(String name) { - StringBuilder buffer = new StringBuilder(); - buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention); - - int pointerLevels = getPointerLevels(); - if (pointerLevels > 0) { - if (callingConvention != null) { - buffer.append(SPACE); - } - - addParentName(buffer); - - for (int i = 0; i < pointerLevels; ++i) { - buffer.append('*'); - } - } - - if ((modifier != null) && (modifier.length() != 0)) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(modifier); - } - - if (isConstPointer) { - buffer.append(CONST); - } - - if (isPointer64()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (name != null) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(name); - } - - return buffer.toString(); - } - - private void addParentName(StringBuilder buffer) { - if (parentName == null) { - return; - } - - if (parentName.startsWith(DEFAULT_NAME_PREFIX)) { - return; - } - - if (buffer.length() > 2) { - char lastChar = buffer.charAt(buffer.length() - 1); - if (SPACE != lastChar) { - buffer.append(SPACE); - } - } - buffer.append(parentName).append(NAMESPACE_DELIMITER); - } - - @Override - public DataType getDataType(DataTypeManager dataTypeManager) { - - FunctionDefinitionDataType fddt = new FunctionDefinitionDataType(getName()); - - if (returnType != null) { - fddt.setReturnType(returnType.getDataType(dataTypeManager)); - } - - if (parameters.size() != 1 || - !(parameters.get(0).getDataType(dataTypeManager) instanceof VoidDataType)) { - ParameterDefinition[] params = new ParameterDefinition[parameters.size()]; - for (int i = 0; i < parameters.size(); ++i) { - params[i] = new ParameterDefinitionImpl(null, - parameters.get(i).getDataType(dataTypeManager), null); - } - fddt.setArguments(params); - } - - DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName()); - if (dt == null || !(dt instanceof FunctionDefinitionDataType)) { - dt = fddt; - } - - return new PointerDataType(dt, dataTypeManager); + protected String getTypeString() { + return "*"; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionReference.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionReference.java index 16d05a242c..92b856dcb5 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionReference.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionReference.java @@ -15,341 +15,17 @@ */ package ghidra.app.util.demangler; -import java.util.ArrayList; -import java.util.List; - -import ghidra.program.model.data.*; - /** - * A class to represent a demangled function reference. + * A class to represent a demangled function reference */ -public class DemangledFunctionReference extends DemangledDataType implements ParameterReceiver { +public class DemangledFunctionReference extends AbstractDemangledFunctionDefinitionDataType { - private static final String DEFAULT_NAME_PREFIX = "FuncDef"; - private static final Object NAMESPACE_DELIMITER = "::"; - private static final String EMPTY_STRING = ""; - private static int ID = 0; - private DemangledDataType returnType; - protected String callingConvention;// __cdecl, __thiscall, etc. - private List parameters = new ArrayList<>(); - protected String modifier;// namespace::, etc. - protected boolean isConstPointer; - - private String parentName; - private boolean isTrailingPointer64; - private boolean isTrailingUnaligned; - private boolean isTrailingRestrict; - - /** display parens in front of parameter list */ - private boolean displayFunctionPointerParens = true; - - /** - * Constructs a new demangled function reference. - */ - public DemangledFunctionReference() { - super("FuncDef" + nextID()); - } - - private synchronized static int nextID() { - return ID++; - } - - /** - * Returns the return type. - * @return the return type - */ - public DemangledDataType getReturnType() { - return returnType; - } - - /** - * Sets the return type. - * @param returnType the return type - */ - public void setReturnType(DemangledDataType returnType) { - this.returnType = returnType; - } - - /** - * Returns the calling convention or null, if unspecified. - * @return the calling convention or null, if unspecified - */ - public String getCallingConvention() { - return callingConvention; - } - - /** - * Sets the function calling convention. For example, "__cdecl". - * @param callingConvention the function calling convention - */ - public void setCallingConvention(String callingConvention) { - this.callingConvention = callingConvention; - } - - /** - * Sets the function __ modifier. For example, "namespace::". - * @param modifier the function modifier - */ - public void setModifier(String modifier) { - this.modifier = modifier; - } - - public boolean isConstPointer() { - return isConstPointer; - } - - public void setConstPointer() { - isConstPointer = true; - } - - public boolean isTrailingPointer64() { - return isTrailingPointer64; - } - - public void setTrailingPointer64() { - isTrailingPointer64 = true; - } - - public boolean isTrailingUnaligned() { - return isTrailingUnaligned; - } - - public void setTrailingUnaligned() { - isTrailingUnaligned = true; - } - - public boolean isTrailingRestrict() { - return isTrailingRestrict; - } - - public void setTrailingRestrict() { - isTrailingRestrict = true; - } - - public void setDisplayFunctionPointerParens(boolean b) { - this.displayFunctionPointerParens = b; - } - - /** - * Adds a parameters to the end of the parameter list for - * this demangled function. - * @param parameter the new parameter to add - */ - @Override - public void addParameter(DemangledDataType parameter) { - parameters.add(parameter); - } - - /** - * Returns a list of the parameters for this demangled functions. - * @return a list of the parameters for this demangled functions - */ - @Override - public List getParameters() { - return new ArrayList<>(parameters); + public DemangledFunctionReference(String mangled, String originalDemangled) { + super(mangled, originalDemangled); } @Override - public DemangledDataType copy() { - DemangledFunctionReference copy = new DemangledFunctionReference(); - copy(this, copy); - return copy; - } - - @Override - protected void copy(DemangledDataType source, DemangledDataType destination) { - super.copy(source, destination); - if ((source instanceof DemangledFunctionReference) && - (destination instanceof DemangledFunctionReference)) { - DemangledFunctionReference copySource = (DemangledFunctionReference) source; - DemangledFunctionReference copyDestination = (DemangledFunctionReference) destination; - - copyDestination.returnType = copySource.returnType.copy(); - for (DemangledDataType parameter : copySource.parameters) { - copyDestination.parameters.add(parameter.copy()); - } - - copyDestination.callingConvention = copySource.callingConvention; - } - } - - @Override - public String toSignature() { - return toSignature(null); - } - - public String toSignature(String name) { - StringBuffer buffer = new StringBuffer(); - StringBuffer buffer1 = new StringBuffer(); - String s = getConventionPointerNameString(name); - if (s.contains(" ") || s.isEmpty()) { - // spaces--add parens - addFunctionPointerParens(buffer1, s); - } - else { // this allows the '__cdecl' in templates to not have parens - buffer1.append(s); - } - - buffer1.append('('); - for (int i = 0; i < parameters.size(); ++i) { - buffer1.append(parameters.get(i).toSignature()); - if (i < parameters.size() - 1) { - buffer1.append(','); - } - } - buffer1.append(')'); - - if (returnType instanceof DemangledFunctionPointer) { - buffer.append( - ((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionReference) { - buffer.append( - ((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else if (returnType instanceof DemangledFunctionIndirect) { - buffer.append( - ((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append( - SPACE); - } - else { - buffer.append(returnType.toSignature()).append(SPACE); - buffer.append(buffer1); - } - - if (isConst()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(CONST); - } - - if (isVolatile()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(VOLATILE); - } - - if (isTrailingUnaligned) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(UNALIGNED); - } - - if (isTrailingPointer64) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (isTrailingRestrict) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(RESTRICT); - } - - return buffer.toString(); - } - - private void addFunctionPointerParens(StringBuffer buffer, String s) { - if (!displayFunctionPointerParens) { - return; - } - - buffer.append('(').append(s).append(')'); - } - - private String getConventionPointerNameString(String name) { - StringBuilder buffer = new StringBuilder(); - buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention); - - int pointerLevels = getPointerLevels(); - if (pointerLevels > 0) { - if (callingConvention != null) { - buffer.append(SPACE); - } - - addParentName(buffer); - - buffer.append('&'); -// for (int i = 0; i < pointerLevels; ++i) { -// buffer.append('*'); -// } - } - - if ((modifier != null) && (modifier.length() != 0)) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(modifier); - } - - if (isConstPointer) { - buffer.append(CONST); - } - - if (isPointer64()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (name != null) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(name); - } - - return buffer.toString(); - } - - private void addParentName(StringBuilder buffer) { - if (parentName == null) { - return; - } - - if (parentName.startsWith(DEFAULT_NAME_PREFIX)) { - return; - } - - if (buffer.length() > 2) { - char lastChar = buffer.charAt(buffer.length() - 1); - if (SPACE != lastChar) { - buffer.append(SPACE); - } - } - buffer.append(parentName).append(NAMESPACE_DELIMITER); - } - - @Override - public DataType getDataType(DataTypeManager dataTypeManager) { - - FunctionDefinitionDataType fddt = new FunctionDefinitionDataType(getName()); - fddt.setReturnType(returnType.getDataType(dataTypeManager)); - - if (parameters.size() != 1 || - !(parameters.get(0).getDataType(dataTypeManager) instanceof VoidDataType)) { - ParameterDefinition[] params = new ParameterDefinition[parameters.size()]; - for (int i = 0; i < parameters.size(); ++i) { - params[i] = new ParameterDefinitionImpl(null, - parameters.get(i).getDataType(dataTypeManager), null); - } - fddt.setArguments(params); - } - - DataType dt = DemangledDataType.findDataType(dataTypeManager, namespace, getName()); - if (dt == null || !(dt instanceof FunctionDefinitionDataType)) { - dt = fddt; - } - - return new PointerDataType(dt, dataTypeManager); + protected String getTypeString() { + return "&"; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionType.java deleted file mode 100644 index b4c7fce735..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledFunctionType.java +++ /dev/null @@ -1,39 +0,0 @@ -/* ### - * 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; - -/** - * An extension of {@link DemangledType} that signals that the type is function and can provide - * more info, like the function signature. - */ -public class DemangledFunctionType extends DemangledType { - - private String signature; - - public DemangledFunctionType(String name, String signature) { - super(name); - this.signature = signature; - } - - @Override - public boolean isFunction() { - return true; - } - - public String getSignature() { - return signature; - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledMethod.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledLambda.java similarity index 63% rename from Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledMethod.java rename to Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledLambda.java index 46f80a6b9b..6d8ec51af6 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledMethod.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledLambda.java @@ -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,16 +15,22 @@ */ package ghidra.app.util.demangler; -import util.demangler.GenericDemangledMethod; +/** + * Represents a demangled lambda function + */ +public class DemangledLambda extends DemangledFunction { -public class DemangledMethod extends DemangledFunction { - - public DemangledMethod(String name) { - super(name); + public DemangledLambda(String mangled, String originalDemangled, String name) { + super(mangled, originalDemangled, name); } - DemangledMethod(GenericDemangledMethod generic) { - super(generic); + @Override + public String getNamespaceName() { + return getName(); } + @Override + public String toString() { + return getName(); + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java index ffacc6fc5f..c4e47fb5a9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObject.java @@ -22,19 +22,18 @@ import java.util.regex.Pattern; import ghidra.app.cmd.label.SetLabelPrimaryCmd; import ghidra.app.util.NamespaceUtils; import ghidra.program.model.address.Address; -import ghidra.program.model.data.*; -import ghidra.program.model.listing.*; +import ghidra.program.model.listing.CodeUnit; +import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.*; import ghidra.util.Msg; -import ghidra.util.exception.*; +import ghidra.util.exception.DuplicateNameException; +import ghidra.util.exception.InvalidInputException; import ghidra.util.task.TaskMonitor; -import util.demangler.GenericDemangledObject; -import util.demangler.GenericDemangledType; /** * A class to represent a demangled object. */ -public abstract class DemangledObject { +public abstract class DemangledObject implements Demangled { protected static final String SPACE = " "; protected static final Pattern SPACE_PATTERN = Pattern.compile(SPACE); @@ -42,12 +41,10 @@ public abstract class DemangledObject { protected static final String NAMESPACE_SEPARATOR = Namespace.DELIMITER; protected static final String EMPTY_STRING = ""; - protected String originalMangled; - protected String utilDemangled; + protected final String mangled; // original mangled string + protected final String originalDemangled; protected String specialPrefix; - protected String specialMidfix; - protected String specialSuffix; - protected DemangledType namespace; + protected Demangled namespace; protected String visibility;//public, protected, etc. //TODO: storageClass refers to things such as "static" but const and volatile are @@ -73,62 +70,17 @@ public abstract class DemangledObject { private String signature; - DemangledObject() { - // default + DemangledObject(String mangled, String originalDemangled) { + this.mangled = mangled; + this.originalDemangled = originalDemangled; } - DemangledObject(GenericDemangledObject other) { - originalMangled = other.getOriginalMangled(); - specialPrefix = other.getSpecialPrefix(); - specialMidfix = other.getSpecialMidfix(); - specialSuffix = other.getSpecialSuffix(); - - GenericDemangledType otherNamespace = other.getNamespace(); - if (otherNamespace != null) { - namespace = DemangledType.convertToNamespace(otherNamespace); - } - - visibility = other.getVisibility(); - storageClass = other.getStorageClass(); - setName(other.getName()); - isConst = other.isConst(); - isVolatile = other.isVolatile(); - isPointer64 = other.isPointer64(); - isStatic = other.isStatic(); - isVirtual = other.isVirtual(); - isThunk = other.isThunk(); - - isUnaligned = other.isUnaligned(); - isRestrict = other.isRestrict(); - basedName = other.getBasedName(); - memberScope = other.getMemberScope(); - } - - /** - * Returns the unmodified demangled name of this object. - * This name may contain whitespace and other characters not - * supported for symbol or data type creation. See {@link #getName()} - * for the same name modified for use within Ghidra. - * @return name of this DemangledObject - */ + @Override public String getDemangledName() { return demangledName; } - /** - * Returns the original mangled name - * @return the name - */ - public String getMangledName() { - return originalMangled; - } - - /** - * Returns the demangled name of this object. - * NOTE: unsupported symbol characters, like whitespace, will be - * converted to an underscore. - * @return name of this DemangledObject with unsupported characters converted to underscore - */ + @Override public String getName() { return name; } @@ -217,6 +169,7 @@ public abstract class DemangledObject { * Sets the name of the demangled object * @param name the new name */ + @Override public void setName(String name) { this.demangledName = name; this.name = name; @@ -228,39 +181,23 @@ public abstract class DemangledObject { } } - /** - * Sets the original mangled name - * @param mangled the original mangled name - */ - public void setOriginalMangled(String mangled) { - this.originalMangled = mangled; + @Override + public String getMangledString() { + return mangled; } - /** - * Sets the demangled output from a supplemental utility. - * @param utilDemangled the demangled string - */ - public void setUtilDemangled(String utilDemangled) { - this.utilDemangled = utilDemangled; + @Override + public String getOriginalDemangled() { + return originalDemangled; } - /** - * Gets the demangled output from a supplemental utility. - * @return the demangled String created for this object. - */ - public String getUtilDemangled() { - return utilDemangled; - } - - /** - * Returns the namespace containing this demangled object. - * @return the namespace containing this demangled object - */ - public DemangledType getNamespace() { + @Override + public Demangled getNamespace() { return namespace; } - public void setNamespace(DemangledType namespace) { + @Override + public void setNamespace(Demangled namespace) { this.namespace = namespace; } @@ -288,22 +225,6 @@ public abstract class DemangledObject { this.specialPrefix = special; } - public String getSpecialMidfix() { - return specialMidfix; - } - - public void setSpecialMidfix(String chargeType) { - this.specialMidfix = chargeType; - } - - public String getSpecialSuffix() { - return specialSuffix; - } - - public void setSpecialSuffix(String specialSuffix) { - this.specialSuffix = specialSuffix; - } - /** * Returns a complete signature for the demangled symbol. *
For example: @@ -317,6 +238,20 @@ public abstract class DemangledObject { */ public abstract String getSignature(boolean format); + @Override + public final String getSignature() { + return getSignature(false); + } + + /** + * Returns a signature that contains only the name (and parameter list for functions) + * @return the signature + */ + @Override + public String getNamespaceName() { + return getSignature(false); + } + /** * Sets the signature. Calling this method will * override the auto-generated signature. @@ -331,6 +266,17 @@ public abstract class DemangledObject { return getSignature(false); } + @Override + public String getNamespaceString() { + StringBuilder buffer = new StringBuilder(); + if (namespace != null) { + buffer.append(namespace.getNamespaceString()); + buffer.append(Namespace.DELIMITER); + } + buffer.append(getNamespaceName()); + return buffer.toString(); + } + /** * Determine if the symbol at address has already been demangled. While memory symbols * check for presence of demangledName, external symbols simply check if demangled/alternate @@ -364,7 +310,7 @@ public abstract class DemangledObject { public boolean applyTo(Program program, Address address, DemanglerOptions options, TaskMonitor monitor) throws Exception { - if (originalMangled.equals(name)) { + if (mangled.equals(name)) { return false; } String comment = program.getListing().getComment(CodeUnit.PLATE_COMMENT, address); @@ -382,8 +328,8 @@ public abstract class DemangledObject { } protected String generatePlateComment() { - if (utilDemangled != null) { - return utilDemangled; + if (originalDemangled != null) { + return originalDemangled; } return (signature == null) ? getSignature(true) : signature; } @@ -432,7 +378,7 @@ public abstract class DemangledObject { } private Symbol updateExternalSymbol(Program program, Address externalAddr, String symbolName, - DemangledType demangledNamespace) { + Demangled demangledNamespace) { SymbolTable symbolTable = program.getSymbolTable(); Symbol s = symbolTable.getPrimarySymbol(externalAddr); @@ -461,30 +407,28 @@ public abstract class DemangledObject { * @param typeNamespace demangled namespace object * @return list of namespace names */ - private static List getNamespaceList(DemangledType typeNamespace) { - ArrayList list = new ArrayList<>(); - DemangledType ns = typeNamespace; + private static List getNamespaceList(Demangled typeNamespace) { + List list = new ArrayList<>(); + Demangled ns = typeNamespace; while (ns != null) { - list.add(0, ns.getName()); + list.add(0, ns.getNamespaceName()); ns = ns.getNamespace(); } return list; } - // TODO needs updating. Couldn't determine what getResigualNamespacePath was changed to. /** * Get or create the specified typeNamespace. The returned namespace may only be a partial * namespace if errors occurred. The caller should check the returned namespace and adjust - * any symbol creation accordingly. Caller should use - * getResidualNamespacePath(DemangledType, Namespace) to handle the case where - * only a partial namespace has been returned. - * @param program + * any symbol creation accordingly. + * + * @param program the program * @param typeNamespace demangled namespace * @param parentNamespace root namespace to be used (e.g., library, global, etc.) * @param functionPermitted if true an existing function may be used as a namespace * @return namespace or partial namespace if error occurs */ - public static Namespace createNamespace(Program program, DemangledType typeNamespace, + public static Namespace createNamespace(Program program, Demangled typeNamespace, Namespace parentNamespace, boolean functionPermitted) { Namespace namespace = parentNamespace; @@ -572,37 +516,4 @@ public abstract class DemangledObject { return buffy.toString(); } - protected Structure createClassStructure(Program prog, Function func) { - DataTypeManager dataTypeManager = prog.getDataTypeManager(); - - if (namespace == null) { - // unexpected - return null; - } - String structureName = namespace.getName(); - - Symbol parentSymbol = func.getSymbol().getParentSymbol(); - if (parentSymbol.getSymbolType() == SymbolType.NAMESPACE) { - try { - NamespaceUtils.convertNamespaceToClass((Namespace) parentSymbol.getObject()); - } - catch (InvalidInputException e) { - throw new AssertException(e); // unexpected condition - } - } - - // Store class structure in parent namespace - DemangledType classStructureNamespace = namespace.getNamespace(); - - Structure classStructure = (Structure) DemangledDataType.findDataType(dataTypeManager, - classStructureNamespace, structureName); - if (classStructure == null) { - classStructure = DemangledDataType.createPlaceHolderStructure(structureName, - classStructureNamespace); - } - classStructure = (Structure) dataTypeManager.resolve(classStructure, - DataTypeConflictHandler.DEFAULT_HANDLER); - return classStructure; - } - } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObjectFactory.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObjectFactory.java deleted file mode 100644 index 376c3b1f16..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledObjectFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* ### - * 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. - * 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; - -import util.demangler.*; - -public class DemangledObjectFactory { - - private DemangledObjectFactory() { - // factory - } - - public static DemangledObject convert(GenericDemangledObject generic) throws DemangledException { - if (generic instanceof GenericDemangledVariable) { - return new DemangledVariable((GenericDemangledVariable) generic); - } - else if (generic instanceof GenericDemangledString) { - return new DemangledString((GenericDemangledString) generic); - } - else if (generic instanceof GenericDemangledMethod) { - return new DemangledMethod((GenericDemangledMethod) generic); - } - else if (generic instanceof GenericDemangledFunction) { - return new DemangledFunction((GenericDemangledFunction) generic); - } - else if (generic instanceof GenericDemangledAddressTable) { - return new DemangledAddressTable((GenericDemangledAddressTable) generic); - } - - throw new DemangledException("Unknown GenericDemangledObject: " + generic.getClass()); - } - - public static DemangledType convert(GenericDemangledType generic) { - if (generic instanceof GenericDemangledFunctionPointer) { - return new DemangledFunctionPointer((GenericDemangledFunctionPointer) generic); - } - else if (generic instanceof GenericDemangledDataType) { - return new DemangledDataType((GenericDemangledDataType) generic); - } - - return new DemangledType(generic); - } -} diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledString.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledString.java index 813d8116af..9d0399a7ad 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledString.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledString.java @@ -22,7 +22,6 @@ import ghidra.program.model.symbol.*; import ghidra.util.Msg; import ghidra.util.StringUtilities; import ghidra.util.task.TaskMonitor; -import util.demangler.GenericDemangledString; public class DemangledString extends DemangledObject { private String string; @@ -31,6 +30,8 @@ public class DemangledString extends DemangledObject { /** * Construct demangled string. + * @param mangled the source mangled string + * @param originalDemangled the original demangled string * @param name name associated with this object * @param string string text associated with this object or null. This is used to establish * label and plate comment if specified. If null, name will be used as symbol name. @@ -38,34 +39,22 @@ public class DemangledString extends DemangledObject { * assumes null terminated string. * @param unicode true if string is a Unicode string. */ - public DemangledString(String name, String string, int length, boolean unicode) { + public DemangledString(String mangled, String originalDemangled, String name, String string, + int length, boolean unicode) { + super(mangled, originalDemangled); setName(name); this.string = string; this.length = length; this.unicode = unicode; } - /** - * Construct demangled string from a GenericDemangledString - * @param generic generic demangled string - */ - DemangledString(GenericDemangledString generic) { - super(generic); - string = generic.getString(); - length = generic.getLength(); - unicode = generic.isUnicode(); - } - @Override public String getSignature(boolean format) { StringBuffer buffer = new StringBuffer(); if (specialPrefix != null) { - buffer.append(specialPrefix + " for "); + buffer.append(specialPrefix); } buffer.append(string); - if (specialSuffix != null) { - buffer.append(" " + specialSuffix); - } return buffer.toString(); } @@ -84,9 +73,9 @@ public class DemangledString extends DemangledObject { public boolean applyTo(Program program, Address address, DemanglerOptions options, TaskMonitor monitor) throws Exception { - String label = SymbolUtilities.replaceInvalidChars(string, false); + String label = buildStringLabel(); if (hasLabel(program, address, label)) { - return true; // Desired symbol already exists here. + return true; // This string has already been applied } if (!super.applyTo(program, address, options, monitor)) { @@ -100,24 +89,24 @@ public class DemangledString extends DemangledObject { return false; } - // TODO: should we be using length ? CreateStringCmd cmd = new CreateStringCmd(address, -1, isUnicode()); cmd.applyTo(program); - // unclear what demangled name should be used so apply - // fabricated string label which is more useful than mangled name Symbol demangledSymbol = - applyDemangledName(buildStringLabel(), address, true, false, program); + applyDemangledName(label, address, true, false, program); return (demangledSymbol != null); } private String buildStringLabel() { - // build string label consistent with dynamic label formatting + if (specialPrefix != null) { + // a 'special prefix' implies that the author wishes to apply the string exactly as-is return getName(); } + + // build string label consistent with dynamic label formatting int len = string.length(); - StringBuffer buf = new StringBuffer(len); + StringBuilder buf = new StringBuilder(len); for (int i = 0; i < len; ++i) { char c = string.charAt(i); if (StringUtilities.isDisplayable(c) && (c != ' ')) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledTemplate.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledTemplate.java index ea264fa02f..7d9cec77d9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledTemplate.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledTemplate.java @@ -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,48 +15,27 @@ */ package ghidra.app.util.demangler; -import ghidra.program.model.data.DataType; -import ghidra.util.Msg; - import java.util.ArrayList; import java.util.List; -import util.demangler.GenericDemangledDataType; -import util.demangler.GenericDemangledTemplate; +import ghidra.program.model.data.DataType; -public class DemangledTemplate implements ParameterReceiver { +public class DemangledTemplate { private List parameters = new ArrayList(); - public DemangledTemplate() { - } - - DemangledTemplate(GenericDemangledTemplate template) { - List genericParameters = template.getParameters(); - for (GenericDemangledDataType parameter : genericParameters) { - parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter)); - } - } - - @Override public void addParameter(DemangledDataType parameter) { parameters.add(parameter); } - @Override public List getParameters() { return new ArrayList(parameters); } public String toTemplate() { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); buffer.append('<'); for (int i = 0; i < parameters.size(); ++i) { - try { - buffer.append(parameters.get(i).toSignature()); - } - catch (Error e) { - Msg.error(this, "Unexpected Error: " + e.getMessage(), e); - } + buffer.append(parameters.get(i).getSignature()); if (i < parameters.size() - 1) { buffer.append(','); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledThunk.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledThunk.java index f1daaf45c4..5c54b95fdd 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledThunk.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledThunk.java @@ -34,7 +34,9 @@ public class DemangledThunk extends DemangledObject { private boolean covariantReturnThunk = false; - public DemangledThunk(DemangledFunction thunkedFunctionObject) { + public DemangledThunk(String mangled, String originalDemangled, + DemangledFunction thunkedFunctionObject) { + super(mangled, originalDemangled); this.thunkedFunctionObject = thunkedFunctionObject; this.namespace = thunkedFunctionObject.getNamespace(); setName(thunkedFunctionObject.getName()); @@ -106,7 +108,7 @@ public class DemangledThunk extends DemangledObject { function = function.getThunkedFunction(false); } - if (thunkedFunction != null && originalMangled.equals(function.getName()) && + if (thunkedFunction != null && mangled.equals(function.getName()) && !function.isThunk()) { function.setThunkedFunction(thunkedFunction); } @@ -115,14 +117,6 @@ public class DemangledThunk extends DemangledObject { return s != null; } - /** - * Create normal function where thunk resides - * @param prog program - * @param addr thunk function address - * @param doDisassembly - * @param monitor - * @return function - */ private Function createPreThunkFunction(Program prog, Address addr, boolean doDisassembly, TaskMonitor monitor) { @@ -147,8 +141,9 @@ public class DemangledThunk extends DemangledObject { while (instr != null) { // This is done in a way to handle potential delay slots InstructionContext instructionContext = instr.getInstructionContext(); - Address fallThru = instructionContext.getAddress().add( - instr.getPrototype().getFallThroughOffset(instructionContext)); + Address fallThru = instructionContext.getAddress() + .add( + instr.getPrototype().getFallThroughOffset(instructionContext)); Address maxAddr = fallThru.previous(); if (maxAddr.compareTo(instr.getMinAddress()) < 0) { // just in case we wrapped @@ -181,7 +176,7 @@ public class DemangledThunk extends DemangledObject { } Symbol s = SymbolUtilities.getExpectedLabelOrFunctionSymbol(program, - thunkedFunctionObject.originalMangled, err -> Msg.warn(this, err)); + mangled, err -> Msg.warn(this, err)); if (s == null) { Address thunkedAddr = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java index 4f627fbd4d..6288ceab96 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledType.java @@ -15,102 +15,43 @@ */ package ghidra.app.util.demangler; -import java.util.List; - -import ghidra.app.util.SymbolPath; import ghidra.program.model.symbol.Namespace; -import util.demangler.GenericDemangledTemplate; -import util.demangler.GenericDemangledType; -public class DemangledType { +/** + * Represents a demangled string. This class is really just a placeholder for demangled + * information. See {@link DemangledObject} for a class that represents software concepts that + * can be applied to a program. The {@link DemangledObject} may use instances of this class + * to compose its internal state for namespace information, return types and parameters. + */ +public class DemangledType implements Demangled { + + protected String mangled; // the original mangled string + private String originalDemangled; private String demangledName; - private String name; - protected String originalMangled; - protected DemangledType namespace; + private String name; // 'safe' name + + protected Demangled namespace; protected DemangledTemplate template; private boolean isConst; private boolean isVolatile; - /** - * Takes a {@link DemangledType} with a name that contains namespace elements - * (such as Foo::Bar) and breaks it into a hierarchy of types where each type - * represents one item in the list of namespace elements. - * - * @param otherNamespace the type to convert - * @return the original type if the name does not represent a namespace; a new type - * that contains a child, that contains a child and so on, representing the - * split-up of the original namespace string. - */ - public static DemangledType convertToNamespace(GenericDemangledType otherNamespace) { - if (otherNamespace == null) { - return null; - } - - DemangledType newNamespace = new DemangledType(otherNamespace); - String demangledName = newNamespace.getName(); - - SymbolPath symbolPath = new SymbolPath(demangledName); - if (symbolPath.getParent() == null) { - return newNamespace; - } - - List names = symbolPath.asList(); - - DemangledType lastParent = new DemangledType(names.get(0)); - for (int i = 1; i < names.size(); i++) { - DemangledType child = new DemangledType(names.get(i)); - child.setNamespace(lastParent); - lastParent = child; - } - - return lastParent; - } - - public DemangledType(String name) { + public DemangledType(String mangled, String originaDemangled, String name) { + this.mangled = mangled; + this.originalDemangled = originaDemangled; setName(name); } - DemangledType(GenericDemangledType toCopy) { - GenericDemangledType otherNamespace = toCopy.getNamespace(); - - if (otherNamespace != null) { - namespace = convertToNamespace(otherNamespace); - } - - setName(toCopy.getName()); - GenericDemangledTemplate otherTemplate = toCopy.getTemplate(); - if (otherTemplate != null) { - template = new DemangledTemplate(otherTemplate); - } - isConst = toCopy.isConst(); - isVolatile = toCopy.isVolatile(); - } - - /** - * Returns the unmodified demangled name of this object. - * This name may contain whitespace and other characters not - * supported for symbol or data type creation. See {@link #getName()} - * for the same name modified for use within Ghidra. - * @return name of this DemangledObject - */ + @Override public String getDemangledName() { return demangledName; } - /** - * Get the name of this type. - * NOTE: unsupported symbol characters, like whitespace, will be - * converted to an underscore. - * @return name of this DemangledType suitable for namespace creation. - */ + @Override public String getName() { return name; } - /** - * Sets the name of the demangled type object. - * @param name the new name - */ + @Override public void setName(String name) { demangledName = name; this.name = name; @@ -120,20 +61,14 @@ public class DemangledType { } } - /** - * Sets the original mangled name - * @param mangled the original mangled name - */ - public void setOriginalMangled(String mangled) { - this.originalMangled = mangled; + @Override + public String getOriginalDemangled() { + return originalDemangled; } - /** - * Gets the original mangled name - * @return the original mangled name - */ - public String getOriginalMangled() { - return originalMangled; + @Override + public String getMangledString() { + return mangled; } public boolean isConst() { @@ -144,10 +79,6 @@ public class DemangledType { isConst = true; } - public boolean isFunction() { - return false; - } - public boolean isVolatile() { return isVolatile; } @@ -156,11 +87,13 @@ public class DemangledType { isVolatile = true; } - public DemangledType getNamespace() { + @Override + public Demangled getNamespace() { return namespace; } - public void setNamespace(DemangledType namespace) { + @Override + public void setNamespace(Demangled namespace) { if (this == namespace) { throw new IllegalArgumentException("Attempt to set this.namespace == this!"); } @@ -175,15 +108,23 @@ public class DemangledType { this.template = template; } - public String toSignature() { - return toNamespace(); + @Override + public String getSignature() { + return getNamespaceName(); } - public String toNamespace() { - StringBuffer buffer = new StringBuffer(); - if (namespace != null) { - buffer.append(namespace.toNamespace()); + @Override + public String getNamespaceString() { + return getName(true); + } + + private String getName(boolean includeNamespace) { + StringBuilder buffer = new StringBuilder(); + if (includeNamespace && namespace != null) { + buffer.append(namespace.getNamespaceString()); + buffer.append(Namespace.DELIMITER); } + buffer.append(demangledName); if (template != null) { buffer.append(template.toTemplate()); @@ -193,12 +134,16 @@ public class DemangledType { return ""; } - buffer.append(Namespace.DELIMITER); return buffer.toString(); } + @Override + public String getNamespaceName() { + return name; + } + @Override public String toString() { - return toNamespace(); + return getNamespaceString(); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledUnknown.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledUnknown.java index b7b24b499f..e630bb45ca 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledUnknown.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledUnknown.java @@ -26,38 +26,16 @@ import ghidra.program.model.symbol.SymbolUtilities; */ public class DemangledUnknown extends DemangledObject { - public DemangledUnknown() { - } - - public DemangledUnknown(String name) { + public DemangledUnknown(String mangled, String originalDemangled, String name) { + super(mangled, originalDemangled); setName(name); } -// DemangledUnknown(GenericDemangledVariable other) { -// super(other); -// } -// @Override public String getSignature(boolean format) { - return utilDemangled; + return originalDemangled; } -// @Override -// protected boolean isAlreadyDemangled(Program program, Address address) { -// return !utilDemangled.isEmpty(); -// } -// -// @Override -// public boolean applyTo(Program program, Address address, DemanglerOptions options, -// TaskMonitor monitor) throws Exception { -// -// if (isAlreadyDemangled(program, address)) { -// return true; -// } -// -// return super.applyTo(program, address, options, monitor); -// } -// @Override public String getName() { //These items likely do not have names or data types, so return the signature. diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledVariable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledVariable.java index 22dfed2c6f..c9a5092f52 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledVariable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemangledVariable.java @@ -15,6 +15,8 @@ */ package ghidra.app.util.demangler; +import org.apache.commons.lang3.StringUtils; + import ghidra.app.cmd.data.CreateDataCmd; import ghidra.app.util.PseudoDisassembler; import ghidra.program.model.address.Address; @@ -27,8 +29,6 @@ import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.util.Msg; import ghidra.util.exception.AssertException; import ghidra.util.task.TaskMonitor; -import util.demangler.GenericDemangledDataType; -import util.demangler.GenericDemangledVariable; /** * An interface to represent a demangled global variable. @@ -36,19 +36,11 @@ import util.demangler.GenericDemangledVariable; public class DemangledVariable extends DemangledObject { private DemangledDataType datatype; - public DemangledVariable(String name) { + public DemangledVariable(String mangled, String originalDemangled, String name) { + super(mangled, originalDemangled); setName(name); } - DemangledVariable(GenericDemangledVariable other) { - super(other); - - GenericDemangledDataType otherDatatype = other.getDataType(); - if (otherDatatype != null) { - datatype = (DemangledDataType) DemangledObjectFactory.convert(otherDatatype); - } - } - public void setDatatype(DemangledDataType datatype) { this.datatype = datatype; } @@ -70,7 +62,7 @@ public class DemangledVariable extends DemangledObject { @Override public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); buffer.append(specialPrefix == null ? EMPTY_STRING : specialPrefix + SPACE); buffer.append( visibility == null || "global".equals(visibility) ? EMPTY_STRING : visibility + SPACE); @@ -80,7 +72,7 @@ public class DemangledVariable extends DemangledObject { buffer.append(isVirtual ? "virtual" + SPACE : EMPTY_STRING); String n = getDemangledName(); - boolean hasName = (n != null) && !n.isEmpty(); + boolean hasName = !StringUtils.isBlank(n); StringBuffer datatypeBuffer = new StringBuffer(); String spacer = EMPTY_STRING; @@ -88,7 +80,7 @@ public class DemangledVariable extends DemangledObject { !(datatype instanceof DemangledFunctionReference) && !(datatype instanceof DemangledFunctionIndirect)) { if (datatype != null) { - datatypeBuffer.append(datatype.toSignature()); + datatypeBuffer.append(datatype.getSignature()); spacer = SPACE; } } @@ -139,11 +131,10 @@ public class DemangledVariable extends DemangledObject { datatypeBuffer.append(spacer); spacer = EMPTY_STRING; - datatypeBuffer.append(namespace.toNamespace()); + datatypeBuffer.append(namespace.getNamespaceString()); - if (!hasName) { - int end = buffer.length(); - datatypeBuffer.delete(end - 2, end); // strip off the last namespace characters + if (hasName) { + datatypeBuffer.append(NAMESPACE_SEPARATOR); } } @@ -153,22 +144,16 @@ public class DemangledVariable extends DemangledObject { datatypeBuffer.append(getName()); } - datatypeBuffer.append(specialMidfix == null ? EMPTY_STRING : specialMidfix + SPACE); - datatypeBuffer.append(specialSuffix == null ? EMPTY_STRING : SPACE + specialSuffix); - if (datatype instanceof DemangledFunctionPointer) { DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) datatype; - //return funcPtr.toSignature(buffer.toString()); return buffer.append(funcPtr.toSignature(datatypeBuffer.toString())).toString(); } else if (datatype instanceof DemangledFunctionReference) { DemangledFunctionReference funcRef = (DemangledFunctionReference) datatype; - //return funcRef.toSignature(buffer.toString()); return buffer.append(funcRef.toSignature(datatypeBuffer.toString())).toString(); } else if (datatype instanceof DemangledFunctionIndirect) { DemangledFunctionIndirect funcDef = (DemangledFunctionIndirect) datatype; - //return funcDef.toSignature(buffer.toString()); return buffer.append(funcDef.toSignature(datatypeBuffer.toString())).toString(); } @@ -177,6 +162,20 @@ public class DemangledVariable extends DemangledObject { return buffer.toString(); } + @Override + public String getNamespaceName() { + + String n = getDemangledName(); + if (!StringUtils.isBlank(n)) { + return n; + } + + if (datatype != null) { + return datatype.getSignature(); + } + return ""; // shouldn't happen + } + @Override protected boolean isAlreadyDemangled(Program program, Address address) { Data data = program.getListing().getDefinedDataAt(address); @@ -199,9 +198,6 @@ public class DemangledVariable extends DemangledObject { } Symbol demangledSymbol = applyDemangledName(address, true, true, program); - - //TODO replace existing datatype? - DataType demangledDT = getProgramDataType(program); if (address.isExternalAddress()) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java index c51f9d2b9a..7517ae882f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/DemanglerUtil.java @@ -101,31 +101,6 @@ public class DemanglerUtil { return ClassSearcher.getInstances(Demangler.class); } - /** - * Converts the list of names into a namespace demangled type. - * Given names = { "A", "B", "C" }, which represents "A::B::C". - * The following will be created {@literal "Namespace{A}->Namespace{B}->Namespace{C}"} - * and Namespace{C} will be returned. - * - * NOTE: the list will be empty after the call. - * @param names the names to convert - * @return the newly created type - */ - public static DemangledType convertToNamespaces(List names) { - if (names.size() == 0) { - return null; - } - int index = names.size() - 1; - DemangledType myNamespace = new DemangledType(names.get(index)); - DemangledType namespace = myNamespace; - while (--index >= 0) { - DemangledType parentNamespace = new DemangledType(names.get(index)); - namespace.setNamespace(parentNamespace); - namespace = parentNamespace; - } - return myNamespace; - } - /** * Remove superfluous function signature spaces from specified string * @param str string @@ -146,13 +121,4 @@ public class DemanglerUtil { matcher.appendTail(buffy); return buffy.toString(); } - - public static void setNamespace(DemangledType dt, DemangledType namespace) { - if (dt.getNamespace() == null) { - dt.setNamespace(namespace); - } - else { - setNamespace(dt.getNamespace(), namespace); - } - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/ParameterReceiver.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/ParameterReceiver.java deleted file mode 100644 index eeebdc3fe2..0000000000 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/demangler/ParameterReceiver.java +++ /dev/null @@ -1,37 +0,0 @@ -/* ### - * 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. - * 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; - -import java.util.List; - -/** - * A generic interface to represent - * object that support parameters. - */ -public interface ParameterReceiver { - /** - * Adds the specified parameter to this object. - * @param parameter the parameter to add - */ - public void addParameter(DemangledDataType parameter); - - /** - * Returns the parameters added to this object. - * @return the parameters added to this object - */ - public List getParameters(); -} diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java index 0a140605f3..a6b0409958 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/plugin/core/colorizer/ColorizingPluginTest.java @@ -400,8 +400,7 @@ public class ColorizingPluginTest extends AbstractGhidraHeadedIntegrationTest { ActionContext context = getActionContext(); performAction(setColorAction, context, false); - Window chooserWindow = waitForWindow(null, ColorizingServiceProvider.COLOR_CHOOSER_TITLE, - DEFAULT_WINDOW_TIMEOUT); + Window chooserWindow = waitForWindow(ColorizingServiceProvider.COLOR_CHOOSER_TITLE); assertNotNull("Did not find Color Chooser", chooserWindow); GhidraColorChooser colorChooser = findComponent(chooserWindow, GhidraColorChooser.class); JButton okButton = findButtonByText(chooserWindow, "OK"); diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledMethod.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/DemanglerParseException.java similarity index 71% rename from Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledMethod.java rename to Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/DemanglerParseException.java index 36ec6f24fe..1c6c36994c 100644 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledMethod.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/DemanglerParseException.java @@ -13,11 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package util.demangler; +package ghidra.app.util.demangler.gnu; -public class GenericDemangledMethod extends GenericDemangledFunction { +/** + * Exception to signal a problem parsing a demangled string + */ +public class DemanglerParseException extends RuntimeException { - public GenericDemangledMethod(String name) throws GenericDemangledException { - super(name); + public DemanglerParseException(String message) { + super(message); } } diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java index 452e8c2acc..ebc234d92f 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemangler.java @@ -113,9 +113,9 @@ public class GnuDemangler implements Demangler { } if (globalPrefix != null) { - // TODO: may need better naming convention for demangled function DemangledFunction dfunc = - new DemangledFunction(globalPrefix + demangledObject.getName()); + new DemangledFunction(originalMangled, demangled, + globalPrefix + demangledObject.getName()); dfunc.setNamespace(demangledObject.getNamespace()); demangledObject = dfunc; } @@ -123,14 +123,12 @@ public class GnuDemangler implements Demangler { demangledObject.setSignature(demangled); } - demangledObject.setOriginalMangled(originalMangled); - if (isDwarf) { - DemangledAddressTable dat = new DemangledAddressTable((String) null, 1); + DemangledAddressTable dat = + new DemangledAddressTable(originalMangled, demangled, (String) null, false); dat.setSpecialPrefix("DWARF Debug "); dat.setName(demangledObject.getName()); dat.setNamespace(demangledObject.getNamespace()); - dat.setOriginalMangled(originalMangled); return dat; } @@ -209,7 +207,7 @@ public class GnuDemangler implements Demangler { return null; } - GnuDemanglerParser parser = new GnuDemanglerParser(process); + GnuDemanglerParser parser = new GnuDemanglerParser(); DemangledObject demangledObject = parser.parse(mangled, demangled); return demangledObject; } diff --git a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java index 47c9ecda9b..cc6fdb639d 100644 --- a/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java +++ b/Ghidra/Features/GnuDemangler/src/main/java/ghidra/app/util/demangler/gnu/GnuDemanglerParser.java @@ -15,16 +15,19 @@ */ package ghidra.app.util.demangler.gnu; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -import ghidra.app.util.NamespaceUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + import ghidra.app.util.SymbolPath; import ghidra.app.util.demangler.*; import ghidra.program.model.lang.CompilerSpec; +import ghidra.program.model.symbol.Namespace; import ghidra.util.StringUtilities; public class GnuDemanglerParser { @@ -35,543 +38,468 @@ public class GnuDemanglerParser { private static final String TYPEINFO_NAME_FOR = "typeinfo name for "; private static final String TYPEINFO_FN_FOR = "typeinfo fn for "; private static final String TYPEINFO_FOR = "typeinfo for "; - private static final String REFERENCE_TEMPORARY_FOR = "reference temporary for "; - private static final String GUARD_VARIABLE_FOR = "guard variable for "; private static final String COVARIANT_RETURN_THUNK = "covariant return thunk"; - private static final String VIRTUAL_THUNK = "virtual thunk"; - private static final String NONVIRTUAL_THUNK = "non-virtual thunk"; - private static final String NAMESPACE_DELIMITER = "::"; + private static final Set ADDRESS_TABLE_PREFIXES = Set.of( + CONSTRUCTION_VTABLE_FOR, + VTT_FOR, + VTABLE_FOR, + TYPEINFO_FN_FOR, + TYPEINFO_FOR); - /** - *

-	 * Syntax: bob(const(Rect &, bool))
+	private static final String OPERATOR = "operator";
+	private static final String LAMBDA = "lambda";
+	private static final String VAR_ARGS = "...";
+	private static final String THUNK = "thunk";
+	private static final String CONST = " const";
+	private static final char NULL_CHAR = '\u0000';
+
+	/*
+	 * Sample:  bob((Rect &, unsigned long))
+	 *          bob(const(Rect &, bool))
 	 *
-	 * pattern: 'const' with surrounding '()' with a capture group for the contents
-	 * 
- */ - private static final Pattern CONST_FUNCTION_PATTERN = Pattern.compile("const\\((.*)\\)"); - - /** - *
-	 * Syntax: bob((Rect &, unsigned long))
+	 * Pattern: name(([const] [params]))
 	 *
-	 * pattern: optional spaces followed by '()' with a capture group for the contents of the
-	 *          parens
-	 * note:    this pattern is used for matching the arguments string, in the above example it
-	 *          would be: (Rect &, unsigned long)
-	 * 
+ * Parts: -optional spaces + * -optional (const) (non-capture group) + * -followed by '()' with optinal parameter text (capture group 1) + * + * Note: this pattern is used for matching the arguments string, in the above examples it + * would be: + * Rect &, unsigned long + * and + * Rect &, bool + * */ - private static final Pattern UNNECESSARY_PARENS_PATTERN = Pattern.compile("\\s*\\((.*)\\)\\s*"); + private static final Pattern UNNECESSARY_PARENS_PATTERN = + Pattern.compile("\\s*(?:const){0,1}\\((.*)\\)\\s*"); - /** - *
-	 * Syntax: 	bob(short (&)[7])
+	/*
+	 * Sample: 	bob(short (&)[7])
 	 * 			bob(int const[8] (*) [12])
 	 *
-	 * 			   typename[optional '*'](*|&)[optional spaces][optional value]
+	 * Pattern: name[optional '*'](*|&)[optional spaces][optional value]
 	 *
-	 * pattern:
-	 * 				-a word
+	 * Parts:
+	 * 				-a word (capture group 1)
+	 *              -followed by an optional pointer '*'
 	 * 				-followed by a space
-	 * 				-*optional: any other text (e.g., const[8])
-	 * 				-followed by '()' that contain a '&' or a '*'
-	 * 				-followed by one or more '[]' with optional interior text
-	 * 
+ * -*optional: any other text (e.g., const[8]) (non-capture group) + * -followed by '()' that contain a '&' or a '*' (capture group 2) + * -followed by one or more '[]' with optional interior text (capture group 3) + * + * Group Samples: + * short (&)[7] + * 1 short + * 2 & + * 3 [7] + * + * CanRxItem (&) [2][64u] + * 1 CanRxItem + * 2 & + * 3 [2][64u] + * */ private static final Pattern ARRAY_POINTER_REFERENCE_PATTERN = - Pattern.compile("([\\w:]+)\\*?\\s(.*)\\(([&*])\\)\\s*((?:\\[.*?\\])+)"); + Pattern.compile("([\\w:]+)\\*?\\s(?:.*)\\(([&*])\\)\\s*((?:\\[.*?\\])+)"); - /** - *
-	 * Syntax: bob(short (&)[7])
+	/*
+	 * Sample:  bob(short (&)[7])
 	 *
-	 * 			   (*|&)[optional spaces][optional value]
+	 * Pattern: (*|&)[optional spaces][optional value]
 	 *
-	 * pattern: '()' that contain a '&' or a '*' followed by '[]' with optional text; a capture
-	 *          group for the contents of the parens
+	 * Parts:   
+	 * 			-'()' that contain a '&' or a '*' 
+	 *          -followed by '[]' with optional text
 	 * 
*/ private static final Pattern ARRAY_POINTER_REFERENCE_PIECE_PATTERN = - Pattern.compile("\\(([&*])\\)\\s*\\[.*?\\]"); + Pattern.compile("\\([&*]\\)\\s*\\[.*?\\]"); - /** - *
-	* Syntax: (unsigned)4294967295
+	/*
+	* Sample:  (unsigned)4294967295
 	*
-	* 			   (some text)[optional space]1 or more characters
+	* Pattern: (some text)[optional space]1 or more characters
 	*
-	* Regex:
-	*
-	* pattern:
+	* Parts:
 	* 			-parens containing text
-	* 			--the text can have "::" namespace separators (this is in a non-capturing group) and
-	*             must be followed by more text
-	*           --the text can have multiple words, such as (unsigned long)
+	* 				--the text can have "::" namespace separators (non-capturing group) and
+	*             	  must be followed by more text
+	*           	--the text can have multiple words, such as (unsigned long)
 	*           -optional space
-	*           -optional '-' character
+	*           -optional '-' character (a negative sign character)
 	* 			-followed by more text (with optional spaces)
 	* 
*/ private static final Pattern CAST_PATTERN = - Pattern.compile("\\((?:\\w+\\s)*\\w+(?:::\\w+)*\\)\\s*-*\\w+"); + Pattern.compile("\\((?:\\w+\\s)*\\w+(?:::\\w+)*\\)\\s*-{0,1}\\w+"); - private static final Pattern CONVERSION_OPERATOR_PATTERN = - Pattern.compile("(.*operator) (.*)\\(\\).*"); + /* + * Sample: Magick::operator<(Magick::Coordinate const&, Magick::Coordinate const&) + * std::basic_istream >& std::operator>> >(std::basic_istream >&, char&) + * bool myContainer::operator<< (double) + * + * Pattern: [return_type] operator operator_character(s) (opeartor_params) [trailing text] + * + * Parts: + * -optional a return type (capture group 1) + * -operator (capture group 2) + * -operator character(s) (capture group 3) + * -optional space + * -optional templates (capture group 4) + * -parameters (capture group 5) + * -trailing text (capture group 6) + * + * Note: this regex is generated from all known operator patterns and looks like: + * (.*operator(generated_text).*)\s*(\(.*\))(.*) + */ + private static final Pattern OVERLOAD_OPERATOR_PATTERN = + createOverloadedOperatorPattern(); - /** - *
-	* Syntax: operator new(unsigned long)
-	*         operator new(void*)
-	*         operator new[](void*)
-	*
-	* pattern:
-	* 			-operator
+	/*
+	* Sample:  std::integral_constant::operator bool() const
+	*          Magick::Color::operator std::basic_string, std::allocator >() const
+	*         
+	* Pattern: operator type() [trailing text]
+	* 
+	* Parts:
+	* 			-operator (capture group 1)
 	* 			-space
-	*           -keyword 'new' or 'delete'
-	*           -optional array brackets
-	*           -optional parameters
+	*           -keyword for cast type (capture group 2)
+	*           -optional keywords
+	*
+	*/
+	private static final Pattern CONVERSION_OPERATOR_PATTERN =
+		Pattern.compile("(.*" + OPERATOR + ") (.*)\\(\\).*");
+
+	/*
+	* Sample:  operator new(unsigned long)
+	*          operator new(void*)
+	*          operator new[](void*)
+	*
+	* Pattern: operator new|delete[] ([parameters]) [trailing text]
+	*
+	* Parts:
+	* 			-operator (capture group 1)
+	* 			-space
+	*           -keyword 'new' or 'delete' (capture group 2)
+	*           -optional array brackets (capture group 3)
+	*           -optional parameters (capture group 4)
 	*
-	* 
*/ private static final Pattern NEW_DELETE_OPERATOR_PATTERN = - Pattern.compile("(.*operator) (new|delete)(\\[\\])?\\((.*)\\).*"); + Pattern.compile("(.*" + OPERATOR + ") (new|delete)(\\[\\])?\\((.*)\\).*"); - // note: the '?' after the .* this is there to allow the trailing digits to match as many as - // possible + /* + * Pattern for newer C++ lambda syntax: + * + * Sample: {lambda(void const*, unsigned int)#1} + * + * Pattern: [optional text] brace lambda([parameters])#digits brace + * + * Parts: + * -full text without leading characters (capture group 1) + * -parameters of the lambda function (capture group 2) + * -trailing id (capture group 3) + */ + private static final Pattern LAMBDA_PATTERN = + Pattern.compile(".*(\\{" + LAMBDA + "\\((.*)\\)(#\\d+)\\})"); + + /* + * Sample: covariant return thunk to Foo::Bar::copy(Foo::CoolStructure*) const + * + * Pattern: text for|to text + * + * Parts: + * -required text (capture group 2) + * -a space + * -'for' or 'to' (capture group 3) + * -a space + * -optional text (capture group 4) + * + * Note: capture group 1 is the combination of groups 2 and 3 + * + * Examples: + * construction vtable for + * vtable for + * typeinfo name for + * typeinfo for + * guard variable for + * covariant return thunk to + * virtual thunk to + * non-virtual thunk to + */ + private static final Pattern DESCRIPTIVE_PREFIX_PATTERN = + Pattern.compile("((.+ )+(for|to) )(.+)"); + + /** + * The c 'decltype' keyword pattern + */ + private static final Pattern DECLTYPE_RETURN_TYPE_PATTERN = + Pattern.compile("decltype \\(.*\\)"); + + /** + * Simple pattern to match any text that is trailed by digits + * + * note: the '?' after the .* this is there to allow the trailing digits to match as many as + * possible + */ private static final Pattern ENDS_WITH_DIGITS_PATTERN = Pattern.compile("(.*?)\\d+"); - private static final String VAR_ARGS = "..."; + private static Pattern createOverloadedOperatorPattern() { - private static final String CONST_KEYWORD = " const"; + //@formatter:off + Set operators = new HashSet<>(Set.of( + "++", "--", + "+", "-", "*", "/", "%", + "==", "!=", ">", "<", ">=", "<=", + "&", "|", ">>", "<<", "~", "^", + "&&", "||", "!", + "=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", ">>=", "<<=", + ",", "()", + "\"\"" + )); + //@formatter:on - private static final String ANONYMOUS_NAMESPACE = "\\(anonymous namespace\\)"; - private static final String ANONYMOUS_NAMESPACE_FIXUP = "anonymous_namespace"; + CollectionUtils.transform(operators, Pattern::quote); + String alternated = StringUtils.join(operators, "|"); - private GnuDemanglerNativeProcess process; + String returnType = "(.* ){0,1}"; + String operatorTemplates = "(<.+>){0,1}"; + String operatorPrefix = + "(.*" + OPERATOR + "(" + alternated + ")\\s*" + operatorTemplates + ".*)\\s*"; + String parameters = "(\\(.*\\))"; + String trailing = "(.*)"; - public GnuDemanglerParser(GnuDemanglerNativeProcess process) { - this.process = process; + return Pattern.compile(returnType + operatorPrefix + parameters + trailing); } - public DemangledObject parse(String mangled, String demangled) { - try { - return doParse(mangled, demangled); - } - catch (Exception e) { - throw new RuntimeException( - "Unexpected problem parsing " + demangled + " from mangled string: " + mangled, e); + private String mangledSource; + private String demangledSource; + + /** + * Parses the given demangled string and creates a {@link DemangledObject} + * + * @param mangled the original mangled text + * @param demangled the demangled text + * @return the demangled object + * @throws DemanglerParseException if there is an unexpected error parsing + */ + public DemangledObject parse(String mangled, String demangled) + throws DemanglerParseException { + + this.mangledSource = mangled; + this.demangledSource = demangled; + + DemangledObjectBuilder builder = getSpecializedBuilder(demangled); + if (builder != null) { + return builder.build(); } + + return parseFunctionOrVariable(demangled); } - public DemangledObject doParse(String mangled, String demangled) throws IOException { - if (demangled.trim().equals("c")) { - return null; + private DemangledObjectBuilder getSpecializedBuilder(String demangled) { + + DemangledObjectBuilder operatorHandler = getOperatorHandler(demangled); + if (operatorHandler != null) { + return operatorHandler; } - // remove spaces from anonymous namespace strings - demangled = demangled.replaceAll(ANONYMOUS_NAMESPACE, ANONYMOUS_NAMESPACE_FIXUP); + DemangledObjectBuilder handler = getSpecialPrefixHandler(mangledSource, demangled); + if (handler != null) { + return handler; + } - if (mangled != null && mangled.startsWith("_ZZ")) {//TODO: just detect this case, so we don't need "mangled" - return parseGuardVariableOrReferenceTemporary(demangled, ""); + return null; + } + + private OperatorHandler getOperatorHandler(String demangled) { + + OperatorHandler handler = new OverloadOperatorHandler(demangled); + if (handler.matches(demangled)) { + return handler; } - if (demangled.startsWith(GUARD_VARIABLE_FOR)) { - return parseGuardVariableOrReferenceTemporary(demangled, GUARD_VARIABLE_FOR); + + handler = new ConversionOperatorHandler(demangled); + if (handler.matches(demangled)) { + return handler; } - if (demangled.startsWith(REFERENCE_TEMPORARY_FOR)) { - return parseGuardVariableOrReferenceTemporary(demangled, REFERENCE_TEMPORARY_FOR); + + handler = new NewOrDeleteOperatorHandler(demangled); + if (handler.matches(demangled)) { + return handler; } - if (demangled.startsWith(TYPEINFO_NAME_FOR)) { - return parseTypeInfoName(demangled); - } - if (demangled.startsWith(TYPEINFO_FOR)) { - return parseAddressTable(demangled, TYPEINFO_FOR); - } - if (demangled.startsWith(TYPEINFO_FN_FOR)) { - return parseAddressTable(demangled, TYPEINFO_FN_FOR); - } - if (demangled.startsWith(VTABLE_FOR)) { - return parseAddressTable(demangled, VTABLE_FOR); - } - if (demangled.startsWith(VTT_FOR)) { - return parseAddressTable(demangled, VTT_FOR); - } - if (demangled.startsWith(CONSTRUCTION_VTABLE_FOR)) { - Matcher matcher = ENDS_WITH_DIGITS_PATTERN.matcher(demangled); - if (!matcher.matches()) { - return parseAddressTable(demangled, CONSTRUCTION_VTABLE_FOR); + + return null; + } + + private SpecialPrefixHandler getSpecialPrefixHandler(String mangled, String demangled) { + + Matcher matcher = DESCRIPTIVE_PREFIX_PATTERN.matcher(demangled); + if (matcher.matches()) { + String prefix = matcher.group(1); + String type = matcher.group(4); + if (prefix.contains(THUNK)) { + return new ThunkHandler(demangled, prefix, type); } - // ends with a number, strip it off - String textWithoutTrailingDigits = matcher.group(1); - return parseAddressTable(textWithoutTrailingDigits, CONSTRUCTION_VTABLE_FOR); - } - if (demangled.startsWith(NONVIRTUAL_THUNK) || // _ZTh - demangled.startsWith(VIRTUAL_THUNK) || // _ZTv - demangled.startsWith(COVARIANT_RETURN_THUNK)) {// _ZTc - - int index = mangled.indexOf('_', 1); - if (index < 0) { - return null; - } - if (demangled.startsWith(VIRTUAL_THUNK) || - demangled.startsWith(COVARIANT_RETURN_THUNK)) { - // skip second constant for virtual thunk - index = mangled.indexOf('_', ++index); - if (index < 0) { - return null; - } + if (ADDRESS_TABLE_PREFIXES.contains(prefix)) { + return new AddressTableHandler(demangled, prefix, type); } - String referencedMangledName = "_Z" + mangled.substring(index + 1); - String referencedDemangledName = process.demangle(referencedMangledName); - if (referencedMangledName.equals(referencedDemangledName) || - referencedDemangledName.length() == 0) { - return null; + if (prefix.startsWith(TYPEINFO_NAME_FOR)) { + return new TypeInfoNameHandler(demangled, TYPEINFO_NAME_FOR); } - DemangledObject refObj = parse(referencedMangledName, referencedDemangledName); - if (!(refObj instanceof DemangledFunction)) { - return null; - } - refObj.setOriginalMangled(referencedMangledName); - refObj.setSignature(referencedDemangledName); - - // mark referenced function as a thiscall - ((DemangledFunction) refObj).setCallingConvention( - CompilerSpec.CALLING_CONVENTION_thiscall); - - // TODO: (SCR 9800) Need to add support for Covariant Return Thunks which will allow the return type - // to differ from the underlying thunked function - - DemangledThunk thunkObj = new DemangledThunk((DemangledFunction) refObj); - - if (demangled.startsWith(COVARIANT_RETURN_THUNK)) { - thunkObj.setCovariantReturnThunk(); - } - - // TODO: may need more stuff from demangled string - - index = demangled.indexOf(" to "); - if (index > 0) { - thunkObj.setSignaturePrefix(demangled.substring(0, index + 4)); - } - - return thunkObj; + return new ItemInNamespaceHandler(demangled, prefix, type); } - DemangledObject conversionOperator = parseConversionOperator(demangled); - if (conversionOperator != null) { - return conversionOperator;// special case + if (mangled.startsWith("_ZZ")) { + return new ItemInNamespaceHandler(demangled); } + return null; + } - DemangledObject newDeleteOperator = parseNewOrDeleteOperator(demangled); - if (newDeleteOperator != null) { - return newDeleteOperator;// special case - } + private DemangledObject parseFunctionOrVariable(String demangled) { ParameterLocator paramLocator = new ParameterLocator(demangled); - if (!paramLocator.hasParameters()) { return parseVariable(demangled); } int paramStart = paramLocator.getParamStart(); int paramEnd = paramLocator.getParamEnd(); - if (paramStart + 1 == demangled.indexOf(')')) {//check for overloaded 'operator()' - int pos = paramStart - "operator".length(); - if (pos >= 0 && demangled.indexOf("operator") == pos) { - paramStart = demangled.indexOf('(', paramStart + 1); - paramEnd = demangled.lastIndexOf(')'); - } - } String parameterString = demangled.substring(paramStart + 1, paramEnd).trim(); List parameters = parseParameters(parameterString); + // 'prefix' is the text before the parameters int prefixEndPos = paramStart; - - String chargeType = null; - if (demangled.charAt(paramStart - 1) == ']') {//skip the GNU charge type... - int sqBracketStartPos = backIndexOf(demangled, paramStart - 1, '['); - // - // This is case would include operator_new[] and operator_delete[] - // check to see if empty brackets exists - // - if (sqBracketStartPos != prefixEndPos - 2) { - chargeType = demangled.substring(sqBracketStartPos, paramStart); - prefixEndPos = sqBracketStartPos; - } - } - String prefix = demangled.substring(0, prefixEndPos).trim(); - prefix = fixupTemplateSeparators(prefix); + prefix = fixupInternalSeparators(prefix); - int nameStartPos = backIndexOf(prefix, prefix.length() - 1, ' '); - if (nameStartPos == -1) { - throw new RuntimeException(); - } - String name = prefix.substring(nameStartPos, prefix.length()); - if (chargeType != null) { - name += chargeType; + int nameStart = Math.max(0, prefix.lastIndexOf(' ')); + String name = prefix.substring(nameStart, prefix.length()).trim(); + DemangledFunction function = new DemangledFunction(mangledSource, demangled, null); + + String simpleName = name; + LambdaName lambdaName = getLambdaName(demangled); + if (lambdaName != null) { + String uniqueName = lambdaName.getFullText(); + String fullLambda = fixupInternalSeparators(uniqueName); + simpleName = name.replace("{lambda", fullLambda); + function = new DemangledLambda(mangledSource, demangled, null); + function.setSignature(lambdaName.getFullText()); } // For GNU, we cannot leave the return type as null, because the DemangleCmd will fill in // pointer to the class to accommodate windows demangling - DemangledMethod method = new DemangledMethod((String) null); - method.setReturnType(new DemangledDataType("undefined")); + function.setReturnType(new DemangledDataType(mangledSource, demangled, "undefined")); for (DemangledDataType parameter : parameters) { - method.addParameter(parameter); + function.addParameter(parameter); } - setNameAndNamespace(method, name); + setNameAndNamespace(function, simpleName); - if (method.getName().startsWith("operator")) { - char ch = method.getName().charAt("operator".length()); - if (!Character.isLetterOrDigit(ch)) { - method.setOverloadedOperator(true); - } + // check for return type + if (nameStart > 0) { + String returnType = prefix.substring(0, nameStart); + setReturnType(function, returnType); } - if (nameStartPos > 0) {//we have a return type - String returnType = prefix.substring(0, nameStartPos); - method.setReturnType(parseDataType(returnType)); + if (demangled.endsWith(CONST)) { + function.setConst(true); } - return method; + + return function; } - private DemangledObject parseTypeInfoName(String demangled) { + private void setReturnType(DemangledFunction function, String returnType) { - String classname = demangled.substring(TYPEINFO_NAME_FOR.length()).trim(); + if (DECLTYPE_RETURN_TYPE_PATTERN.matcher(returnType).matches()) { + // Not sure yet if there is any information we wish to recover from this pattern. + // Sample: decltype (functionName({parm#1}, (float)[42c80000])) + return; + } - DemangledString demangledString = - new DemangledString("typeinfo_name", classname, -1/*unknown length*/, false); - demangledString.setSpecialPrefix("typeinfo name"); - demangledString.setUtilDemangled(demangled); - setNamespace(demangledString, classname); - return demangledString; + function.setReturnType(parseDataType(returnType)); } - private DemangledObject parseConversionOperator(String demangled) { - // - // An example to follow along with: - // - // 'conversion operator' syntax is: - // operator () - // - // OR - // operator const&() const - // operator const &() const - // - // Namespace::Class::operator Namespace::Type() - // - // NS1::Foo::operator std::string() - // - Matcher matcher = CONVERSION_OPERATOR_PATTERN.matcher(demangled); + private LambdaName getLambdaName(String name) { + Matcher matcher = LAMBDA_PATTERN.matcher(name); if (!matcher.matches()) { return null; } - // this will yield: - // fullName: NS1::Foo::operator - // fullReturnType: std::string - String fullName = matcher.group(1);// group 0 is the entire match string - String fullReturnType = matcher.group(2); - - boolean isConst = false; - int index = fullReturnType.indexOf(CONST_KEYWORD); - if (index != -1) { - fullReturnType = fullReturnType.replace(CONST_KEYWORD, ""); - isConst = true; - } - - DemangledMethod method = new DemangledMethod((String) null); - DemangledDataType returnType = createDataType(fullReturnType); - if (isConst) { - returnType.setConst(); - } - method.setReturnType(returnType); - - // 'conversion operator' syntax is operator () - // assume fullName endsWith '::operator' - int operatorIndex = fullName.lastIndexOf("::operator"); - String namespace = fullName.substring(0, operatorIndex); - - String templatelessNamespace = stripOffTemplates(namespace); - setNamespace(method, templatelessNamespace); - - // shortReturnType: string - String templatelessReturnType = stripOffTemplates(fullReturnType); - SymbolPath path = new SymbolPath(templatelessReturnType); - String shortReturnTypeName = path.getName(); - - // - // The preferred name: 'operator basic_string()' - // - // Ghidra does not allow spaces in the name or extra parens. So, make a name that is - // as clear as possible in describing the construct. - // - method.setName("operator.cast.to." + shortReturnTypeName); - - method.setSignature(fullName + " " + fullReturnType); - method.setOverloadedOperator(true); - - return method; - } - - private DemangledObject parseNewOrDeleteOperator(String demangled) { - // - // An example to follow along with: - // - // 'operator' syntax is: - // operator new(void*) - // - // OR - // operator new(unsigned long) - // operator delete[](void*) - // - // Namespace::Class::operator new() - // - - Matcher matcher = NEW_DELETE_OPERATOR_PATTERN.matcher(demangled); - if (!matcher.matches()) { - return null; - } - - String operatorText = matcher.group(1);// group 0 is the entire match string - String operatorName = matcher.group(2); - String arrayBrackets = matcher.group(3); - String parametersText = matcher.group(4); - - DemangledMethod method = new DemangledMethod((String) null); - DemangledDataType returnType = new DemangledDataType("void"); - if (operatorName.startsWith("new")) { - returnType.incrementPointerLevels(); - } - - method.setReturnType(returnType); - - // 'conversion operator' syntax is operator (), where the - // operator itself could be in a class namespace - setNameAndNamespace(method, operatorText); - - List parameters = parseParameters(parametersText); - for (DemangledDataType parameter : parameters) { - method.addParameter(parameter); - } - - // - // The preferred name: 'operator new()' - // - // Ghidra does not allow spaces in the name or extra parens. So, make a name that is - // as clear as possible in describing the construct. - // - String name = operatorName; - if (arrayBrackets != null) { - name += "[]"; - } - method.setName("operator." + name); - - method.setSignature(operatorText + " " + operatorName); - method.setOverloadedOperator(true); - - return method; - } - - private DemangledDataType createDataType(String fullReturnType) { - DemangledDataType parsedDataType = parseDataType(fullReturnType); - return parsedDataType; + String fullText = matcher.group(1); + String params = matcher.group(2); + String trailing = matcher.group(3); + return new LambdaName(fullText, params, trailing); } private String stripOffTemplates(String string) { StringBuilder buffy = new StringBuilder(); - int templateCount = 0; + int depth = 0; for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (c == '<') { - templateCount++; + depth++; continue; } else if (c == '>') { - templateCount--; + depth--; continue; } - if (templateCount == 0) { + if (depth == 0) { buffy.append(c); } } return buffy.toString(); } - private DemangledObject parseGuardVariableOrReferenceTemporary(String demangled, - String prefix) { - String str = demangled.substring(prefix.length()).trim(); + private DemangledObject parseItemInNamespace(String itemText) { - int pos = str.lastIndexOf(NAMESPACE_DELIMITER); + int pos = itemText.lastIndexOf(Namespace.DELIMITER); if (pos == -1) { - throw new RuntimeException(); - } - if (str.endsWith(")")) { - throw new RuntimeException(); + throw new DemanglerParseException( + "Expected the demangled string to contain a namespace"); } - DemangledObject dobj = parse(null, str.substring(0, pos)); - if (dobj == null) { - return null; - } - if (str.endsWith(CONST_KEYWORD)) { - str = str.substring(0, str.length() - CONST_KEYWORD.length()); - dobj.setConst(true); - } - - String name = str.substring(pos + 2); - name = name.replaceAll(" ", "_"); - return dobjToNamespace(dobj, name); - } - - private DemangledObject dobjToNamespace(DemangledObject parent, String name) { - DemangledType namespace = null; - if (parent instanceof DemangledFunction) { - DemangledFunction dfun = (DemangledFunction) parent; - namespace = new DemangledFunctionType(dfun.getName() + dfun.getParameterString(), - dfun.getSignature(false)); - } - else { - namespace = new DemangledType(parent.getName()); - } - - namespace.setNamespace(parent.getNamespace()); - - DemangledVariable variable = new DemangledVariable(name); - variable.setNamespace(namespace); - return variable; + String parentText = itemText.substring(0, pos); + DemangledObject parent = parseFunctionOrVariable(parentText); + String name = itemText.substring(pos + 2); + DemangledObject item = parseFunctionOrVariable(name); + item.setNamespace(parent); + return item; } /** - * Replaces all SPACES and COLONS inside the templates with UNDERSCORES. + * Replaces all SPACES and COLONS inside of groups (templates/parentheses) + * with UNDERSCORES and DASHES, respectively */ - private String fixupTemplateSeparators(String name) { - StringBuffer buffer = new StringBuffer(); - int templateLevel = 0; - char last = '\u0000'; + private String fixupInternalSeparators(String name) { + StringBuilder buffer = new StringBuilder(); + int depth = 0; + char last = NULL_CHAR; for (int i = 0; i < name.length(); ++i) { char ch = name.charAt(i); - if (ch == '<') { - ++templateLevel; + if (ch == '<' || ch == '(') { + ++depth; } - else if (ch == '>' && templateLevel != 0) { - --templateLevel; + else if ((ch == '>' || ch == ')') && depth != 0) { + --depth; } - if (templateLevel > 0 && ch == ' ') { - char next = (i + 1) < name.length() ? name.charAt(i + 1) : '\u0000'; + if (depth > 0 && ch == ' ') { + char next = (i + 1) < name.length() ? name.charAt(i + 1) : NULL_CHAR; if (isSurroundedByCharacters(last, next)) { // separate words with a value so they don't run together; drop the other spaces buffer.append('_'); } } - else if (templateLevel > 0 && ch == ':') { + else if (depth > 0 && ch == ':') { buffer.append('-'); } else { @@ -584,26 +512,12 @@ public class GnuDemanglerParser { } private boolean isSurroundedByCharacters(char last, char next) { - if (last == '\u0000' || next == '\u0000') { + if (last == NULL_CHAR || next == NULL_CHAR) { return false; } return Character.isLetterOrDigit(last) && Character.isLetterOrDigit(next); } - /** - * Searches backward for the specified character - * starting at the index. - */ - private int backIndexOf(String string, int index, char ch) { - while (index >= 0) { - if (string.charAt(index) == ch) { - return index; - } - --index; - } - return 0; - } - /** * This method separates the parameters as strings. * This is more complicated then one might initially think. @@ -626,37 +540,29 @@ public class GnuDemanglerParser { // note: this matches the syntax of bob( const(param1, param2)), where for some // reason the demangled symbol has const() around the params. After research, this is seen // when demangling functions that have const at the end, such as bob(param1, param2) const; - Matcher matcher = CONST_FUNCTION_PATTERN.matcher(parameterString); + Matcher matcher = UNNECESSARY_PARENS_PATTERN.matcher(parameterString); if (matcher.matches()) { - parameterString = matcher.group(1);// group 0 is the entire string - } - else { - matcher = UNNECESSARY_PARENS_PATTERN.matcher(parameterString); - if (matcher.matches()) { - parameterString = matcher.group(1); - } + parameterString = matcher.group(1); } - if (parameterString.trim().length() == 0) { + if (StringUtils.isBlank(parameterString)) { return parameters; } - int templateLevel = 0; - int functionPointerLevel = 0; + int depth = 0; int startIndex = 0; - for (int i = 0; i < parameterString.length(); ++i) { char ch = parameterString.charAt(i); - if (ch == ',' && templateLevel == 0 && functionPointerLevel == 0) { + if (ch == ',' && depth == 0) { String ps = parameterString.substring(startIndex, i); parameters.add(ps.trim()); startIndex = i + 1; } else if (ch == '<') { - ++templateLevel; + ++depth; } else if (ch == '>') { - --templateLevel; + --depth; } else if (ch == '(') { // @@ -711,7 +617,7 @@ public class GnuDemanglerParser { private int getFunctionPointerCloseParen(String parameterString, int currentIndex) { int firstCloseParen = parameterString.indexOf(')', currentIndex); if (firstCloseParen == -1) { - throw new RuntimeException( + throw new DemanglerParseException( "Unable to find closing paren for parameter string: " + parameterString); } @@ -757,10 +663,18 @@ public class GnuDemanglerParser { return parameters; } - private DemangledDataType parseDataType(String datatype) { - DemangledDataType ddt = new DemangledDataType((String) null); - setNameAndNamespace(ddt, datatype); + private DemangledDataType parseDataType(String fullDatatype) { + Matcher castMatcher = CAST_PATTERN.matcher(fullDatatype); + if (castMatcher.matches()) { + // special case: template parameter with a cast (just make the datatype + // be the name of the template parameter, since it will just be a display + // attribute for the templated type) + return new DemangledDataType(mangledSource, demangledSource, fullDatatype); + } + + DemangledDataType ddt = createTypeInNamespace(fullDatatype); + String datatype = ddt.getDemangledName(); boolean finishedName = false; for (int i = 0; i < datatype.length(); ++i) { char ch = datatype.charAt(i); @@ -776,26 +690,19 @@ public class GnuDemanglerParser { ddt.setVarArgs(); } else { - - Matcher matcher = CAST_PATTERN.matcher(datatype); - if (matcher.matches()) { - // special case: template parameter with a cast (just make the datatype - // be the name of the template parameter, since it will just be a display - // attribute for the templated type) - String value = matcher.group(0);// group 0 is the entire match - return new DemangledDataType(value); - } - String name = datatype.substring(0, i).trim(); - setNameAndNamespace(ddt, name); + ddt.setName(name); } } + if (ch == ' ') { + continue; + } if (ch == '<') {//start of template int contentStart = i + 1; - int templateEnd = getTemplateEndIndex(datatype, contentStart); + int templateEnd = findTemplateEnd(datatype, i); if (templateEnd == -1 || templateEnd > datatype.length()) { - throw new RuntimeException("Did not find ending to template"); + throw new DemanglerParseException("Did not find ending to template"); } String templateContent = datatype.substring(contentStart, templateEnd); @@ -812,39 +719,52 @@ public class GnuDemanglerParser { // // check for array case - Matcher matcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(datatype); - if (matcher.matches()) { - String name = matcher.group(1);// group 0 is the entire string - ddt = parseArrayPointerOrReference(datatype, name); - i = matcher.end(); + Matcher arrayMatcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(datatype); + if (arrayMatcher.matches()) { + Demangled namespace = ddt.getNamespace(); + String name = arrayMatcher.group(1);// group 0 is the entire string + ddt = parseArrayPointerOrReference(datatype, name, arrayMatcher); + ddt.setNamespace(namespace); + i = arrayMatcher.end(); } else { int startParenCount = StringUtilities.countOccurrences(datatype.substring(i), '('); boolean hasPointerParens = startParenCount == 2; if (hasPointerParens) { - ddt = parseFunctionPointer(datatype); + Demangled namespace = ddt.getNamespace(); + DemangledFunctionPointer dfp = parseFunctionPointer(datatype); int firstParenEnd = datatype.indexOf(')', i + 1); int secondParenEnd = datatype.indexOf(')', firstParenEnd + 1); if (secondParenEnd == -1) { - throw new RuntimeException( + throw new DemanglerParseException( "Did not find ending to closure: " + datatype); } + + dfp.getReturnType().setNamespace(namespace); + ddt = dfp; i = secondParenEnd + 1; // two sets of parens (normal case) } else { - ddt = parseFunction(datatype, i); + + // parse as a function pointer, but display as a function + Demangled namespace = ddt.getNamespace(); + DemangledFunctionPointer dfp = parseFunction(datatype, i); int firstParenEnd = datatype.indexOf(')', i + 1); if (firstParenEnd == -1) { - throw new RuntimeException( + throw new DemanglerParseException( "Did not find ending to closure: " + datatype); } + + dfp.getReturnType().setNamespace(namespace); + ddt = dfp; i = firstParenEnd + 1;// two sets of parens (normal case) } } } else if (ch == '*') { ddt.incrementPointerLevels(); + continue; } else if (ch == '&') { if (!ddt.isReference()) { @@ -853,9 +773,12 @@ public class GnuDemanglerParser { else { ddt.incrementPointerLevels(); } + continue; } - else if (ch == '[') {//TODO consume closing ']' + else if (ch == '[') { ddt.setArray(ddt.getArrayDimensions() + 1); + i = datatype.indexOf(']', i + 1); + continue; } String substr = datatype.substring(i); @@ -930,47 +853,84 @@ public class GnuDemanglerParser { //@formatter:on } - // scan to last part of template - private int getTemplateEndIndex(String datatype, int start) { - int endIndex = start; - int depth = 1; - while (endIndex < datatype.length()) { - char tempCh = datatype.charAt(endIndex); - if (tempCh == '>') { - depth--; - if (depth == 0) { + /** + * Scans the given string from the given offset looking for a template and reporting the + * index of the closing template character '>' or -1 if no templates are found + * + * @param string the input string + * @param start the start position within the string + * @return the template end index; -1 if no templates found + */ + private int findTemplateEnd(String string, int start) { + + boolean found = false; + int depth = 0; + for (int i = start; i < string.length(); i++) { + switch (string.charAt(i)) { + case '<': + depth++; + found = true; + break; + case '>': + depth--; break; - } } - if (tempCh == '<') { - depth++; + + if (found && depth == 0) { + return i; } - endIndex++; } - return endIndex; + + return -1; } - private void setNameAndNamespace(DemangledDataType ddt, String name) { - List names = NamespaceUtils.splitNamespacePath(name); + // assumption: the given index is in a template + // Walk backwards to find the template start + private int findMatchingTemplateStart(String string, int templateEnd) { + + int depth = 1; + for (int i = templateEnd - 1; i >= 0; i--) { + switch (string.charAt(i)) { + case '<': + depth--; + break; + case '>': + depth++; + break; + } + + if (depth == 0) { + return i;// found our opening tag + } + } + + return -1; + } + + private DemangledDataType createTypeInNamespace(String name) { + SymbolPath path = new SymbolPath(name); + List names = path.asList(); DemangledType namespace = null; if (names.size() > 1) { - namespace = DemanglerUtil.convertToNamespaces(names.subList(0, names.size() - 1)); + namespace = convertToNamespaces(names.subList(0, names.size() - 1)); } String datatypeName = names.get(names.size() - 1); - + DemangledDataType ddt = new DemangledDataType(mangledSource, demangledSource, datatypeName); ddt.setName(datatypeName); ddt.setNamespace(namespace); + return ddt; } private void setNameAndNamespace(DemangledObject object, String name) { - List names = NamespaceUtils.splitNamespacePath(name); + SymbolPath path = new SymbolPath(name); + List names = path.asList(); DemangledType namespace = null; if (names.size() > 1) { - namespace = DemanglerUtil.convertToNamespaces(names.subList(0, names.size() - 1)); + namespace = convertToNamespaces(names.subList(0, names.size() - 1)); } String objectName = names.get(names.size() - 1); @@ -981,12 +941,19 @@ public class GnuDemanglerParser { private void setNamespace(DemangledObject object, String name) { - List names = NamespaceUtils.splitNamespacePath(name); - object.setNamespace(DemanglerUtil.convertToNamespaces(names)); + SymbolPath path = new SymbolPath(name); + List names = path.asList(); + object.setNamespace(convertToNamespaces(names)); } - private DemangledTemplate parseTemplate(String templateStr) { - List parameters = parseParameters(templateStr); + private DemangledTemplate parseTemplate(String string) { + + String contents = string; + if (string.startsWith("<") && string.endsWith(">")) { + contents = string.substring(1, string.length() - 1); + } + + List parameters = parseParameters(contents); DemangledTemplate template = new DemangledTemplate(); for (DemangledDataType parameter : parameters) { template.addParameter(parameter); @@ -994,14 +961,13 @@ public class GnuDemanglerParser { return template; } - private DemangledDataType parseArrayPointerOrReference(String datatype, String name) { + private DemangledDataType parseArrayPointerOrReference(String datatype, String name, + Matcher matcher) { // int (*)[8] // char (&)[7] - DemangledDataType ddt = new DemangledDataType(name); - Matcher matcher = ARRAY_POINTER_REFERENCE_PATTERN.matcher(datatype); - matcher.find(); - String type = matcher.group(3); + DemangledDataType ddt = new DemangledDataType(mangledSource, demangledSource, name); + String type = matcher.group(2); if (type.equals("*")) { ddt.incrementPointerLevels(); } @@ -1009,39 +975,31 @@ public class GnuDemanglerParser { ddt.setReference(); } else { - throw new RuntimeException("Unexpected charater inside of parens: " + type); + throw new DemanglerParseException("Unexpected charater inside of parens: " + type); } - String arraySubscripts = matcher.group(4); + String arraySubscripts = matcher.group(3); int n = StringUtilities.countOccurrences(arraySubscripts, '['); ddt.setArray(n); return ddt; } - private DemangledDataType parseFunctionPointer(String functionPointerString) { + private DemangledFunctionPointer parseFunctionPointer(String functionString) { //unsigned long (*)(long const &) - int parenStart = functionPointerString.indexOf('('); - int parenEnd = functionPointerString.indexOf(')'); + int parenStart = functionString.indexOf('('); + int parenEnd = functionString.indexOf(')'); - String returnType = functionPointerString.substring(0, parenStart).trim(); + String returnType = functionString.substring(0, parenStart).trim(); - int paramStart = functionPointerString.indexOf('(', parenEnd + 1); - int paramEnd = functionPointerString.lastIndexOf(')'); - String parameterStr = functionPointerString.substring(paramStart + 1, paramEnd); - List parameters = parseParameters(parameterStr); - - DemangledFunctionPointer dfp = new DemangledFunctionPointer(); - dfp.setReturnType(parseDataType(returnType)); - for (DemangledDataType parameter : parameters) { - dfp.addParameter(parameter); - } - - return dfp; + int paramStart = functionString.indexOf('(', parenEnd + 1); + int paramEnd = functionString.lastIndexOf(')'); + String parameters = functionString.substring(paramStart + 1, paramEnd); + return createFunctionPointer(parameters, returnType); } - private DemangledDataType parseFunction(String functionString, int offset) { + private DemangledFunctionPointer parseFunction(String functionString, int offset) { //unsigned long (long const &) int parenStart = functionString.indexOf('(', offset); @@ -1051,108 +1009,460 @@ public class GnuDemanglerParser { int paramStart = parenStart; int paramEnd = parenEnd; - String parameterStr = functionString.substring(paramStart + 1, paramEnd); - List parameters = parseParameters(parameterStr); - - DemangledFunctionPointer dfp = new DemangledFunctionPointer(); - dfp.setReturnType(parseDataType(returnType)); - for (DemangledDataType parameter : parameters) { - dfp.addParameter(parameter); - } - + String parameters = functionString.substring(paramStart + 1, paramEnd); + DemangledFunctionPointer dfp = createFunctionPointer(parameters, returnType); dfp.setDisplayFunctionPointerParens(false); return dfp; } + private DemangledFunctionPointer createFunctionPointer(String paramerterString, + String returnType) { + + List parameters = parseParameters(paramerterString); + + DemangledFunctionPointer dfp = new DemangledFunctionPointer(mangledSource, demangledSource); + dfp.setReturnType(parseDataType(returnType)); + for (DemangledDataType parameter : parameters) { + dfp.addParameter(parameter); + } + return dfp; + } + private DemangledObject parseVariable(String demangled) { - // Are all of these necessary? Many appear to be duplicated within doParse method - if (demangled.startsWith(TYPEINFO_NAME_FOR)) { - return parseTypeInfoName(demangled); - } - if (demangled.startsWith(TYPEINFO_FOR)) { - return parseAddressTable(demangled, TYPEINFO_FOR); - } - if (demangled.startsWith(TYPEINFO_FN_FOR)) { - return parseAddressTable(demangled, TYPEINFO_FN_FOR); - } - if (demangled.startsWith(VTABLE_FOR)) { - return parseAddressTable(demangled, VTABLE_FOR); - } - if (demangled.startsWith(VTT_FOR)) { - return parseAddressTable(demangled, VTT_FOR); - } - if (demangled.startsWith(CONSTRUCTION_VTABLE_FOR)) { - //ends with a number, strip it off - int pos = backIndexOf(demangled, demangled.length() - 1, ' '); - String str = demangled.substring(0, pos).trim(); - return parseAddressTable(str, CONSTRUCTION_VTABLE_FOR); - } -// TODO: I don't believe the various thunk forms should ever be seen for a parameter type -// if (demangled.startsWith(COVARIANT_RETURN_THUNK) || -// demangled.startsWith(NONVIRTUAL_THUNK) || -// demangled.startsWith(VIRTUAL_THUNK)) { -// int pos = demangled.indexOf(" to "); -// return ??? -// } + /* + Examples: + + NS1::Function<>()::StructureName::StructureConstructor() + + */ - demangled = fixupTemplateSeparators(demangled).trim(); - - int nameStartPos = backIndexOf(demangled, demangled.length() - 1, ' '); - if (nameStartPos == -1) { - throw new RuntimeException(); - } - String name = demangled.substring(nameStartPos, demangled.length()); - DemangledVariable variable = new DemangledVariable((String) null); - setNameAndNamespace(variable, name); + String nameString = fixupInternalSeparators(demangled).trim(); + DemangledVariable variable = + new DemangledVariable(mangledSource, demangledSource, (String) null); + setNameAndNamespace(variable, nameString); return variable; } - private DemangledObject parseAddressTable(String demangled, String prefix) { - int pos = prefix.trim().lastIndexOf(' '); - String name = prefix.substring(0, pos).replace(' ', '-'); - - String str; - if (prefix.length() >= demangled.length()) { // demangled may be shorter than prefix due to trimming - str = demangled.trim(); - } - else { - str = demangled.substring(prefix.length()).trim(); - } - DemangledObject parent = parse(null, str); - if (parent == null) { + /** + * Converts the list of names into a namespace demangled type. + * Given names = { "A", "B", "C" }, which represents "A::B::C". + * The following will be created {@literal "Namespace{A}->Namespace{B}->Namespace{C}"} + * and Namespace{C} will be returned. + * + *

This method will also escape spaces and namespace separators inside of templates + * (see {@link #fixupInternalSeparators(String)}). + * + * @param names the names to convert + * @return the newly created type + */ + private DemangledType convertToNamespaces(List names) { + if (names.size() == 0) { return null; } - DemangledType namespace = new DemangledType(parent.getName()); - namespace.setNamespace(parent.getNamespace()); + int index = names.size() - 1; + String rawName = names.get(index); + String escapedName = fixupInternalSeparators(rawName); + DemangledType myNamespace = new DemangledType(mangledSource, demangledSource, escapedName); - DemangledAddressTable addressTable = new DemangledAddressTable(name, -1); - addressTable.setNamespace(namespace); - return addressTable; + DemangledType namespace = myNamespace; + while (--index >= 0) { + rawName = names.get(index); + escapedName = fixupInternalSeparators(rawName); + DemangledType parentNamespace = + new DemangledType(mangledSource, demangledSource, escapedName); + namespace.setNamespace(parentNamespace); + namespace = parentNamespace; + } + return myNamespace; } //================================================================================================== // Inner Classes //================================================================================================== + + private abstract class DemangledObjectBuilder { + + protected String demangled; + + DemangledObjectBuilder(String demangled) { + this.demangled = demangled; + } + + abstract DemangledObject build(); + } + + private abstract class OperatorHandler extends DemangledObjectBuilder { + + protected Matcher matcher; + + OperatorHandler(String demangled) { + super(demangled); + } + + abstract boolean matches(String s); + + } + + private abstract class SpecialPrefixHandler extends DemangledObjectBuilder { + + protected String prefix; + protected String name; + protected String type; + + SpecialPrefixHandler(String demangled) { + super(demangled); + } + + @Override + DemangledObject build() { + + DemangledObject dobj = parseFunctionOrVariable(type); + + return doBuild(dobj); + } + + abstract DemangledObject doBuild(Demangled namespace); + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE); + return builder + .append("name", name) + .append("prefix", prefix) + .append("type", type) + .append("demangled", demangled) + .toString(); + } + } + + private class ItemInNamespaceHandler extends SpecialPrefixHandler { + + ItemInNamespaceHandler(String demangled) { + super(demangled); + this.demangled = demangled; + this.type = demangled; + } + + ItemInNamespaceHandler(String demangled, String prefix, String item) { + super(demangled); + this.demangled = demangled; + this.prefix = prefix; + this.type = item; + } + + @Override + DemangledObject doBuild(Demangled namespace) { + DemangledObject demangledObject = parseItemInNamespace(type); + return demangledObject; + } + } + + private class ThunkHandler extends SpecialPrefixHandler { + + ThunkHandler(String demangled, String prefix, String item) { + super(demangled); + this.demangled = demangled; + this.prefix = prefix; + this.type = item; + } + + @Override + DemangledObject doBuild(Demangled demangledObject) { + + DemangledFunction function = (DemangledFunction) demangledObject; + function.setSignature(type); + function.setCallingConvention(CompilerSpec.CALLING_CONVENTION_thiscall); + + DemangledThunk thunk = new DemangledThunk(mangledSource, demangledSource, function); + if (prefix.contains(COVARIANT_RETURN_THUNK)) { + thunk.setCovariantReturnThunk(); + } + + thunk.setSignaturePrefix(prefix); + return thunk; + } + } + + private class TypeInfoNameHandler extends SpecialPrefixHandler { + + TypeInfoNameHandler(String demangled, String prefix) { + super(demangled); + this.demangled = demangled; + this.prefix = prefix; + + String classname = demangled.substring(prefix.length()).trim(); + this.type = classname; + } + + @Override + DemangledObject doBuild(Demangled namespace) { + DemangledString demangledString = + new DemangledString(mangledSource, demangledSource, "typeinfo-name", type, + -1/*unknown length*/, false); + demangledString.setSpecialPrefix("typeinfo name for "); + String namespaceString = fixupInternalSeparators(type); + setNamespace(demangledString, namespaceString); + return demangledString; + } + } + + private class AddressTableHandler extends SpecialPrefixHandler { + + AddressTableHandler(String demangled, String prefix, String type) { + super(demangled); + this.demangled = demangled; + this.prefix = prefix; + this.type = type; + + Matcher matcher = ENDS_WITH_DIGITS_PATTERN.matcher(demangled); + if (matcher.matches()) { + // ends with a number, strip it off + int oldLength = demangled.length(); + this.demangled = matcher.group(1); + int delta = oldLength - this.demangled.length(); + this.type = type.substring(0, type.length() - delta); + } + + /* + Samples: + prefix: construction vtable for + name: construction-vtable + + prefix: vtable for + name: vtable + + prefix: typeinfo name for + name: typeinfo-name + + prefix: covariant return thunk + name: covariant-return + */ + int pos = prefix.trim().lastIndexOf(' '); + name = prefix.substring(0, pos).replace(' ', '-'); + } + + @Override + DemangledObject doBuild(Demangled namespace) { + DemangledAddressTable addressTable = + new DemangledAddressTable(mangledSource, demangled, name, true); + addressTable.setNamespace(namespace); + return addressTable; + } + } + + private class OverloadOperatorHandler extends OperatorHandler { + + OverloadOperatorHandler(String demangled) { + super(demangled); + } + + @Override + boolean matches(String text) { + matcher = OVERLOAD_OPERATOR_PATTERN.matcher(text); + return matcher.matches(); + } + + @Override + DemangledObject build() { + + // + // An example to follow along with: + // + // 'overloaded operator' syntax is: + // [return_type] operator[templates](parameters) + // + // Namespace::Class::operator Namespace::Type() + // + // NS1::operator<(NS1::Coordinate const &,NS1::Coordinate const &) + // + + // prefix: return_type operator operator_chars[templates] + // (everything before the parameters) + String returnTypeText = matcher.group(1); + String operatorPrefix = matcher.group(2); + //String operatorChars = matcher.group(3); + String templates = matcher.group(4); + String parametersText = matcher.group(5); + //String trailing = matcher.group(6); + + String operatorName = operatorPrefix; + + operatorPrefix = fixupInternalSeparators(operatorPrefix); + + if (returnTypeText == null) { + returnTypeText = "undefined"; + } + returnTypeText = fixupInternalSeparators(returnTypeText); + DemangledDataType returnType = createTypeInNamespace(returnTypeText); + + DemangledFunction function = + new DemangledFunction(mangledSource, demangledSource, (String) null); + function.setOverloadedOperator(true); + function.setReturnType(returnType); + + if (!StringUtils.isBlank(templates)) { + int templateIndex = operatorName.lastIndexOf(templates); + operatorName = operatorName.substring(0, templateIndex); + DemangledTemplate demangledTemplate = parseTemplate(templates); + function.setTemplate(demangledTemplate); + } + + operatorName = fixupInternalSeparators(operatorName); + setNameAndNamespace(function, operatorName); + + List parameters = parseParameters(parametersText); + for (DemangledDataType parameter : parameters) { + function.addParameter(parameter); + } + + return function; + } + } + + private class ConversionOperatorHandler extends OperatorHandler { + + ConversionOperatorHandler(String demangled) { + super(demangled); + } + + @Override + boolean matches(String text) { + matcher = CONVERSION_OPERATOR_PATTERN.matcher(text); + return matcher.matches(); + } + + @Override + DemangledObject build() { + + // this will yield: + // fullName: NS1::Foo::operator + // fullReturnType: std::string + String fullName = matcher.group(1);// group 0 is the entire match string + String fullReturnType = matcher.group(2); + + boolean isConst = false; + int index = fullReturnType.indexOf(CONST); + if (index != -1) { + fullReturnType = fullReturnType.replace(CONST, ""); + isConst = true; + } + + DemangledFunction method = + new DemangledFunction(mangledSource, demangledSource, (String) null); + DemangledDataType returnType = parseDataType(fullReturnType); + if (isConst) { + returnType.setConst(); + } + method.setReturnType(returnType); + + // 'conversion operator' syntax is 'operator ()' + // assume fullName endsWith '::operator' + int operatorIndex = fullName.lastIndexOf("::operator"); + String namespace = fullName.substring(0, operatorIndex); + + String templatelessNamespace = stripOffTemplates(namespace); + setNamespace(method, templatelessNamespace); + + // shortReturnType: string + String templatelessReturnType = stripOffTemplates(fullReturnType); + SymbolPath path = new SymbolPath(templatelessReturnType); + String shortReturnTypeName = path.getName(); + + // + // The preferred name: 'operator basic_string()' + // + // Ghidra does not allow spaces in the name or extra parens. So, make a name that is + // as clear as possible in describing the construct. + // + method.setName("operator.cast.to." + shortReturnTypeName); + + method.setSignature(fullName + " " + fullReturnType); + method.setOverloadedOperator(true); + + return method; + } + } + + private class NewOrDeleteOperatorHandler extends OperatorHandler { + + NewOrDeleteOperatorHandler(String demangled) { + super(demangled); + } + + @Override + boolean matches(String demangler) { + matcher = NEW_DELETE_OPERATOR_PATTERN.matcher(demangler); + return matcher.matches(); + } + + @Override + DemangledObject build() { + + String operatorText = matcher.group(1);// group 0 is the entire match string + String operatorName = matcher.group(2); + String arrayBrackets = matcher.group(3); + String parametersText = matcher.group(4); + + DemangledFunction function = + new DemangledFunction(mangledSource, demangledSource, (String) null); + function.setOverloadedOperator(true); + DemangledDataType returnType = + new DemangledDataType(mangledSource, demangledSource, "void"); + if (operatorName.startsWith("new")) { + returnType.incrementPointerLevels(); + } + + function.setReturnType(returnType); + + // 'new operator' syntax is 'operator ()', where the + // operator itself could be in a class namespace + setNameAndNamespace(function, operatorText); + + List parameters = parseParameters(parametersText); + for (DemangledDataType parameter : parameters) { + function.addParameter(parameter); + } + + // + // The preferred name: 'operator new()' + // + // Ghidra does not allow spaces in the name or extra parens. So, make a name that is + // as clear as possible in describing the construct. + // + String name = operatorName; + if (arrayBrackets != null) { + name += "[]"; + } + function.setName("operator." + name); + + function.setSignature(operatorText + " " + operatorName); + + return function; + } + } + private class ParameterLocator { int paramStart = -1; int paramEnd = -1; + private String text; ParameterLocator(String text) { + this.text = text; paramEnd = text.lastIndexOf(')'); if (paramEnd < 0) { return; } - if (isContainedWithinNamespace(text)) { + if (isContainedWithinNamespace()) { // ignore param list associated with namespace specification paramEnd = -1; return; } paramStart = findParameterStart(text, paramEnd); - int templateEnd = findInitialTemplateEndPosition(text); + int templateEnd = findTemplateEnd(text, 0); int templateStart = -1; if (templateEnd != -1) { - templateStart = findInitialTemplateStartPosition(text, templateEnd); + templateStart = findMatchingTemplateStart(text, templateEnd); } if (paramStart > templateStart && paramStart < templateEnd) { // ignore parentheses inside of templates (they are cast operators) @@ -1161,7 +1471,17 @@ public class GnuDemanglerParser { } } - private boolean isContainedWithinNamespace(String text) { + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE); + return builder + .append("text", text) + .append("paramStart", paramStart) + .append("paramEnd", paramEnd) + .toString(); + } + + private boolean isContainedWithinNamespace() { return (paramEnd < (text.length() - 1)) && (':' == text.charAt(paramEnd + 1)); } @@ -1177,74 +1497,50 @@ public class GnuDemanglerParser { return paramStart != -1 && paramEnd != -1; } + // walks backwards to find the start of the parameter list private int findParameterStart(String demangled, int end) { - int templateLevel = 0; - int functionPointerLevel = 0; + + int depth = 0; for (int i = end - 1; i >= 0; --i) { char ch = demangled.charAt(i); - if (ch == '(' && templateLevel == 0 && functionPointerLevel == 0) { + if (ch == '(' && depth == 0) { return i; } - else if (ch == '>') { - ++templateLevel; + else if (ch == '>' || ch == ')') { + ++depth; } - else if (ch == '<') { - --templateLevel; - } - else if (ch == ')') { - ++functionPointerLevel; - } - else if (ch == '(') { - --functionPointerLevel; + else if (ch == '<' || ch == '(') { + depth--; } } return -1; } - - private int findInitialTemplateEndPosition(String string) { - - boolean seenTemplate = false; - int templateLevel = 0; - char[] chars = string.toCharArray(); - for (int i = 0; i < chars.length; i++) { - switch (chars[i]) { - case '<': - templateLevel++; - seenTemplate = true; - break; - case '>': - templateLevel--; - break; - } - - if (seenTemplate && templateLevel == 0) { - return i; - } - } - - return -1; - } - - private int findInitialTemplateStartPosition(String string, int templateEnd) { - // note: we are moving backwards! - int templateLevel = 1; - char[] chars = string.toCharArray(); - for (int i = templateEnd - 1; i >= 0; i--) { - switch (chars[i]) { - case '<': - templateLevel--; - break; - case '>': - templateLevel++; - break; - } - - if (templateLevel == 0) { - return i;// found our opening tag - } - } - - return -1; - } + } + + private class LambdaName { + + private String fullText; + private String params; + private String trailing; + + LambdaName(String fullText, String params, String trailing) { + this.fullText = fullText; + this.params = params; + this.trailing = trailing; + } + + String getFullText() { + return fullText; + } + + @Override + public String toString() { + ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.JSON_STYLE); + return builder + .append("fullText", fullText) + .append("params", params) + .append("trailing", trailing) + .toString(); + } } } diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParser2Test.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParser2Test.java new file mode 100644 index 0000000000..b0f15a6a73 --- /dev/null +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParser2Test.java @@ -0,0 +1,621 @@ +/* ### + * 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; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import generic.test.AbstractGenericTest; +import ghidra.app.util.demangler.gnu.GnuDemanglerParser; + +public class GnuDemanglerParser2Test extends AbstractGenericTest { + + private GnuDemanglerParser parser = new GnuDemanglerParser(); + + //@Test + public void test1() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeC1Eii", "OpTestType::OpTestType(int, int)"); + String name = object.getName(); + assertEquals("", name); + } + + //@Test + public void test2() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeC2Eii", "OpTestType::OpTestType(int, int)"); + String name = object.getName(); + assertEquals("", name); + } + + @Test + public void test3() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeclEf", "OpTestType::operator()(float)"); + String name = object.getName(); + assertEquals("operator()", name); + } + + @Test + public void test4() { + + DemangledObject object = parser.parse("_ZN10OpTestTypeclEi", "OpTestType::operator()(int)"); + String name = object.getName(); + assertEquals("operator()", name); + } + + //@Test + public void test5() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypecvN16Names", "_ZN10OpTestTypecvN16Names"); + String name = object.getName(); + assertEquals("", name); + } + + @Test + public void test6() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypecvPKcEv", "OpTestType::operator char const*()"); + String name = object.getName(); + assertEquals("operator.cast.to.char*", name); + } + + @Test + public void test7() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypedaEPv", "OpTestType::operator delete[](void*)"); + String name = object.getName(); + assertEquals("operator.delete[]", name); + } + + @Test + public void test8() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypedlEPv", "OpTestType::operator delete(void*)"); + String name = object.getName(); + assertEquals("operator.delete", name); + } + + @Test + public void test9() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypemIERKS_", "OpTestType::operator-=(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator-=", name); + } + + @Test + public void test10() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypemiERKS_", "OpTestType::operator-(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator-", name); + } + + @Test + public void test11() { + + DemangledObject object = parser.parse("_ZN10OpTestTypemmEi", "OpTestType::operator--(int)"); + String name = object.getName(); + assertEquals("operator--", name); + } + + @Test + public void test12() { + + DemangledObject object = parser.parse("_ZN10OpTestTypemmEv", "OpTestType::operator--()"); + String name = object.getName(); + assertEquals("operator--", name); + } + + @Test + public void test13() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypenaEm", "OpTestType::operator new[](unsigned long)"); + String name = object.getName(); + assertEquals("operator.new[]", name); + } + + @Test + public void test14() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypenwEm", "OpTestType::operator new(unsigned long)"); + String name = object.getName(); + assertEquals("operator.new", name); + } + + @Test + public void test15() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypepLERKS_", "OpTestType::operator+=(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator+=", name); + } + + @Test + public void test16() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeplERKS_", "OpTestType::operator+(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator+", name); + } + + @Test + public void test17() { + + DemangledObject object = parser.parse("_ZN10OpTestTypeppEi", "OpTestType::operator++(int)"); + String name = object.getName(); + assertEquals("operator++", name); + } + + @Test + public void test18() { + + DemangledObject object = parser.parse("_ZN10OpTestTypeppEv", "OpTestType::operator++()"); + String name = object.getName(); + assertEquals("operator++", name); + } + +//-------------------- +//TODO: for the following, determine what arguments are needed. + + @Test + public void testOperatorNew() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypenwEm", "OpTestType::operator new(unsigned long)"); + String name = object.getName(); + assertEquals("operator.new", name); + } + + @Test + public void testOperatorDelete() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypedlEPv", "OpTestType::operator delete(void*)"); + String name = object.getName(); + assertEquals("operator.delete", name); + } + + @Test + public void testOperatorAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator=()"); + String name = object.getName(); + assertEquals("operator=", name); + } + + @Test + public void testOperatorRightShift() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator>>()"); + String name = object.getName(); + assertEquals("operator>>", name); + } + + @Test + public void testOperatorLeftShift() { + + DemangledObject object = + parser.parse("_ZN11myContainerIiElsEi", "myContainer::operator<<(int)"); + String name = object.getName(); + assertEquals("operator<<", name); + } + + @Test + public void testOperatorLeftShiftTemplated() { + + DemangledObject object = parser.parse("_ZN11myContainerIiElsIdEEbT_", + "bool myContainer::operator<< (double)"); + String name = object.getName(); + assertEquals("operator<<", name); + assertEquals("bool myContainer::operator<<(double)", + object.getSignature()); + } + + @Test + public void testOperatorLogicalNot() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator!()"); + String name = object.getName(); + assertEquals("operator!", name); + } + + @Test + public void testOperatorEquality() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator==()"); + String name = object.getName(); + assertEquals("operator==", name); + } + + @Test + public void testOperatorInequality() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator!=()"); + String name = object.getName(); + assertEquals("operator!=", name); + } + + @Test + public void testOperatorArraySubscript() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator[]()"); + String name = object.getName(); + assertEquals("operator[]", name); + } + + @Test + public void testOperatorTypeCast() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypecvPKcEv", "OpTestType::operator char const*()"); + String name = object.getName(); + assertEquals("operator.cast.to.char*", name); + } + + @Test + public void testOperatorTypeCast_WithNamespace() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypecvN16NamespaceOpTest116NamespaceOpTest210CastToTypeEEv", + "OpTestType::operator NamespaceOpTest1::NamespaceOpTest2::CastToType()"); + assertName(object, "operator.cast.to.CastToType", "OpTestType"); + assertEquals( + "NamespaceOpTest1::NamespaceOpTest2::CastToType OpTestType::operator.cast.to.CastToType(void)", + object.getSignature()); + } + + @Test + public void testOperatorPointerDereference() { + DemangledObject object = parser.parse("fake", "OpTestType::operator->()"); + String name = object.getName(); + assertEquals("operator->", name); + } + + @Test + public void testOperatorMultiplication() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator*()"); + String name = object.getName(); + assertEquals("operator*", name); + } + + //TODO: If laying down function signatures, then we need to investigate whether we can + // determine prefix vs. postfix increment. Postfix will have an argument and prefix will not. + // Same for prefix vs. postfix decrement. + @Test + public void testOperatorPrefixIncrement() { + + DemangledObject object = parser.parse("_ZN10OpTestTypeppEv", "OpTestType::operator++()"); + String name = object.getName(); + assertEquals("operator++", name); + } + + @Test + public void testOperatorPostfixIncrement() { + + DemangledObject object = parser.parse("_ZN10OpTestTypeppEi", "OpTestType::operator++(int)"); + String name = object.getName(); + assertEquals("operator++", name); + } + + @Test + public void testOperatorPrefixDecrement() { + + DemangledObject object = parser.parse("_ZN10OpTestTypemmEv", "OpTestType::operator--()"); + String name = object.getName(); + assertEquals("operator--", name); + } + + @Test + public void testOperatorPostfixDecrement() { + + DemangledObject object = parser.parse("_ZN10OpTestTypemmEi", "OpTestType::operator--(int)"); + String name = object.getName(); + assertEquals("operator--", name); + } + + @Test + public void testOperatorSubtraction() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypemiERKS_", "OpTestType::operator-(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator-", name); + } + + @Test + public void testOperatorAddition() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeplERKS_", "OpTestType::operator+(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator+", name); + } + + @Test + public void testOperatorAddressOf() { + + DemangledObject object = parser.parse("_ZN10SmallClassadEv", "SmallClass::operator&()"); + String name = object.getName(); + assertEquals("operator&", name); + } + + @Test + public void testOperatorPointerToMemberSelection() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator->*()"); + String name = object.getName(); + assertEquals("operator->*", name); + } + + @Test + public void testOperatorDivision() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator/()"); + String name = object.getName(); + assertEquals("operator/", name); + } + + @Test + public void testOperatorModulus() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator%()"); + String name = object.getName(); + assertEquals("operator%", name); + } + + @Test + public void testOperatorLessThan() { + + DemangledObject object = + parser.parse("_ZN11myContainerIiEltEi", "myContainer::operator<(int)"); + String name = object.getName(); + assertEquals("operator<", name); + } + + @Test + public void testOperatorLessThanTemplated() { + + DemangledObject object = parser.parse("_ZltI11myContainerIiEEbRKT_S4_", + "bool operator< >(myContainer const&, myContainer const&)"); + String name = object.getName(); + assertEquals("operator<", name); + assertEquals( + "bool operator<>(myContainer const &,myContainer const &)", + object.getSignature()); + } + + @Test + public void testOperatorLessThanOrEqualTo() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator<=()"); + String name = object.getName(); + assertEquals("operator<=", name); + } + + @Test + public void testOperatorGreaterThan() { + + DemangledObject object = parser.parse("_ZgtRK10complex_ldS1_", + "operator>(complex_ld const&, complex_ld const&)"); + String name = object.getName(); + assertEquals("operator>", name); + } + + @Test + public void testOperatorGreaterThanOrEqualTo() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator>=()"); + String name = object.getName(); + assertEquals("operator>=", name); + } + + @Test + public void testOperatorComma() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator,()"); + String name = object.getName(); + assertEquals("operator,", name); + } + + @Test + public void testOperatorFunctionCall() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypeclEf", "OpTestType::operator()(float)"); + String name = object.getName(); + assertEquals("operator()", name); + } + + @Test + public void testOperatorOnesComplement() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator~()"); + String name = object.getName(); + assertEquals("operator~", name); + } + + @Test + public void testOperatorExclusiveOr() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator^()"); + String name = object.getName(); + assertEquals("operator^", name); + } + + @Test + public void testOperatorBitwiseInclusiveOr() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator|()"); + String name = object.getName(); + assertEquals("operator|", name); + } + + @Test + public void testOperatorLogicalAnd() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator&&()"); + String name = object.getName(); + assertEquals("operator&&", name); + } + + @Test + public void testOperatorLogicalOr() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator||()"); + String name = object.getName(); + assertEquals("operator||", name); + } + + @Test + public void testOperatorMultiplicationAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator*=()"); + String name = object.getName(); + assertEquals("operator*=", name); + } + + @Test + public void testOperatorAdditionAssignment() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypepLERKS_", "OpTestType::operator+=(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator+=", name); + } + + @Test + public void testOperatorSubtractionAssignment() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypemIERKS_", "OpTestType::operator-=(OpTestType const&)"); + String name = object.getName(); + assertEquals("operator-=", name); + } + + @Test + public void testOperatorDivisionAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator/=()"); + String name = object.getName(); + assertEquals("operator/=", name); + } + + @Test + public void testOperatorModulusAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator%=()"); + String name = object.getName(); + assertEquals("operator%=", name); + } + + @Test + public void testOperatorRightShiftAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator>>=()"); + String name = object.getName(); + assertEquals("operator>>=", name); + } + + @Test + public void testOperatorLeftShiftAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator<<=()"); + String name = object.getName(); + assertEquals("operator<<=", name); + } + + @Test + public void testOperatorBitwiseAndAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator&=()"); + String name = object.getName(); + assertEquals("operator&=", name); + } + + @Test + public void testOperatorBitwiseOrAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator|=()"); + String name = object.getName(); + assertEquals("operator|=", name); + } + + @Test + public void testOperatorExclusiveOrAssignment() { + + DemangledObject object = parser.parse("fake", "OpTestType::operator^=()"); + String name = object.getName(); + assertEquals("operator^=", name); + } + + @Test + public void testOperatorNewArray() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypenaEm", "OpTestType::operator new[](unsigned long)"); + String name = object.getName(); + assertEquals("operator.new[]", name); + } + + @Test + public void testOperatorDeleteArray() { + + DemangledObject object = + parser.parse("_ZN10OpTestTypedaEPv", "OpTestType::operator delete[](void*)"); + String name = object.getName(); + assertEquals("operator.delete[]", name); + } + + @Test + public void testOperatorUserDefinedLiteral() { + + DemangledObject object = + parser.parse("_Zli5_initPKcm", "operator\"\" _init(char const*, unsigned long)"); + String name = object.getName(); + assertEquals("operator\"\"__init", name); + } + + private void assertName(DemangledObject demangledObj, String name, String... namespaces) { + + assertEquals("Unexpected demangled name", name, demangledObj.getName()); + Demangled namespace = demangledObj.getNamespace(); + for (int i = namespaces.length - 1; i >= 0; i--) { + String expectedName = namespaces[i]; + assertNotNull("Namespace mismatch", namespace); + String actualName = namespace.getNamespaceName(); + assertEquals(expectedName, actualName); + namespace = namespace.getNamespace(); + } + assertNull("Namespace mismatch", namespace); + } +} diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java index 27905e7adf..1434c17590 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/GnuDemanglerParserTest.java @@ -17,7 +17,6 @@ package ghidra.app.util.demangler; import static org.junit.Assert.*; -import java.io.IOException; import java.util.List; import org.junit.Before; @@ -35,159 +34,67 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { public void setUp() throws Exception { process = GnuDemanglerNativeProcess .getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_33_1); - parser = new GnuDemanglerParser(process); + parser = new GnuDemanglerParser(); } @Test - public void test() throws Exception { - long start = System.currentTimeMillis(); + public void testParse_ArrayPointerReferencePattern_ConstArray() throws Exception { - demangle("_ZTVN6Magick21DrawableTextAntialiasE"); - demangle("_ZGVZN10KDirLister11emitChangesEvE3dot");//guard variables + // bob(int const[8] (*) [12]) - demangle("_ZZ18__gthread_active_pvE20__gthread_active_ptr"); + String demangled = + "bob(int const[8] (*) [12])"; + DemangledObject object = parser.parse("fake", demangled); + assertType(object, DemangledFunction.class); + assertName(object, "bob"); - demangle("_ZNSt10_List_baseIN6Magick5VPathESaIS1_EE5clearEv"); - demangle("_ZTISt14unary_functionIPN9MagickLib12_DrawContextEvE"); - demangle("_ZTSSt14unary_functionIPN9MagickLib12_DrawContextEvE"); - demangle("_ZTCN4Arts17StdoutWriter_implE68_NS_11Object_skelE"); - demangle("_ZN6Magick5ImageD1Ev"); - demangle( - "_ZN6Magick19matteFloodfillImageC2ERKNS_5ColorEjiiN9MagickLib11PaintMethodE"); - demangle("_ZThn8_N14nsPrintSession6AddRefEv");// non-virtual thunk - demangle( - "_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev");// virtual thunk - demangle("_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE");// covariant return thunk - - demangle("_ZNK2cc14ScrollSnapTypeneERKS0_"); - - List list = loadTextResource(GnuDemanglerParserTest.class, "libMagick.symbols.txt"); - for (String mangled : list) { - if (mangled == null) { - break; - } - demangle(mangled); - } - - System.out.println("Elapsed Time: " + (System.currentTimeMillis() - start)); - } - - private void demangle(String mangled) throws IOException { - String demangled = process.demangle(mangled); - assertNotNull(demangled); - assertNotEquals(mangled, demangled); - //System.out.println(parser.parse(mangled, demangled)); - assertNotNull(parser.parse(mangled, demangled)); + DemangledFunction function = (DemangledFunction) object; + List parameters = function.getParameters(); + assertEquals(1, parameters.size()); + DemangledDataType p1 = parameters.get(0); + assertEquals("bob(int const[8] (*) [12])", p1.getOriginalDemangled()); + assertEquals("undefined bob(int *[])", object.getSignature(false)); } @Test - public void testOverloadedShiftOperatorParsingBug() { - parser = new GnuDemanglerParser(null); - DemangledObject object = parser.parse(null, - "std::basic_istream >& " + - "std::operator>> >" + - "(std::basic_istream >&, char&)"); - String name = object.getName(); - assertEquals("operator>>>", name); + public void testParse_CastInTemplates() throws Exception { + + String demangled = + "std::__default_alloc_template<(bool)1, (int)0>::allocate(unsigned)"; + DemangledObject object = parser.parse("fake", demangled); + assertType(object, DemangledFunction.class); + assertName(object, "allocate", "std", "__default_alloc_template<(bool)1,(int)0>"); + + assertEquals( + "undefined std::__default_alloc_template<(bool)1,(int)0>::allocate(unsigned)", + object.getSignature(false)); } @Test - public void testParsing() throws Exception { + public void testParse_CastInTemplates_WithNegativeNumber() throws Exception { - DemangledObject parse = parser.parse(null, "__gthread_active_p()::__gthread_active_ptr"); - assertTrue(parse instanceof DemangledVariable); - assertName(parse, "__gthread_active_ptr", "__gthread_active_p()"); + String demangled = + "A::B::C::Foo::Foo(A::B::Bar*, A::B::C::Foo*)"; + DemangledObject object = parser.parse("fake", demangled); + assertType(object, DemangledFunction.class); + assertName(object, "Foo", "A", "B", "C", "Foo"); - parse = parser.parse(null, "typeinfo name for Magick::Blob"); - assertTrue(parse instanceof DemangledString); - assertEquals("Magick::Blob", ((DemangledString) parse).getString()); - assertName(parse, "typeinfo_name", "Magick", "Blob"); - - parse = parser.parse(null, "Bob::operator_new[](float, double, Bob::Fred &)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "operator_new[]", "Bob"); - - parse = parser.parse(null, - "Magick::pageImage::operator()(Magick::pageImage::Image::abc&) const"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "operator()", "Magick", "pageImage"); - - parse = parser.parse(null, - "std::__default_alloc_template<(bool)1, (int)0>::allocate(unsigned)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "allocate", "std", "__default_alloc_template<(bool)1,(int)0>"); - - parse = parser.parse(null, - "XpsMap::XpsMap(unsigned long (*)(long const &), unsigned long, unsigned long, float)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "XpsMap", "XpsMap"); - - parse = parser.parse(null, "Bar::Foo::getX(float)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "getX", "Bar", "Foo"); - - parse = parser.parse(null, "toChar(int)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "toChar"); - - parse = parser.parse(null, "toFloat(int, double, char, long, short)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "toFloat"); - - parse = parser.parse(null, "toFloat(int**, double**, char**, long**, short**)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "toFloat"); - - parse = parser.parse(null, "Foo::operator<<(int)"); - assertTrue(parse instanceof DemangledMethod); - assertName(parse, "operator<<", "Foo"); - - parse = parser.parse(null, "Foo::getX(Bob::Fred,double, Martha)"); - assertTrue(parse instanceof DemangledMethod); - - parse = parser.parse("_ZThn8_N14nsPrintSession14QueryInterfaceERK4nsIDPPv", - "non-virtual thunk [nv:-8] to nsPrintSession::QueryInterface(nsID const&, void**)"); - assertTrue(parse instanceof DemangledThunk); - assertName(parse, "QueryInterface", "nsPrintSession"); - - parse = parser.parse( - "_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED1Ev", - "virtual thunk [v:0,-24] to std::basic_ostringstream, pool_allocator >::~basic_ostringstream [in-charge]()"); - assertTrue(parse instanceof DemangledThunk); - assertName(parse, "~basic_ostringstream", "std", - "basic_ostringstream,pool_allocator>"); - - parse = parser.parse("_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE", - "covariant return thunk [nv:0] [nv:16] to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const"); - assertTrue(parse instanceof DemangledThunk); - assertName(parse, "copy", "KHotKeys", "WindowTrigger"); - - try { - parse = parser.parse( - "_ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j", - "GrGLFunction::GrGLFunction(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)::{lambda(void const*, unsigned int)#1}::__invoke(void const*, unsigned int)"); - assertNull("Shouldn't have parsed", parser); - } - catch (Exception exc) { - // should get an exception - } + assertEquals( + "undefined A::B::C::Foo::Foo(A::B::Bar *,A::B::C::Foo *)", + object.getSignature(false)); } - private void assertName(DemangledObject demangledObj, String name, String... namespaces) { -// String label = demangledObj.getName(); -// if (demangledObj instanceof DemangledString) { -// label = ((DemangledString) demangledObj).getString(); -// } + @Test + public void testParse_MultiDimensionalArray() throws Exception { - assertEquals("Unexpected demangled name", name, demangledObj.getName()); - DemangledType namespace = demangledObj.getNamespace(); - for (int i = namespaces.length - 1; i >= 0; i--) { - String n = namespaces[i]; - assertNotNull("Namespace mismatch", namespace); - assertEquals(n, namespace.getName()); - namespace = namespace.getNamespace(); - } - assertNull("Namespace mismatch", namespace); + DemangledObject object = parser.parse("fake", + "Layout::graphNew(short[][][][], char*)"); + assertType(object, DemangledFunction.class); + DemangledFunction function = (DemangledFunction) object; + List parameters = function.getParameters(); + assertEquals(2, parameters.size()); + DemangledDataType p1 = parameters.get(0); + assertEquals(4, p1.getArrayDimensions()); } @Test @@ -197,7 +104,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertEquals("undefined glob_fn9(" + "char,int,long,long long,unsigned int,unsigned long,float,double,long double,bool,void *,void * *)", @@ -214,7 +121,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "XpsMap", "XpsMap"); assertEquals( @@ -222,48 +129,60 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { "unsigned long ()(long const &),unsigned long,unsigned long,float)", object.getSignature(false)); - DemangledMethod method = (DemangledMethod) object; + DemangledFunction method = (DemangledFunction) object; List parameters = method.getParameters(); assertEquals(4, parameters.size()); - assertEquals("unsigned long ()(long const &)", parameters.get(0).toSignature()); - assertEquals("unsigned long", parameters.get(1).toSignature()); - assertEquals("unsigned long", parameters.get(2).toSignature()); - assertEquals("float", parameters.get(3).toSignature()); + assertEquals("unsigned long ()(long const &)", parameters.get(0).getSignature()); + assertEquals("unsigned long", parameters.get(1).getSignature()); + assertEquals("unsigned long", parameters.get(2).getSignature()); + assertEquals("float", parameters.get(3).getSignature()); } @Test - public void testTemplates() throws Exception { + public void testTemplates_TemplatedType() throws Exception { String mangled = "_ZNKSt8_Rb_treeI8LocationS0_St9_IdentityIS0_ESt4lessIS0_ESaIS0_EE4findERKS0_"; - String demangled = process.demangle(mangled); + assertEquals( + "std" + + "::" + + "_Rb_tree, std::less, std::allocator >" + + "::" + + "find(Location const&) const", + demangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "find", "std", "_Rb_tree,std--less,std--allocator>"); - DemangledMethod method = (DemangledMethod) object; - List parameters = method.getParameters(); + DemangledFunction function = (DemangledFunction) object; + List parameters = function.getParameters(); assertEquals(1, parameters.size()); - assertEquals("Location const &", parameters.get(0).toSignature()); + assertEquals("Location const &", parameters.get(0).getSignature()); + } - mangled = + @Test + public void testTemplates_TemplatedInsertionSort() throws Exception { + + String mangled = "_ZSt16__insertion_sortIN9__gnu_cxx17__normal_iteratorIPSt4pairImP7PcodeOpESt6vectorIS5_SaIS5_EEEEPFbRKS5_SC_EEvT_SF_T0_"; - demangled = process.demangle(mangled); - object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + String demangled = process.demangle(mangled); + assertEquals( + "void std::__insertion_sort<__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, bool (*)(std::pair const&, std::pair const&)>(__gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, bool (*)(std::pair const&, std::pair const&))", + demangled); + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledFunction.class); - method = (DemangledMethod) object; - parameters = method.getParameters(); + DemangledFunction function = (DemangledFunction) object; + List parameters = function.getParameters(); assertEquals( "__insertion_sort<__gnu_cxx--__normal_iterator*,std--vector,std--allocator>>>,bool(*)(std--pairconst&,std--pairconst&)>", - method.getName()); - assertEquals("std", method.getNamespace().getName()); + function.getName()); + assertEquals("std", function.getNamespace().getName()); - // TODO: in the original, it was "bool (*)...." now is "bool ()" it still comes out as a function pointer assertEquals( "__gnu_cxx::__normal_iterator *,std::vector,std::allocator>>>", parameters.get(0).toString()); @@ -274,7 +193,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { "bool ()(std::pair const &,std::pair const &)", parameters.get(2).toString()); - assertTrue(parameters.get(2) instanceof DemangledFunctionPointer); + assertType(parameters.get(2), DemangledFunctionPointer.class); DemangledFunctionPointer fptr = (DemangledFunctionPointer) parameters.get(2); @@ -289,17 +208,17 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "insert", "std", "set,std--allocator>"); - DemangledMethod method = (DemangledMethod) object; + DemangledFunction method = (DemangledFunction) object; assertEquals( "undefined std::set,std--allocator>::insert(bbnode const * &)", method.getSignature(false)); List parameters = method.getParameters(); assertEquals(1, parameters.size()); - assertEquals("bbnode const * &", parameters.get(0).toSignature()); + assertEquals("bbnode const * &", parameters.get(0).getSignature()); } @Test @@ -309,33 +228,140 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "Fred", "Bar", "Fred"); - DemangledMethod method = (DemangledMethod) object; + DemangledFunction method = (DemangledFunction) object; assertEquals("undefined Bar::Fred::Fred(int)", method.getSignature(false)); List parameters = method.getParameters(); assertEquals(1, parameters.size()); - assertEquals("int", parameters.get(0).toSignature()); + assertEquals("int", parameters.get(0).getSignature()); } @Test - public void testMethods() throws Exception { + public void testDestructor() throws Exception { + + String mangled = "_ZN6Magick5ImageD1Ev"; + String demangled = process.demangle(mangled); + assertEquals("Magick::Image::~Image()", demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledFunction.class); + assertName(object, "~Image", "Magick", "Image"); + + assertEquals("undefined Magick::Image::~Image(void)", object.getSignature(false)); + } + + @Test + public void testThunk_Virtual() throws Exception { + + String mangled = + "_ZTv0_n24_NSt19basic_ostringstreamIcSt11char_traitsIcE14pool_allocatorIcEED0Ev"; + String demangled = process.demangle(mangled); + assertEquals( + "virtual thunk to std::basic_ostringstream, pool_allocator >::~basic_ostringstream()", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledThunk.class); + assertName(object, "~basic_ostringstream", "std", + "basic_ostringstream,pool_allocator>"); + + assertEquals( + "virtual thunk to undefined __thiscall std::basic_ostringstream,pool_allocator>::~basic_ostringstream(void)", + object.getSignature(false)); + } + + @Test + public void testThunk_NonVirtual() throws Exception { + + String mangled = + "_ZThn8_N14nsPrintSession6AddRefEv"; + String demangled = process.demangle(mangled); + assertEquals("non-virtual thunk to nsPrintSession::AddRef()", demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledThunk.class); + assertName(object, "AddRef", "nsPrintSession"); + + assertEquals("non-virtual thunk to undefined __thiscall nsPrintSession::AddRef(void)", + object.getSignature(false)); + } + + @Test + public void testParse_Thunk_NonVirtual_WithExtraInfo() throws Exception { + + String mangled = + "_ZThn8_N14nsPrintSession14QueryInterfaceERK4nsIDPPv"; + + // this is an older format + String demangled = + "non-virtual thunk [nv:-8] to nsPrintSession::QueryInterface(nsID const&, void**)"; + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledThunk.class); + assertName(object, "QueryInterface", "nsPrintSession"); + + // for now we preserve the extra stuff between 'thunk' and 'to' in the signature + assertEquals( + "non-virtual thunk [nv:-8] to undefined __thiscall nsPrintSession::QueryInterface(nsID const &,void * *)", + object.getSignature(false)); + } + + @Test + public void testThunk_CovariantReturn() throws Exception { + + String mangled = + "_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE"; + String demangled = process.demangle(mangled); + assertEquals( + "covariant return thunk to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledThunk.class); + assertName(object, "copy", "KHotKeys", "WindowTrigger"); + + assertEquals( + "covariant return thunk to undefined __thiscall KHotKeys::WindowTrigger::copy(KHotKeys::ActionData *)", + object.getSignature(false)); + } + + @Test + public void testParse_Thunk_testThunk_CovariantReturn_WithExtraInfo() throws Exception { + + String mangled = + "_ZTch0_h16_NK8KHotKeys13WindowTrigger4copyEPNS_10ActionDataE"; + + // this is an older format + String demangled = + "covariant return thunk [nv:0] [nv:16] to KHotKeys::WindowTrigger::copy(KHotKeys::ActionData*) const"; + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledThunk.class); + assertName(object, "copy", "KHotKeys", "WindowTrigger"); + + // for now we preserve the extra stuff between 'thunk' and 'to' in the signature + assertEquals( + "covariant return thunk [nv:0] [nv:16] to undefined __thiscall KHotKeys::WindowTrigger::copy(KHotKeys::ActionData *)", + object.getSignature(false)); + } + + @Test + public void testMethod() throws Exception { String mangled = "_ZN3Foo7getBoolEf"; String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "getBool", "Foo"); - DemangledMethod method = (DemangledMethod) object; - assertEquals("undefined Foo::getBool(float)", method.getSignature(false)); + DemangledFunction function = (DemangledFunction) object; + assertEquals("undefined Foo::getBool(float)", function.getSignature(false)); - List parameters = method.getParameters(); + List parameters = function.getParameters(); assertEquals(1, parameters.size()); - assertEquals("float", parameters.get(0).toSignature()); + assertEquals("float", parameters.get(0).getSignature()); } @Test @@ -345,7 +371,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "toFloat"); assertEquals("undefined toFloat(int,double,char,long,short)", object.getSignature(false)); @@ -354,11 +380,11 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { List parameters = function.getParameters(); assertEquals(5, parameters.size()); - assertEquals("int", parameters.get(0).toSignature()); - assertEquals("double", parameters.get(1).toSignature()); - assertEquals("char", parameters.get(2).toSignature()); - assertEquals("long", parameters.get(3).toSignature()); - assertEquals("short", parameters.get(4).toSignature()); + assertEquals("int", parameters.get(0).getSignature()); + assertEquals("double", parameters.get(1).getSignature()); + assertEquals("char", parameters.get(2).getSignature()); + assertEquals("long", parameters.get(3).getSignature()); + assertEquals("short", parameters.get(4).getSignature()); } @Test @@ -368,7 +394,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledVariable); + assertType(object, DemangledVariable.class); assertName(object, "magickCleanUpGuard", "Magick"); assertEquals("Magick::magickCleanUpGuard", object.getSignature(false)); @@ -385,11 +411,27 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledAddressTable); + assertType(object, DemangledAddressTable.class); assertName(object, "vtable", "Magick", "DrawableTextAntialias"); assertEquals("Magick::DrawableTextAntialias::vtable", object.getSignature(false)); + } + @Test + public void testReferenceTemporaryFor() throws Exception { + + String mangled = "_ZGRZNK17KSimpleFileFilter12passesFilterEPK9KFileItemE6dotdot"; + String demangled = process.demangle(mangled); + assertEquals( + "reference temporary #0 for KSimpleFileFilter::passesFilter(KFileItem const*) const::dotdot", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledVariable.class); + assertName(object, "dotdot", "KSimpleFileFilter", "passesFilter(KFileItem const *)"); + + assertEquals("KSimpleFileFilter::passesFilter(KFileItem const *)::dotdot", + object.getSignature(false)); } @Test @@ -399,28 +441,94 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledAddressTable); + assertType(object, DemangledAddressTable.class); assertName(object, "typeinfo", "Arts", "FileInputStream_impl_Factory"); assertEquals("Arts::FileInputStream_impl_Factory::typeinfo", object.getSignature(false)); } @Test - public void testGuardVariables() throws Exception { + public void testTypeInfo_For() throws Exception { + String mangled = "_ZTISt14unary_functionIPN9MagickLib12_DrawContextEvE"; + String demangled = process.demangle(mangled); + assertEquals("typeinfo for std::unary_function", demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledAddressTable.class); + assertName(object, "typeinfo", "std", "unary_function"); + + assertEquals("std::unary_function::typeinfo", + object.getSignature(false)); + } + + @Test + public void testTypeInfo_NameFor() throws Exception { + String mangled = "_ZTSSt14unary_functionIPN9MagickLib12_DrawContextEvE"; + String demangled = process.demangle(mangled); + assertEquals("typeinfo name for std::unary_function", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledString.class); + assertName(object, "typeinfo-name", "std", "unary_function"); + + assertEquals("typeinfo name for std::unary_function", + object.getSignature(false)); + } + + @Test + public void testVtable_ConstructionVtableFor() throws Exception { + + String mangled = "_ZTCN4Arts17StdoutWriter_implE68_NS_11Object_skelE"; + String demangled = process.demangle(mangled); + assertEquals("construction vtable for Arts::Object_skel-in-Arts::StdoutWriter_impl", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledAddressTable.class); + assertName(object, "construction-vtable", "Arts", "Object_skel-in-Arts", + "StdoutWriter_impl"); + + assertEquals("Arts::Object_skel-in-Arts::StdoutWriter_impl::construction-vtable", + object.getSignature(false)); + } + + @Test + public void testGuardVariable_WithGuardVariableText() throws Exception { + + String mangled = "_ZGVZN10KDirLister11emitChangesEvE3dot"; + String demangled = process.demangle(mangled); + assertEquals("guard variable for KDirLister::emitChanges()::dot", demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledVariable.class); + assertName(object, "dot", "KDirLister", "emitChanges()"); + + assertEquals("KDirLister::emitChanges()::dot", object.getSignature(false)); + + DemangledVariable variable = (DemangledVariable) object; + assertEquals("dot", variable.getName()); + assertEquals("emitChanges()", variable.getNamespace().getNamespaceName()); + assertEquals("KDirLister::emitChanges()", variable.getNamespace().getNamespaceString()); + assertNull(variable.getDataType()); // no type information provided + } + + @Test + public void testGuardVariable_ThreadPointer() throws Exception { String mangled = "_ZZ18__gthread_active_pvE20__gthread_active_ptr"; String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledVariable); + assertType(object, DemangledVariable.class); assertName(object, "__gthread_active_ptr", "__gthread_active_p()"); assertEquals("__gthread_active_p()::__gthread_active_ptr", object.getSignature(false)); DemangledVariable variable = (DemangledVariable) object; assertEquals("__gthread_active_ptr", variable.getName()); - assertEquals("__gthread_active_p()", variable.getNamespace().getName()); + assertEquals("__gthread_active_p()", variable.getNamespace().getNamespaceName()); assertNull(variable.getDataType()); // no type information provided } @@ -432,13 +540,14 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "CalcPortExposedRect", "LScrollerView"); assertEquals("undefined LScrollerView::CalcPortExposedRect(Rect &,bool)", @@ -456,13 +565,14 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "__dt", "MsoDAL", "VertFrame"); assertEquals("undefined MsoDAL::VertFrame::__dt(void)", object.getSignature(false)); @@ -473,15 +583,13 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // // The below demangles to DDDSaveOptionsCB(_WidgetRec*, void*, void*)::dialog [#1] // - // from program ddd - // String mangled = "_ZZ16DDDSaveOptionsCBP10_WidgetRecPvS1_E6dialog_0"; String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledVariable); - assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec*,void*,void*)"); + assertType(object, DemangledVariable.class); + assertName(object, "dialog", "DDDSaveOptionsCB(_WidgetRec *,void *,void *)"); assertEquals("DDDSaveOptionsCB(_WidgetRec *,void *,void *)::dialog", object.getSignature(false)); @@ -498,13 +606,14 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "GetColWidths", "CDataRenderer"); assertEquals("undefined CDataRenderer::GetColWidths(short &[])", @@ -522,13 +631,14 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "GetColWidths", "CDataRenderer"); assertEquals("undefined CDataRenderer::GetColWidths(short *[])", @@ -546,7 +656,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "graphNew", "Layout"); // note: the two pointers were condensed to one (I think this is correct, but not sure) @@ -563,7 +673,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = "Layout::graphNew(short (*) [41], char*)"; DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "graphNew", "Layout"); assertEquals("undefined Layout::graphNew(short *[],char *)", object.getSignature(false)); @@ -580,27 +690,28 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "_gmStage2"); assertEquals("undefined _gmStage2(SECTION_INFO *,int *,int *[],int,short const *)", object.getSignature(false)); - DemangledMethod method = (DemangledMethod) object; + DemangledFunction method = (DemangledFunction) object; List parameters = method.getParameters(); assertEquals(5, parameters.size()); - assertEquals("SECTION_INFO *", parameters.get(0).toSignature()); - assertEquals("int *", parameters.get(1).toSignature()); - assertEquals("int *[]", parameters.get(2).toSignature()); - assertEquals("int", parameters.get(3).toSignature()); - assertEquals("short const *", parameters.get(4).toSignature()); + assertEquals("SECTION_INFO *", parameters.get(0).getSignature()); + assertEquals("int *", parameters.get(1).getSignature()); + assertEquals("int *[]", parameters.get(2).getSignature()); + assertEquals("int", parameters.get(3).getSignature()); + assertEquals("short const *", parameters.get(4).getSignature()); } @Test @@ -614,13 +725,14 @@ 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); String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "__ct", "CStr", "Buffer"); assertEquals("undefined CStr::Buffer::__ct(CStr &,unsigned long)", @@ -647,7 +759,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledVariable); + assertType(object, DemangledVariable.class); assertName(object, "aaa<(bbb--ccc)120,ddd>"); assertEquals("aaa<(bbb--ccc)120,ddd>", object.getSignature(false)); @@ -662,7 +774,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { demangled = process.demangle(mangled); object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "setmember", "mysequence"); assertEquals("undefined mysequence::setmember(int,int)", object.getSignature(false)); @@ -677,7 +789,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { demangled = process.demangle(mangled); object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "Image", "Magick", "Image"); assertEquals( @@ -693,18 +805,56 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledMethod); + assertType(object, DemangledFunction.class); assertName(object, "operator<", "Magick"); - DemangledMethod method = (DemangledMethod) object; + DemangledFunction method = (DemangledFunction) object; assertEquals( "undefined Magick::operator<(Magick::Coordinate const &,Magick::Coordinate const &)", method.getSignature(false)); List parameters = method.getParameters(); assertEquals(2, parameters.size()); - assertEquals("Magick::Coordinate const &", parameters.get(0).toSignature()); - assertEquals("Magick::Coordinate const &", parameters.get(1).toSignature()); + assertEquals("Magick::Coordinate const &", parameters.get(0).getSignature()); + assertEquals("Magick::Coordinate const &", parameters.get(1).getSignature()); + } + + @Test + public void testOverloadedShiftOperatorParsingBug() { + parser = new GnuDemanglerParser(); + DemangledObject object = parser.parse(null, + "std::basic_istream >& " + + "std::operator>> >" + + "(std::basic_istream >&, char&)"); + String name = object.getName(); + assertEquals("operator>>", name); + assertEquals( + "std::basic_istream>& " + + "std::operator>>>" + + "(std::basic_istream> &,char &)", + object.getSignature()); + } + + @Test + public void testOperator_Functor() throws Exception { + + String mangled = "_ZNK6Magick9pageImageclERNS_5ImageE"; + String demangled = process.demangle(mangled); + assertEquals("Magick::pageImage::operator()(Magick::Image&) const", + demangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertType(object, DemangledFunction.class); + assertName(object, "operator()", "Magick", "pageImage"); + + DemangledFunction method = (DemangledFunction) object; + assertEquals( + "undefined Magick::pageImage::operator()(Magick::Image &)", + method.getSignature(false)); + + List parameters = method.getParameters(); + assertEquals(1, parameters.size()); + assertEquals("Magick::Image &", parameters.get(0).getSignature()); } @Test @@ -720,7 +870,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledObject object = parser.parse(mangled, demangled); assertNotNull(object); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); String signature = object.getSignature(false); assertEquals( @@ -737,13 +887,19 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // Format: operator std::string() const { return "bob"; } // // + // + // + // Mangled: _ZNK6Magick5ColorcvSsEv + // + // Demangled: Magick::Color::operator std::basic_string, std::allocator >() const + // String mangled = "_ZNK6Magick5ColorcvSsEv"; String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator.cast.to.basic_string", "Magick", "Color"); assertEquals("std::basic_string,std::allocator> " + @@ -772,7 +928,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator.cast.to.GCC_ApplicationInvokeIndication&", "GCC_IndicationPDU"); @@ -795,7 +951,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator.delete"); assertEquals("void operator.delete(void *)", object.getSignature(false)); @@ -811,7 +967,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // DemangledObject object = parser.parse("mangled", "operator delete[](void*)"); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator.delete[]"); assertEquals("void operator.delete[](void *)", object.getSignature(false)); @@ -831,7 +987,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator.new"); assertEquals("void * operator.new(unsigned long)", object.getSignature(false)); @@ -844,7 +1000,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "operator()", "Magick", "viewImage"); assertEquals("undefined Magick::viewImage::operator()(Magick::Image &)", @@ -864,10 +1020,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); - assertName(object, "decode_charset_iconv", "anonymous_namespace"); + assertType(object, DemangledFunction.class); + assertName(object, "decode_charset_iconv", "(anonymous_namespace)"); - assertEquals("undefined anonymous_namespace::decode_charset_iconv(char const *)", + assertEquals("undefined (anonymous_namespace)::decode_charset_iconv(char const *)", object.getSignature(false)); } @@ -883,10 +1039,10 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); - assertName(object, "mystrdup", "MeCab", "anonymous_namespace"); + assertType(object, DemangledFunction.class); + assertName(object, "mystrdup", "MeCab", "(anonymous_namespace)"); - assertEquals("undefined MeCab::anonymous_namespace::mystrdup(char const *)", + assertEquals("undefined MeCab::(anonymous_namespace)::mystrdup(char const *)", object.getSignature(false)); } @@ -903,13 +1059,14 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); + assertName(object, - "__uninitialized_copy_aux", + "__uninitialized_copy_aux", "std"); assertEquals( - "MeCab::anonymous_namespace::Range * std::__uninitialized_copy_aux(MeCab::anonymous_namespace::Range *,MeCab::anonymous_namespace::Range *,MeCab::anonymous_namespace::Range *,std::__false_type)", + "MeCab::(anonymous_namespace)::Range * std::__uninitialized_copy_aux(MeCab::(anonymous_namespace)::Range *,MeCab::(anonymous_namespace)::Range *,MeCab::(anonymous_namespace)::Range *,std::__false_type)", object.getSignature(false)); } @@ -918,7 +1075,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // // Mangled: _ZN2Dr15ClipboardHelper17FTransferGvmlDataERN3Art11TransactionERKN3Ofc13TReferringPtrINS_10DrawingE2oEEEbNS4_7TCntPtrI11IDataObjectEERNS_18IClientDataCreatorERNS4_7TVectorINS4_8TWeakPtrINS_14DrawingElementEEELj0ELj4294967295EEERNS1_6Rect64E // - // Demangled: Ofc::TSimpleTypeHelper::ToString(Art::Percentage const&, Ofc::TFixedVarStr<(int)2085>&) + // Demangled: Dr::ClipboardHelper::FTransferGvmlData(Art::Transaction&, Ofc::TReferringPtr const&, bool, Ofc::TCntPtr, Dr::IClientDataCreator&, Ofc::TVector, 0u, 4294967295u>&, Art::Rect64&) // String mangled = "_ZN2Dr15ClipboardHelper17FTransferGvmlDataERN3Art11TransactionERKN3Ofc13TReferringPtrINS_10DrawingE2oEEEbNS4_7TCntPtrI11IDataObjectEERNS_18IClientDataCreatorERNS4_7TVectorINS4_8TWeakPtrINS_14DrawingElementEEELj0ELj4294967295EEERNS1_6Rect64E"; @@ -926,7 +1083,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "FTransferGvmlData", "Dr", "ClipboardHelper"); assertEquals( @@ -934,6 +1091,25 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { object.getSignature(false)); } + @Test + public void testTemplatedParametersWithCast_OldStyleDemangle() throws Exception { + // + // This demangled string has appeared at some point in the past. It no longer looks like + // this (note the odd syntax of '<(int)2085>&)') + // + // Ofc::TSimpleTypeHelper::ToString(Art::Percentage const&, Ofc::TFixedVarStr<(int)2085>&) + // + String demangled = + "Ofc::TSimpleTypeHelper::ToString(Art::Percentage const&, Ofc::TFixedVarStr<(int)2085>&)"; + DemangledObject object = parser.parse("nomangled", demangled); + assertType(object, DemangledFunction.class); + assertName(object, "ToString", "Ofc", "TSimpleTypeHelper"); + + assertEquals( + "undefined Ofc::TSimpleTypeHelper::ToString(Art::Percentage const &,Ofc::TFixedVarStr<(int)2085> &)", + object.getSignature(false)); + } + @Test public void testTemplatedNameSpaces() throws Exception { // @@ -947,7 +1123,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue("Parsed a function", object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "perform", "Core", "AsyncFile"); DemangledFunction df = (DemangledFunction) object; @@ -955,7 +1131,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { List parameters = df.getParameters(); assertEquals("Number of parameters", 1, parameters.size()); assertEquals("Name of type parsed", "F", parameters.get(0).getName()); - assertEquals("Param Type Name parsed", "WTF::", + assertEquals("Param Type Name parsed", "WTF", parameters.get(0).getNamespace().toString()); assertEquals("Param Template was parsed", " (Core::File &)>", @@ -980,7 +1156,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "registerKeysChangedCallback", "LogLevelMonitor"); @@ -991,7 +1167,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledDataType demangParamDT = parameters.get(0); assertEquals("Name of type parsed", "function", demangParamDT.getName()); - assertEquals("Param Type Name parsed", "boost::", demangParamDT.getNamespace().toString()); + assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString()); assertEquals("Param Template parsed", "", demangParamDT.getTemplate().toString()); assertTrue("Is referent", demangParamDT.isReference()); @@ -1013,7 +1189,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "set_mutate_ares_options_callback", "DnsThread"); DemangledFunction df = (DemangledFunction) object; @@ -1023,7 +1199,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledDataType demangParamDT = parameters.get(0); assertEquals("Name of type parsed", "function", demangParamDT.getName()); - assertEquals("Param Type Name parsed", "boost::", demangParamDT.getNamespace().toString()); + assertEquals("Param Type Name parsed", "boost", demangParamDT.getNamespace().toString()); assertEquals("Param Template parsed", "", demangParamDT.getTemplate().toString()); assertTrue("Is referent", demangParamDT.isReference()); @@ -1047,7 +1223,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); assertName(object, "_M_insert_aux", "std", "vector,std--allocator>>"); @@ -1061,14 +1237,15 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // // Mangled: _ZTCN6Crypto10HmacSha256E0_NS_3MacE // - // Demangled: + // Demangled: construction vtable for Crypto::Mac-in-Crypto::HmacSha256 + // String mangled = "_ZTCN6Crypto10HmacSha256E0_NS_3MacE"; String demangled = process.demangle(mangled); DemangledObject object = parser.parse(mangled, demangled); - assertTrue(object instanceof DemangledAddressTable); + assertType(object, DemangledAddressTable.class); assertName(object, "construction-vtable", "Crypto", "Mac-in-Crypto", "HmacSha"); assertEquals("Crypto::Mac-in-Crypto::HmacSha::construction-vtable", @@ -1081,6 +1258,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { // Mangled: _Z11testVarArgsiz // // Demangled: testVarArgs(int, ...) + // String mangled = "_Z11testVarArgsiz"; @@ -1088,7 +1266,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledObject object = parser.parse(mangled, demangled); assertNotNull(object); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); DemangledFunction function = (DemangledFunction) object; List parameters = function.getParameters(); @@ -1112,7 +1290,7 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledObject object = parser.parse(mangled, demangled); assertNotNull(object); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); String signature = object.getSignature(false); assertEquals( @@ -1134,13 +1312,110 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { assertNull(res); } - // @Test TODO upcoming fix for GT-3545 + @Test + public void testStructureConstructorWithinTemplatedFunction() throws Exception { + + // + // Mangled: _ZZN9__gnu_cxx6__stoaIlicJiEEET0_PFT_PKT1_PPS3_DpT2_EPKcS5_PmS9_EN11_Save_errnoC2Ev + // + // Demangled: __gnu_cxx + // :: + // __stoa(long (*)(char const*, char**, int), char const*, char const*, unsigned long*, int) + // :: + // _Save_errno + // :: + // _Save_errno() + // + // This is _Save_errno struct's constructor inside of the stoa templated function, in the + // __gnu_cxx namespace. + // + + String mangled = + "_ZZN9__gnu_cxx6__stoaIlicJiEEET0_PFT_PKT1_PPS3_DpT2_EPKcS5_PmS9_EN11_Save_errnoC2Ev"; + String demangled = process.demangle(mangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertNotNull(object); + assertType(object, DemangledFunction.class); + + String signature = object.getSignature(false); + assertEquals( + "undefined __gnu_cxx" + + "::" + + "__stoa(long(*)(char_const*,char**,int),char_const*,char_const*,unsigned_long*,int)" + + "::" + + "_Save_errno::_Save_errno(void)", + signature); + } + + @Test + public void testOperator_NotEquals() throws Exception { + + // + // Mangled: _ZNK2cc14ScrollSnapTypeneERKS0_ + // + // Demangled: cc::ScrollSnapType::operator!=(cc::ScrollSnapType const&) const + // + + String mangled = "_ZNK2cc14ScrollSnapTypeneERKS0_"; + String demangled = process.demangle(mangled); + + DemangledObject object = parser.parse(mangled, demangled); + assertNotNull(object); + assertType(object, DemangledFunction.class); + + String signature = object.getSignature(false); + assertEquals("undefined cc::ScrollSnapType::operator!=(cc::ScrollSnapType const &)", + signature); + } + + @Test + public void testFunctionInLambdaNamespace() throws Exception { + + // + // Mangled: _ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j + // + // Demangled: GrGLFunction + // :: + // GrGLFunction(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0) + // :: + // {lambda(void const*, unsigned int)#1} + // :: + // __invoke(void const*, unsigned int) + // + + DemangledObject object = parser.parse( + "_ZZN12GrGLFunctionIFPKhjEEC1IZN13skia_bindings28CreateGLES2InterfaceBindingsEPN3gpu5gles214GLES2InterfaceEPNS6_14ContextSupportEE3$_0EET_ENUlPKvjE_8__invokeESF_j", + "GrGLFunction::GrGLFunction(skia_bindings::CreateGLES2InterfaceBindings(gpu::gles2::GLES2Interface*, gpu::ContextSupport*)::$_0)::{lambda(void const*, unsigned int)#1}::__invoke(void const*, unsigned int)"); + assertNotNull(object); + assertType(object, DemangledFunction.class); + + assertName(object, "__invoke", + "GrGLFunction", + "GrGLFunction(skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0)", + "{lambda(void_const*,unsigned_int)#1}"); + + String signature = object.getSignature(false); + assertEquals( + "undefined GrGLFunction::GrGLFunction(skia_bindings--CreateGLES2InterfaceBindings(gpu--gles2--GLES2Interface*,gpu--ContextSupport*)--$_0)::{lambda(void_const*,unsigned_int)#1}::__invoke(void const *,unsigned int)", + signature); + } + + @Test public void testFunctionWithLambda_WrappingAnotherFunctionCall() throws Exception { // // Mangled: _Z11wrap_360_cdIiEDTcl8wrap_360fp_Lf42c80000EEET_ // - // Demangled: (wrap_360({parm#1}, (float)[42c80000])) wrap_360_cd(int) + // Demangled: decltype (wrap_360({parm#1}, (float)[42c80000])) wrap_360_cd(int) + // + // 'wrap_360_cd(int)' is a function that takes an int and then passes that int along + // with a constant value to 'wrap_360' by using a lambda function. It looks like + // this: + // auto wrap_360_cd(int a) -> decltype(wrap_360(angle, 100.f)) + // + // where the function is declared with this syntax: + // auto identifier ( argument-declarations... ) -> return_type // String mangled = "_Z11wrap_360_cdIiEDTcl8wrap_360fp_Lf42c80000EEET_"; @@ -1148,10 +1423,36 @@ public class GnuDemanglerParserTest extends AbstractGenericTest { DemangledObject object = parser.parse(mangled, demangled); assertNotNull(object); - assertTrue(object instanceof DemangledFunction); + assertType(object, DemangledFunction.class); - // TODO maybe put full output in setUtilDemangled() String signature = object.getSignature(false); assertEquals("undefined wrap_360_cd(int)", signature); } + + @Test + public void testGetDataType_LongLong() throws Exception { + assertNotNull( + new DemangledDataType("fake", "fake", DemangledDataType.LONG_LONG).getDataType(null)); + } + + private void assertType(Demangled o, Class c) { + assertTrue("Wrong demangled type. " + + "\nExpected " + c + "; " + + "\nfound " + o.getClass(), + c.isInstance(o)); + } + + private void assertName(DemangledObject demangledObj, String name, String... namespaces) { + + assertEquals("Unexpected demangled name", name, demangledObj.getName()); + Demangled namespace = demangledObj.getNamespace(); + for (int i = namespaces.length - 1; i >= 0; i--) { + String expectedName = namespaces[i]; + assertNotNull("Namespace mismatch", namespace); + String actualName = namespace.getNamespaceName(); + assertEquals(expectedName, actualName); + namespace = namespace.getNamespace(); + } + assertNull("Namespace mismatch", namespace); + } } diff --git a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java index 32874d1ece..7c212ebe01 100644 --- a/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java +++ b/Ghidra/Features/GnuDemangler/src/test/java/ghidra/app/util/demangler/gnu/GnuDemanglerTest.java @@ -145,7 +145,7 @@ public class GnuDemanglerTest extends AbstractGenericTest { Symbol s = symbolTable.getPrimarySymbol(addr("01001000")); assertNotNull(s); - assertEquals("typeinfo_name", s.getName()); + assertEquals("typeinfo-name", s.getName()); assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true)); assertEquals("typeinfo name for AP_HAL::HAL::Callbacks", @@ -238,6 +238,7 @@ public class GnuDemanglerTest extends AbstractGenericTest { String demanglerName = GnuDemanglerOptions.GNU_DEMANGLER_DEFAULT; String applicationArguments = "-s MrBob"; try { + setErrorsExpected(true); GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName, applicationArguments); fail("Expected an exception when passing unknown arguments to the native demangler"); @@ -246,7 +247,7 @@ public class GnuDemanglerTest extends AbstractGenericTest { // expected Msg.error(this, "Test error", e); } - + setErrorsExpected(false); } private Address addr(String address) { diff --git a/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/gnu_mangled_names_macho.txt b/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/gnu_mangled_names_macho.txt deleted file mode 100644 index 518a929c18..0000000000 --- a/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/gnu_mangled_names_macho.txt +++ /dev/null @@ -1,16 +0,0 @@ -__ZTV15_IOConfigThread # -__ZN8IOSyncer9metaClassE # -__ZN8IOSyncer10superClassE # - -__ZN12KLDBootstrapD1Ev # -__ZN12KLDBootstrapD2Ev # -__ZN12KLDBootstrapC1Ev # -__ZN12KLDBootstrapC2Ev # - -__ZL26kCharsetNameISOLatinHebrew -__ZN9__gnu_cxxL16__stl_prime_listE -__ZNSs6appendERKSs -__ZTV21MmsMessageClassHeader - -__ZL30addRecipientsFromMmsWithHeaderPKcP10MmsMessageP9CTMessage # addRecipientsFromMmsWithHeader(char const*, MmsMessage*, CTMessage*) -__ZZN13MmsPduDecoder21_decodeMessageHeadersEP10MmsMessageE15requiredHeaders diff --git a/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/libMagick.symbols.txt b/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/libMagick.symbols.txt deleted file mode 100644 index f3e4fa08f5..0000000000 --- a/Ghidra/Features/GnuDemangler/src/test/resources/ghidra/app/util/demangler/libMagick.symbols.txt +++ /dev/null @@ -1,2280 +0,0 @@ -_ZNSt24__default_alloc_templateILb1ELi0EE8allocateEj -_ZN6Magick5ImageC1ERKSs -_ZN6Magick5Image10monochromeEb -_ZN6Magick5Image8quantizeEb -_ZN6Magick14PathCurvetoAbsC1ERKS0_ -_Znaj -_ZN6Magick8ImageRefC1EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZNK6Magick8ColorYUV1yEv -_ZN6Magick5Image8boxColorERKNS_5ColorE -_ZN6Magick7Options8fillRuleERKN9MagickLib8FillRuleE -_ZN6Magick7OptionsC1Ev -_ZN6MagickneERKNS_8GeometryES2_ -_ZN6Magick13PathLinetoAbsC1ERKS0_ -_ZN6Magick7Options4viewERKSs -_ZN6Magick5Image10matteColorERKNS_5ColorE -_ZNK6Magick7Options15backgroundColorEv -_ZN6Magick5Image6borderERKNS_8GeometryE -_ZN6Magick5ColorC2ERKS0_ -_ZN6Magick5ImageC1ERKNS_8GeometryERKNS_5ColorE -_ZN6Magick5Image5sceneEj -_ZN6Magick13PathMovetoAbsC1ERKS0_ -_ZN6Magick5Image13cycleColormapEi -_ZN6Magick5Image16floodFillTextureEjjRKS0_RKNS_5ColorE -_ZN6Magick5ImageD1Ev -_ZN6Magick5Image9fillColorERKNS_5ColorE -_ZN6Magick18ErrorResourceLimitC1ERKSs -_ZN6Magick19DrawableStrokeColorC1ERKS0_ -_ZN6Magick5Image5shaveERKNS_8GeometryE -_ZNK6Magick5Image19throwImageExceptionEv -_ZN6MagickltERKNS_10CoordinateES2_ -_ZNSt9exceptionD2Ev -_ZN6Magick5Image5matteEb -_ZN6MagickgtERKNS_5ColorES2_ -_ZN6Magick14throwExceptionERN9MagickLib14_ExceptionInfoE -_ZN6Magick12DrawableTextC1ERKS0_ -_ZN6Magick13ErrorFileOpenC1ERKSs -_ZN6Magick5Image5frameEjjii -_ZN6Magick14ErrorUndefinedC1ERKSs -_ZNSt10_List_baseIN6Magick5VPathESaIS1_EE5clearEv -_ZN6Magick5Image11strokeWidthEd -_ZN6Magick7MontageC2Ev -_ZNK6Magick7Options9fillColorEv -_ZN6Magick4BlobC1EPKvj -_ZN6Magick7Options10x11DisplayERKSs -_ZN6Magick5Image18chromaGreenPrimaryEdd -_ZNKSs4copyEPcjj -_ZN6Magick5Image4drawERKSt4listINS_8DrawableESaIS2_EE -_ZNSs4_Rep10_M_disposeERKSaIcE -_ZN6Magick9MutexLockC1Ev -_ZNSsC1ERKSs -_ZNK6Magick7Options8fillRuleEv -_ZN6Magick5Image4blurEdd -_ZN6Magick5Image13interlaceTypeEN9MagickLib13InterlaceTypeE -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC1ERKS0_ -_ZNK6Magick7Options15strokeDashArrayEv -_ZN6Magick5Image9colorFuzzEd -_ZN6Magick7Options15transformOriginEdd -_ZN6Magick5Image16chromaRedPrimaryEdd -_ZN6Magick5Image18quantizeColorSpaceEN9MagickLib14ColorspaceTypeE -_ZN6Magick7Options5debugEb -_ZN6Magick8GeometryC1ERKN9MagickLib14_RectangleInfoE -_ZN6Magick12DrawablePathC1ERKS0_ -_ZNSt14__simple_allocISt10_List_nodeIN6Magick8DrawableEESt24__default_alloc_templateILb1ELi0EEE10deallocateEPS3_j -_ZN6Magick20ErrorMissingDelegateC1ERKSs -_ZN6Magick5Image15backgroundColorERKNS_5ColorE -_ZNK6Magick7Options8boxColorEv -_ZNSt4listIN6Magick10CoordinateESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZN6Magick5VPathC1ERKS0_ -_ZN6MagickgtERKNS_10CoordinateES2_ -_ZN6Magick5Image16chromaWhitePointEdd -_ZN6Magick5Image7enhanceEv -_ZN6Magick9MutexLock4lockEv -_ZN6Magick5Image16floodFillTextureERKNS_8GeometryERKS0_ -_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EED2Ev -_ZN6Magick8GeometryaSERKSs -_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_EPKS3_RKS6_ -_ZN6Magick7Options6endianEN9MagickLib10EndianTypeE -_ZN6Magick23PathQuadraticCurvetoAbsC1ERKS0_ -_ZNSt14__simple_allocISt10_List_nodeIN6Magick5VPathEESt24__default_alloc_templateILb1ELi0EEE10deallocateEPS3_j -_ZN6Magick12ErrorXServerC1ERKSs -_ZN6Magick5Image7magnifyEv -_ZN6Magick17DrawableDashArray9dasharrayEPKj -_ZN6Magick29PathSmoothQuadraticCurvetoRelC1ERKS0_ -_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EE5clearEv -_ZN6Magick9MutexLockD1Ev -_ZN6Magick5Image9antiAliasEb -_ZN6Magick15WarningFileOpenC1ERKSs -_ZN6Magick5ImageC1ERKS0_ -_ZNK6Magick7Options5debugEv -_ZN6Magick8ImageRefC1Ev -_ZN6MagickneERKNS_5ColorES2_ -_ZN6Magick5Image6minifyEv -_ZN6Magick14WarningXServerC1ERKSs -_ZN6Magick7Options7densityERKNS_8GeometryE -_ZN6Magick5Image4cropERKNS_8GeometryE -_ZN6Magick5Image11borderColorERKNS_5ColorE -_ZN6Magick14PathCurvetoRelC1ERKS0_ -_ZN6Magick8GeometryC1EPKc -_ZN6Magick5Image11strokeColorERKNS_5ColorE -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZN6Magick5Image7verboseEb -_ZN6Magick5Image8modulateEddd -_ZN6Magick5Image4fontERKSs -_ZN6Magick7BlobRefD1Ev -_ZN6Magick5ColorD1Ev -_ZNSs6assignERKSs -_ZN6Magick13MagickCleanUpC1Ev -_ZN6Magick5Image12compressTypeEN9MagickLib15CompressionTypeE -_ZN6Magick5Image11modifyImageEv -_ZN6Magick5Image7steganoERKS0_ -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSsD1Ev -_ZN6Magick5Image14floodFillColorEjjRKNS_5ColorE -_ZN6Magick5ImageC1EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZN6Magick5Image14quantizeColorsEj -_ZdlPv -_ZNK6Magick8GeometrycvN9MagickLib14_RectangleInfoEEv -_ZSt10__distanceISt14_List_iteratorIN6Magick10CoordinateERKS2_PS3_EENSt15iterator_traitsIT_E15difference_typeES8_S8_St18input_iterator_tag -_ZN6Magick5Image12medianFilterEd -_ZNK6Magick7Options6magickEv -_ZN6Magick5Image7qualityEj -_ZNSt10_List_baseIN6Magick5VPathESaIS1_EED2Ev -_ZN6Magick15DrawablePolygonC1ERKS0_ -_ZN6Magick7Options15resolutionUnitsEN9MagickLib14ResolutionTypeE -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNK6Magick5Image9signatureEb -_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EED2Ev -_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EED2Ev -_ZN6Magick5Image6embossEdd -_ZN6Magick5Image4flopEv -_ZN6Magick19WarningCorruptImageC1ERKSs -_ZN6Magick5Image8fileNameERKSs -_ZN6Magick5Image4typeEN9MagickLib9ImageTypeE -_ZSt9terminatev -_ZN6Magick5Image8annotateERKSsRKNS_8GeometryEN9MagickLib11GravityTypeEd -_ZN6Magick5Image15renderingIntentEN9MagickLib15RenderingIntentE -_ZN6Magick5Image10x11DisplayERKSs -_ZN6Magick5Image4chopERKNS_8GeometryE -_ZN6Magick5Image9transformERKNS_8GeometryES3_ -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZNSs7replaceEjjPKcj -_ZN6Magick5Image10colorSpaceEN9MagickLib14ColorspaceTypeE -_ZNSt4listIN6Magick10CoordinateESaIS1_EE14_M_create_nodeERKS1_ -_ZN6Magick7Options15strokeDashArrayEPKd -_ZNK6Magick7Options7densityEv -_ZN6Magick8GeometryaSEPKc -_ZN6Magick5Image4viewERKSs -_ZNSs7reserveEj -_ZNSt4listIN6Magick5VPathESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZN6Magick5ColorC1ERKS0_ -_ZNK6Magick8GeometrycvSsEv -_ZN6Magick5Image7channelEN9MagickLib11ChannelTypeE -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryERKSs -_ZN6Magick5ImageC1Ev -_ZN6Magick10PathArcRelC1ERKS0_ -_ZNK6Magick7Montage17updateMontageInfoERN9MagickLib12_MontageInfoE -_ZN6Magick5Image6endianEN9MagickLib10EndianTypeE -_ZN6Magick5Image9thresholdEd -_ZN6Magick9ExceptionC2ERKS0_ -_ZN6Magick5Image9compositeERKS0_iiN9MagickLib17CompositeOperatorE -_ZN6Magick6PixelsD1Ev -_ZN6Magick5Image12replaceImageEPN9MagickLib6_ImageE -_ZN6Magick8GeometryD1Ev -_ZN6Magick7Options14transformSkewYEd -_ZNK6Magick5Image14getConstPixelsEiijj -_ZN6Magick5Image7implodeEd -_ZN6MagickltERKNS_5ImageES2_ -_ZN6MagickneERKNS_5ImageES2_ -_ZN6Magick5Image15resolutionUnitsEN9MagickLib14ResolutionTypeE -_ZN6Magick5Image14matteFloodfillERKNS_5ColorEjiiN9MagickLib11PaintMethodE -_ZN6Magick5Image6adjoinEb -_ZN6Magick5Image4readERKNS_4BlobE -_ZN6Magick5Image16gifDisposeMethodEj -_ZN6Magick9ExceptionC2ERKSs -_ZN6Magick5Image7sharpenEdd -_ZN6Magick5Image9despeckleEv -_ZN6Magick5Image5labelERKSs -_ZN6Magick19DrawablePushPatternC1ERKS0_ -_ZN6Magick11ErrorOptionC1ERKSs -_ZN6Magick5Image17quantizeTreeDepthEj -_ZN6Magick5Image11transparentERKNS_5ColorE -_ZN6Magick5Image7segmentEdd -_ZN6Magick22throwExceptionExplicitEN9MagickLib13ExceptionTypeEPKcS3_ -_ZN6Magick5Image5scaleERKNS_8GeometryE -_ZN6MagickeqERKNS_5ImageES2_ -_ZNSt4listIN6Magick8DrawableESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZN6Magick5Image7densityERKNS_8GeometryE -_ZNK6Magick7Options8tileNameEv -_ZN6Magick5Image16floodFillTextureERKNS_8GeometryERKS0_RKNS_5ColorE -_ZN6Magick5Image14quantizeDitherEb -_ZN6Magick5Image13fontPointsizeEd -_ZN6Magick9MutexLock6unlockEv -_ZN6Magick5Image12gaussianBlurEdd -_ZN6Magick8GeometryC1Ev -_ZN6Magick12DrawableBaseD2Ev -_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EE5clearEv -_ZN6Magick5ColoraSEPKc -_ZN6Magick8DrawableD1Ev -_ZN6Magick5Image10filterTypeEN9MagickLib11FilterTypesE -_ZNK6Magick8DrawableclEPN9MagickLib12_DrawContextE -_ZN6Magick5Image4sizeERKNS_8GeometryE -_ZN6Magick7Options4pageERKNS_8GeometryE -_ZNK6Magick7Options13strokePatternEv -_ZN6Magick17ErrorCorruptImageC1ERKSs -_ZN6Magick5Image6stereoERKS0_ -_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EE5clearEv -_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE5clearEv -_ZN6Magick5Image8colorMapEjRKNS_5ColorE -_ZN6Magick5Image7textureERKS0_ -_ZN6Magick7BlobRefC1EPKvj -_ZN6Magick12DrawableFontC1ERKS0_ -_ZN6Magick5Image17chromaBluePrimaryEdd -_ZNSs6appendEjc -_ZN6Magick5Image4trimEv -_ZN6MagickeqERKNS_8GeometryES2_ -_ZN6Magick5ColoraSERKS0_ -_ZN6Magick5Image4flipEv -_ZNK6Magick7Options17backgroundTextureEv -_ZN6Magick5Image19animationIterationsEj -_ZN6Magick22WarningMissingDelegateC1ERKSs -_ZN6Magick5Image4waveEdd -_ZN6Magick6PixelsC1ERNS_5ImageE -_ZNK6Magick5Image6magickEv -_ZN6Magick8ImageRefD1Ev -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryEjRKSs -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryE -_ZN6Magick7Options6magickERKSs -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryEj -_ZN6Magick5Image4pageERKNS_8GeometryE -_ZN6Magick17DrawableDashArray9dasharrayEPKd -_ZN6Magick8ImageRef5imageEPN9MagickLib6_ImageE -_ZN6Magick5Image6magickERKSs -_ZdaPv -_ZN6Magick8DrawableC1ERKS0_ -_ZN6Magick7Options8tileNameERKSs -_ZN6Magick8ImageRef2idEl -_ZN6Magick5Image4readEjjRKSsN9MagickLib11StorageTypeEPKv -_ZN6Magick7Options14transformSkewXEd -_ZN6Magick20PathSmoothCurvetoAbsC1ERKS0_ -_ZN6Magick5Image9transformERKNS_8GeometryE -_ZNK6Magick5Image15getConstIndexesEv -_ZN6Magick7WarningC2ERKSs -_ZN6Magick7Options14transformResetEv -_ZN6Magick5Image6spreadEj -_ZN6Magick5Image8colorizeEjjjRKNS_5ColorE -_ZN6Magick10ErrorCacheC1ERKSs -_ZNK6Magick7Options11borderColorEv -_ZNSs6appendERKSs -_ZNK6Magick5Image10pixelColorEjj -_ZN6Magick5Image14floodFillColorEjjRKNS_5ColorES3_ -_ZN6Magick5Image8addNoiseEN9MagickLib9NoiseTypeE -_ZN6Magick8GeometryC1Ejjjjbb -_ZNSsC1EPKcRKSaIcE -_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EED2Ev -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZNK6Magick7Options10x11DisplayEv -_ZN6Magick5Image8tileNameERKSs -_ZN6Magick17DrawableFillColorC1ERKS0_ -_ZNSt24__default_alloc_templateILb1ELi0EE10deallocateEPvj -_ZN6Magick5Image7commentERKSs -_ZN6Magick16DrawablePolylineC1ERKS0_ -_ZN6MagickltERKNS_5ColorES2_ -_ZN6Magick22DrawableCompositeImageC1ERKS0_ -_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EED2Ev -_ZN6Magick7OptionsC1ERKS0_ -_ZN6Magick5Image6opaqueERKNS_5ColorES3_ -_ZN6Magick7Options10matteColorERKNS_5ColorE -_ZN6Magick5Image9classTypeEN9MagickLib9ClassTypeE -_ZN6Magick5Image9normalizeEv -_ZN6Magick5Image4readERKSs -_ZN6Magick4Blob12updateNoCopyEPvjNS0_9AllocatorE -_ZN6Magick7Options17transformRotationEd -_ZN6Magick10PathArcAbsC1ERKS0_ -_ZNK6Magick7Options11fillPatternEv -_ZN6Magick5Image8equalizeEv -_ZN6Magick23PathQuadraticCurvetoRelC1ERKS0_ -_ZN6Magick5Image8contrastEj -_ZNK6Magick5Image8fileNameEv -_ZN6Magick7Options11strokeColorERKNS_5ColorE -_ZN6Magick7Options15backgroundColorERKNS_5ColorE -_ZNK6Magick7Options8fileNameEv -_ZN6Magick11WarningBlobC1ERKSs -_ZN6Magick5Image14animationDelayEj -_ZNK6Magick5VPathclEPN9MagickLib12_DrawContextE -_ZN6Magick5Image5gammaEddd -_ZN6Magick7Options17backgroundTextureERKSs -_ZN6Magick5Image6negateEb -_ZN6Magick7Options11borderColorERKNS_5ColorE -_ZN6Magick5Image5swirlEd -_ZN6Magick5Image4zoomERKNS_8GeometryE -_ZN6Magick5Image16floodFillTextureEjjRKS0_ -_ZN6Magick13PathLinetoRelC1ERKS0_ -_ZNSsC1EPKcjRKSaIcE -_ZN6Magick5Image11reduceNoiseEd -_ZN6Magick12WarningCacheC1ERKSs -_ZNK6Magick7Options15resolutionUnitsEv -_ZN6Magick7OptionsD1Ev -_ZN6Magick5Image17backgroundTextureERKSs -_ZN6Magick20PathSmoothCurvetoRelC1ERKS0_ -_ZN6Magick5Image3mapERKS0_b -_ZN6Magick5Image6rotateEd -_ZN6Magick7Options9fillColorERKNS_5ColorE -_ZN6Magick5Image6sampleERKNS_8GeometryE -_ZN6Magick7Options11fillPatternEPKN9MagickLib6_ImageE -_ZN6Magick7Options4sizeERKNS_8GeometryE -_ZNK6Magick8ColorYUV1uEv -_ZNK6Magick5ColorcvSsEv -_ZN6Magick7Options8boxColorERKNS_5ColorE -_ZN6MagickeqERKNS_10CoordinateES2_ -_ZN6Magick5Image7opacityEj -_ZN6Magick5Image4edgeEd -_ZN6Magick22DrawableTextUnderColorC1ERKS0_ -_ZN6Magick5Image10pixelColorEjjRKNS_5ColorE -_ZNSt4listIN6Magick8DrawableESaIS1_EE14_M_create_nodeERKS1_ -_ZNK6Magick7Options4fontEv -_ZN6Magick7Options4fontERKSs -_Znwj -_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EE5clearEv -_ZN6Magick5Image5shadeEddb -_ZN6Magick5Image8oilPaintEd -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZN6Magick5Image10penTextureERKS0_ -_ZN6Magick5ErrorC2ERKSs -_ZNSt4listIN6Magick10CoordinateESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZN6MagickgtERKNS_8GeometryES2_ -_ZN6Magick5Image5shearEdd -_ZNK6Magick8ColorYUV1vEv -_ZN6Magick5Image8subImageEj -_ZN6Magick5Image8charcoalEdd -_ZN6Magick14DrawableBezierC1ERKS0_ -_ZN6Magick5Image5depthEj -_ZN6Magick13MagickCleanUpD1Ev -_ZN6MagickeqERKNS_5ColorES2_ -_ZN6Magick13PathMovetoRelC1ERKS0_ -_ZN6Magick5Image5raiseERKNS_8GeometryEb -_ZN6Magick5Image8solarizeEd -_ZN6MagickltERKNS_8GeometryES2_ -_ZN6MagickneERKNS_10CoordinateES2_ -_ZN6Magick6Pixels3getEiijj -_ZN6Magick9ErrorBlobC1ERKSs -_ZN6Magick7Options8fileNameERKSs -_ZN6Magick17DrawableDashArrayC1ERKS0_ -_ZN6Magick5Image4rollEjj -_ZN6Magick5ColorC1ERKN9MagickLib12_PixelPacketE -_ZN6Magick13ErrorDelegateC1ERKSs -_ZN6Magick11CloneStringEPPcRKSs -_ZN6Magick5ColoraSERKSs -_ZNK6Magick7Options11strokeColorEv -_ZNK6Magick5Image8colorMapEj -_ZNSs4_Rep10_M_destroyERKSaIcE -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZN6Magick13WarningOptionC1ERKSs -_ZN6Magick7Options13strokePatternEPKN9MagickLib6_ImageE -_ZNK6Magick7Options4viewEv -_ZN6Magick5Image8subRangeEj -_ZN6Magick15WarningDelegateC1ERKSs -_ZN6Magick6Pixels4syncEv -_ZN6Magick20WarningResourceLimitC1ERKSs -_ZN6Magick7Options14transformScaleEdd -_ZN6Magick9VPathBaseD2Ev -_ZN6Magick8GeometryC1ERKS0_ -_ZN6Magick5Image7isValidEb -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZNK6Magick5Image7isValidEv -_ZNSs6appendEPKcj -_ZN6Magick5Image8penColorERKNS_5ColorE -_ZN6MagickgtERKNS_5ImageES2_ -_ZN6Magick4BlobC2Ev -_ZN6Magick4BlobC1Ev -_ZN6Magick4BlobC2EPKvj -_ZN6Magick4BlobC1EPKvj -_ZN6Magick4BlobC2ERKS0_ -_ZN6Magick4BlobC1ERKS0_ -_ZN6Magick4BlobD2Ev -_ZN6Magick4BlobD1Ev -_ZN6Magick4BlobD0Ev -_ZN6Magick4BlobaSERKS0_ -_ZN6Magick4Blob6base64ESs -_ZN6Magick4Blob6base64Ev -_ZN6Magick4Blob6updateEPKvj -_ZN6Magick4Blob12updateNoCopyEPvjNS0_9AllocatorE -_ZN6Magick7BlobRefC2EPKvj -_ZN6Magick7BlobRefC1EPKvj -_ZN6Magick7BlobRefD2Ev -_ZN6Magick7BlobRefD1Ev -_ZN6Magick9CoderInfoC2ERKSs -_ZN6Magick9CoderInfoC1ERKSs -_ZN6Magick9CoderInfoD2Ev -_ZN6Magick9CoderInfoD1Ev -_ZNK6Magick9CoderInfo4nameEv -_ZNK6Magick9CoderInfo11descriptionEv -_ZNK6Magick9CoderInfo10isReadableEv -_ZNK6Magick9CoderInfo10isWritableEv -_ZNK6Magick9CoderInfo12isMultiFrameEv -_ZN6Magick9CoderInfoC2EPKN9MagickLib11_MagickInfoE -_ZN6Magick9CoderInfoC1EPKN9MagickLib11_MagickInfoE -_ZN6MagickeqERKNS_5ColorES2_ -_ZN6MagickneERKNS_5ColorES2_ -_ZN6MagickgtERKNS_5ColorES2_ -_ZN6MagickltERKNS_5ColorES2_ -_ZN6MagickgeERKNS_5ColorES2_ -_ZN6MagickleERKNS_5ColorES2_ -_ZN6Magick5ColorC2ERKS0_ -_ZN6Magick5ColorC1ERKS0_ -_ZN6Magick5ColoraSERKS0_ -_ZN6Magick5ColoraSERKSs -_ZN6Magick5ColoraSEPKc -_ZNK6Magick5ColorcvSsEv -_ZN6Magick5ColorC2ERKN9MagickLib12_PixelPacketE -_ZN6Magick5ColorC1ERKN9MagickLib12_PixelPacketE -_ZN6Magick5ColoraSERKN9MagickLib12_PixelPacketE -_ZN6Magick8ColorHSLC2Eddd -_ZN6Magick8ColorHSLC1Eddd -_ZN6Magick8ColorHSLC2Ev -_ZN6Magick8ColorHSLC1Ev -_ZN6Magick8ColorHSLC2ERKNS_5ColorE -_ZN6Magick8ColorHSLC1ERKNS_5ColorE -_ZN6Magick8ColorHSLD2Ev -_ZN6Magick8ColorHSLD1Ev -_ZN6Magick8ColorHSLD0Ev -_ZN6Magick8ColorHSL3hueEd -_ZNK6Magick8ColorHSL3hueEv -_ZN6Magick8ColorHSL10saturationEd -_ZNK6Magick8ColorHSL10saturationEv -_ZN6Magick8ColorHSL10luminosityEd -_ZNK6Magick8ColorHSL10luminosityEv -_ZN6Magick8ColorHSLaSERKNS_5ColorE -_ZN6Magick9ColorGrayC2Ed -_ZN6Magick9ColorGrayC1Ed -_ZN6Magick9ColorGrayC2Ev -_ZN6Magick9ColorGrayC1Ev -_ZN6Magick9ColorGrayC2ERKNS_5ColorE -_ZN6Magick9ColorGrayC1ERKNS_5ColorE -_ZN6Magick9ColorGrayD2Ev -_ZN6Magick9ColorGrayD1Ev -_ZN6Magick9ColorGrayD0Ev -_ZN6Magick9ColorGray5shadeEd -_ZNK6Magick9ColorGray5shadeEv -_ZN6Magick9ColorGrayaSERKNS_5ColorE -_ZN6Magick9ColorMonoC2Eb -_ZN6Magick9ColorMonoC1Eb -_ZN6Magick9ColorMonoC2Ev -_ZN6Magick9ColorMonoC1Ev -_ZN6Magick9ColorMonoC2ERKNS_5ColorE -_ZN6Magick9ColorMonoC1ERKNS_5ColorE -_ZN6Magick9ColorMonoD2Ev -_ZN6Magick9ColorMonoD1Ev -_ZN6Magick9ColorMonoD0Ev -_ZN6Magick9ColorMono4monoEb -_ZNK6Magick9ColorMono4monoEv -_ZN6Magick9ColorMonoaSERKNS_5ColorE -_ZN6Magick8ColorRGBC2Eddd -_ZN6Magick8ColorRGBC1Eddd -_ZN6Magick8ColorRGBC2Ev -_ZN6Magick8ColorRGBC1Ev -_ZN6Magick8ColorRGBC2ERKNS_5ColorE -_ZN6Magick8ColorRGBC1ERKNS_5ColorE -_ZN6Magick8ColorRGBD2Ev -_ZN6Magick8ColorRGBD1Ev -_ZN6Magick8ColorRGBD0Ev -_ZN6Magick8ColorRGBaSERKNS_5ColorE -_ZN6Magick8ColorYUVC2Eddd -_ZN6Magick8ColorYUVC1Eddd -_ZN6Magick8ColorYUVC2Ev -_ZN6Magick8ColorYUVC1Ev -_ZN6Magick8ColorYUVC2ERKNS_5ColorE -_ZN6Magick8ColorYUVC1ERKNS_5ColorE -_ZN6Magick8ColorYUVD2Ev -_ZN6Magick8ColorYUVD1Ev -_ZN6Magick8ColorYUVD0Ev -_ZN6Magick8ColorYUV1uEd -_ZNK6Magick8ColorYUV1uEv -_ZN6Magick8ColorYUV1vEd -_ZNK6Magick8ColorYUV1vEv -_ZN6Magick8ColorYUV1yEd -_ZNK6Magick8ColorYUV1yEv -_ZN6Magick8ColorYUVaSERKNS_5ColorE -_ZN6Magick5ColorD1Ev -_ZN6Magick5ColorD0Ev -_ZN6MagickeqERKNS_10CoordinateES2_ -_ZN6MagickneERKNS_10CoordinateES2_ -_ZN6MagickgtERKNS_10CoordinateES2_ -_ZN6MagickltERKNS_10CoordinateES2_ -_ZN6MagickgeERKNS_10CoordinateES2_ -_ZN6MagickleERKNS_10CoordinateES2_ -_ZN6Magick12DrawableBaseD2Ev -_ZN6Magick12DrawableBaseD1Ev -_ZN6Magick12DrawableBaseD0Ev -_ZN6Magick8DrawableC2Ev -_ZN6Magick8DrawableC1Ev -_ZN6Magick8DrawableC2ERKNS_12DrawableBaseE -_ZN6Magick8DrawableC1ERKNS_12DrawableBaseE -_ZN6Magick8DrawableD2Ev -_ZN6Magick8DrawableD1Ev -_ZN6Magick8DrawableC2ERKS0_ -_ZN6Magick8DrawableC1ERKS0_ -_ZN6Magick8DrawableaSERKS0_ -_ZNK6Magick8DrawableclEPN9MagickLib12_DrawContextE -_ZN6Magick9VPathBaseD2Ev -_ZN6Magick9VPathBaseD1Ev -_ZN6Magick9VPathBaseD0Ev -_ZN6Magick5VPathC2Ev -_ZN6Magick5VPathC1Ev -_ZN6Magick5VPathC2ERKNS_9VPathBaseE -_ZN6Magick5VPathC1ERKNS_9VPathBaseE -_ZN6Magick5VPathD2Ev -_ZN6Magick5VPathD1Ev -_ZN6Magick5VPathD0Ev -_ZN6Magick5VPathC2ERKS0_ -_ZN6Magick5VPathC1ERKS0_ -_ZN6Magick5VPathaSERKS0_ -_ZNK6Magick5VPathclEPN9MagickLib12_DrawContextE -_ZN6Magick14DrawableAffineC2Edddddd -_ZN6Magick14DrawableAffineC1Edddddd -_ZN6Magick14DrawableAffineC2Ev -_ZN6Magick14DrawableAffineC1Ev -_ZN6Magick14DrawableAffineD2Ev -_ZN6Magick14DrawableAffineD1Ev -_ZN6Magick14DrawableAffineD0Ev -_ZNK6Magick14DrawableAffineclEPN9MagickLib12_DrawContextE -_ZNK6Magick14DrawableAffine4copyEv -_ZN6Magick11DrawableArcD2Ev -_ZN6Magick11DrawableArcD1Ev -_ZN6Magick11DrawableArcD0Ev -_ZNK6Magick11DrawableArcclEPN9MagickLib12_DrawContextE -_ZNK6Magick11DrawableArc4copyEv -_ZN6Magick14DrawableBezierC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick14DrawableBezierC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick14DrawableBezierC2ERKS0_ -_ZN6Magick14DrawableBezierC1ERKS0_ -_ZN6Magick14DrawableBezierD2Ev -_ZN6Magick14DrawableBezierD1Ev -_ZN6Magick14DrawableBezierD0Ev -_ZNK6Magick14DrawableBezierclEPN9MagickLib12_DrawContextE -_ZNK6Magick14DrawableBezier4copyEv -_ZN6Magick14DrawableCircleD2Ev -_ZN6Magick14DrawableCircleD1Ev -_ZN6Magick14DrawableCircleD0Ev -_ZNK6Magick14DrawableCircleclEPN9MagickLib12_DrawContextE -_ZNK6Magick14DrawableCircle4copyEv -_ZN6Magick13DrawableColorD2Ev -_ZN6Magick13DrawableColorD1Ev -_ZN6Magick13DrawableColorD0Ev -_ZNK6Magick13DrawableColorclEPN9MagickLib12_DrawContextE -_ZNK6Magick13DrawableColor4copyEv -_ZN6Magick22DrawableCompositeImageC2EddddRKSsN9MagickLib17CompositeOperatorE -_ZN6Magick22DrawableCompositeImageC1EddddRKSsN9MagickLib17CompositeOperatorE -_ZN6Magick22DrawableCompositeImageC2EddddRKNS_5ImageEN9MagickLib17CompositeOperatorE -_ZN6Magick22DrawableCompositeImageC1EddddRKNS_5ImageEN9MagickLib17CompositeOperatorE -_ZN6Magick22DrawableCompositeImageC2EddddRKSs -_ZN6Magick22DrawableCompositeImageC1EddddRKSs -_ZN6Magick22DrawableCompositeImageC2EddddRKNS_5ImageE -_ZN6Magick22DrawableCompositeImageC1EddddRKNS_5ImageE -_ZN6Magick22DrawableCompositeImageC2EddRKSs -_ZN6Magick22DrawableCompositeImageC1EddRKSs -_ZN6Magick22DrawableCompositeImageC2EddRKNS_5ImageE -_ZN6Magick22DrawableCompositeImageC1EddRKNS_5ImageE -_ZN6Magick22DrawableCompositeImageC2ERKS0_ -_ZN6Magick22DrawableCompositeImageC1ERKS0_ -_ZN6Magick22DrawableCompositeImageD2Ev -_ZN6Magick22DrawableCompositeImageD1Ev -_ZN6Magick22DrawableCompositeImageD0Ev -_ZN6Magick22DrawableCompositeImageaSERKS0_ -_ZN6Magick22DrawableCompositeImage8filenameERKSs -_ZNK6Magick22DrawableCompositeImage8filenameEv -_ZN6Magick22DrawableCompositeImage5imageERKNS_5ImageE -_ZNK6Magick22DrawableCompositeImage5imageEv -_ZN6Magick22DrawableCompositeImage6magickESs -_ZN6Magick22DrawableCompositeImage6magickEv -_ZNK6Magick22DrawableCompositeImageclEPN9MagickLib12_DrawContextE -_ZNK6Magick22DrawableCompositeImage4copyEv -_ZN6Magick15DrawableEllipseD2Ev -_ZN6Magick15DrawableEllipseD1Ev -_ZN6Magick15DrawableEllipseD0Ev -_ZNK6Magick15DrawableEllipseclEPN9MagickLib12_DrawContextE -_ZNK6Magick15DrawableEllipse4copyEv -_ZN6Magick17DrawableFillColorC2ERKNS_5ColorE -_ZN6Magick17DrawableFillColorC1ERKNS_5ColorE -_ZN6Magick17DrawableFillColorC2ERKS0_ -_ZN6Magick17DrawableFillColorC1ERKS0_ -_ZN6Magick17DrawableFillColorD2Ev -_ZN6Magick17DrawableFillColorD1Ev -_ZN6Magick17DrawableFillColorD0Ev -_ZNK6Magick17DrawableFillColorclEPN9MagickLib12_DrawContextE -_ZNK6Magick17DrawableFillColor4copyEv -_ZN6Magick16DrawableFillRuleD2Ev -_ZN6Magick16DrawableFillRuleD1Ev -_ZN6Magick16DrawableFillRuleD0Ev -_ZNK6Magick16DrawableFillRuleclEPN9MagickLib12_DrawContextE -_ZNK6Magick16DrawableFillRule4copyEv -_ZN6Magick19DrawableFillOpacityD2Ev -_ZN6Magick19DrawableFillOpacityD1Ev -_ZN6Magick19DrawableFillOpacityD0Ev -_ZNK6Magick19DrawableFillOpacityclEPN9MagickLib12_DrawContextE -_ZNK6Magick19DrawableFillOpacity4copyEv -_ZN6Magick12DrawableFontC2ERKSs -_ZN6Magick12DrawableFontC1ERKSs -_ZN6Magick12DrawableFontC2ERKSsN9MagickLib9StyleTypeEmNS3_11StretchTypeE -_ZN6Magick12DrawableFontC1ERKSsN9MagickLib9StyleTypeEmNS3_11StretchTypeE -_ZN6Magick12DrawableFontC2ERKS0_ -_ZN6Magick12DrawableFontC1ERKS0_ -_ZN6Magick12DrawableFontD2Ev -_ZN6Magick12DrawableFontD1Ev -_ZN6Magick12DrawableFontD0Ev -_ZNK6Magick12DrawableFontclEPN9MagickLib12_DrawContextE -_ZNK6Magick12DrawableFont4copyEv -_ZN6Magick15DrawableGravityD2Ev -_ZN6Magick15DrawableGravityD1Ev -_ZN6Magick15DrawableGravityD0Ev -_ZNK6Magick15DrawableGravityclEPN9MagickLib12_DrawContextE -_ZNK6Magick15DrawableGravity4copyEv -_ZN6Magick12DrawableLineD2Ev -_ZN6Magick12DrawableLineD1Ev -_ZN6Magick12DrawableLineD0Ev -_ZNK6Magick12DrawableLineclEPN9MagickLib12_DrawContextE -_ZNK6Magick12DrawableLine4copyEv -_ZN6Magick13DrawableMatteD2Ev -_ZN6Magick13DrawableMatteD1Ev -_ZN6Magick13DrawableMatteD0Ev -_ZNK6Magick13DrawableMatteclEPN9MagickLib12_DrawContextE -_ZNK6Magick13DrawableMatte4copyEv -_ZN6Magick12DrawablePathC2ERKSt4listINS_5VPathESaIS2_EE -_ZN6Magick12DrawablePathC1ERKSt4listINS_5VPathESaIS2_EE -_ZN6Magick12DrawablePathC2ERKS0_ -_ZN6Magick12DrawablePathC1ERKS0_ -_ZN6Magick12DrawablePathD2Ev -_ZN6Magick12DrawablePathD1Ev -_ZN6Magick12DrawablePathD0Ev -_ZNK6Magick12DrawablePathclEPN9MagickLib12_DrawContextE -_ZNK6Magick12DrawablePath4copyEv -_ZN6Magick13DrawablePointD2Ev -_ZN6Magick13DrawablePointD1Ev -_ZN6Magick13DrawablePointD0Ev -_ZNK6Magick13DrawablePointclEPN9MagickLib12_DrawContextE -_ZNK6Magick13DrawablePoint4copyEv -_ZN6Magick17DrawablePointSizeD2Ev -_ZN6Magick17DrawablePointSizeD1Ev -_ZN6Magick17DrawablePointSizeD0Ev -_ZNK6Magick17DrawablePointSizeclEPN9MagickLib12_DrawContextE -_ZNK6Magick17DrawablePointSize4copyEv -_ZN6Magick15DrawablePolygonC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick15DrawablePolygonC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick15DrawablePolygonC2ERKS0_ -_ZN6Magick15DrawablePolygonC1ERKS0_ -_ZN6Magick15DrawablePolygonD2Ev -_ZN6Magick15DrawablePolygonD1Ev -_ZN6Magick15DrawablePolygonD0Ev -_ZNK6Magick15DrawablePolygonclEPN9MagickLib12_DrawContextE -_ZNK6Magick15DrawablePolygon4copyEv -_ZN6Magick16DrawablePolylineC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick16DrawablePolylineC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick16DrawablePolylineC2ERKS0_ -_ZN6Magick16DrawablePolylineC1ERKS0_ -_ZN6Magick16DrawablePolylineD2Ev -_ZN6Magick16DrawablePolylineD1Ev -_ZN6Magick16DrawablePolylineD0Ev -_ZNK6Magick16DrawablePolylineclEPN9MagickLib12_DrawContextE -_ZNK6Magick16DrawablePolyline4copyEv -_ZN6Magick25DrawablePopGraphicContextD2Ev -_ZN6Magick25DrawablePopGraphicContextD1Ev -_ZN6Magick25DrawablePopGraphicContextD0Ev -_ZNK6Magick25DrawablePopGraphicContextclEPN9MagickLib12_DrawContextE -_ZNK6Magick25DrawablePopGraphicContext4copyEv -_ZN6Magick26DrawablePushGraphicContextD2Ev -_ZN6Magick26DrawablePushGraphicContextD1Ev -_ZN6Magick26DrawablePushGraphicContextD0Ev -_ZNK6Magick26DrawablePushGraphicContextclEPN9MagickLib12_DrawContextE -_ZNK6Magick26DrawablePushGraphicContext4copyEv -_ZN6Magick18DrawablePopPatternD2Ev -_ZN6Magick18DrawablePopPatternD1Ev -_ZN6Magick18DrawablePopPatternD0Ev -_ZNK6Magick18DrawablePopPatternclEPN9MagickLib12_DrawContextE -_ZNK6Magick18DrawablePopPattern4copyEv -_ZN6Magick19DrawablePushPatternC2ERKSsllll -_ZN6Magick19DrawablePushPatternC1ERKSsllll -_ZN6Magick19DrawablePushPatternC2ERKS0_ -_ZN6Magick19DrawablePushPatternC1ERKS0_ -_ZN6Magick19DrawablePushPatternD2Ev -_ZN6Magick19DrawablePushPatternD1Ev -_ZN6Magick19DrawablePushPatternD0Ev -_ZNK6Magick19DrawablePushPatternclEPN9MagickLib12_DrawContextE -_ZNK6Magick19DrawablePushPattern4copyEv -_ZN6Magick17DrawableRectangleD2Ev -_ZN6Magick17DrawableRectangleD1Ev -_ZN6Magick17DrawableRectangleD0Ev -_ZNK6Magick17DrawableRectangleclEPN9MagickLib12_DrawContextE -_ZNK6Magick17DrawableRectangle4copyEv -_ZN6Magick16DrawableRotationD2Ev -_ZN6Magick16DrawableRotationD1Ev -_ZN6Magick16DrawableRotationD0Ev -_ZNK6Magick16DrawableRotationclEPN9MagickLib12_DrawContextE -_ZNK6Magick16DrawableRotation4copyEv -_ZN6Magick22DrawableRoundRectangleD2Ev -_ZN6Magick22DrawableRoundRectangleD1Ev -_ZN6Magick22DrawableRoundRectangleD0Ev -_ZNK6Magick22DrawableRoundRectangleclEPN9MagickLib12_DrawContextE -_ZNK6Magick22DrawableRoundRectangle4copyEv -_ZN6Magick15DrawableScalingD2Ev -_ZN6Magick15DrawableScalingD1Ev -_ZN6Magick15DrawableScalingD0Ev -_ZNK6Magick15DrawableScalingclEPN9MagickLib12_DrawContextE -_ZNK6Magick15DrawableScaling4copyEv -_ZN6Magick13DrawableSkewXD2Ev -_ZN6Magick13DrawableSkewXD1Ev -_ZN6Magick13DrawableSkewXD0Ev -_ZNK6Magick13DrawableSkewXclEPN9MagickLib12_DrawContextE -_ZNK6Magick13DrawableSkewX4copyEv -_ZN6Magick13DrawableSkewYD2Ev -_ZN6Magick13DrawableSkewYD1Ev -_ZN6Magick13DrawableSkewYD0Ev -_ZNK6Magick13DrawableSkewYclEPN9MagickLib12_DrawContextE -_ZNK6Magick13DrawableSkewY4copyEv -_ZN6Magick17DrawableDashArrayC2EPKd -_ZN6Magick17DrawableDashArrayC1EPKd -_ZN6Magick17DrawableDashArrayC2EPKj -_ZN6Magick17DrawableDashArrayC1EPKj -_ZN6Magick17DrawableDashArrayC2ERKS0_ -_ZN6Magick17DrawableDashArrayC1ERKS0_ -_ZN6Magick17DrawableDashArrayD2Ev -_ZN6Magick17DrawableDashArrayD1Ev -_ZN6Magick17DrawableDashArrayD0Ev -_ZN6Magick17DrawableDashArrayaSERKS0_ -_ZNK6Magick17DrawableDashArrayclEPN9MagickLib12_DrawContextE -_ZNK6Magick17DrawableDashArray4copyEv -_ZN6Magick17DrawableDashArray9dasharrayEPKd -_ZN6Magick17DrawableDashArray9dasharrayEPKj -_ZN6Magick18DrawableDashOffsetD2Ev -_ZN6Magick18DrawableDashOffsetD1Ev -_ZN6Magick18DrawableDashOffsetD0Ev -_ZNK6Magick18DrawableDashOffsetclEPN9MagickLib12_DrawContextE -_ZNK6Magick18DrawableDashOffset4copyEv -_ZN6Magick21DrawableStrokeLineCapD2Ev -_ZN6Magick21DrawableStrokeLineCapD1Ev -_ZN6Magick21DrawableStrokeLineCapD0Ev -_ZNK6Magick21DrawableStrokeLineCapclEPN9MagickLib12_DrawContextE -_ZNK6Magick21DrawableStrokeLineCap4copyEv -_ZN6Magick22DrawableStrokeLineJoinD2Ev -_ZN6Magick22DrawableStrokeLineJoinD1Ev -_ZN6Magick22DrawableStrokeLineJoinD0Ev -_ZNK6Magick22DrawableStrokeLineJoinclEPN9MagickLib12_DrawContextE -_ZNK6Magick22DrawableStrokeLineJoin4copyEv -_ZN6Magick18DrawableMiterLimitD2Ev -_ZN6Magick18DrawableMiterLimitD1Ev -_ZN6Magick18DrawableMiterLimitD0Ev -_ZNK6Magick18DrawableMiterLimitclEPN9MagickLib12_DrawContextE -_ZNK6Magick18DrawableMiterLimit4copyEv -_ZN6Magick23DrawableStrokeAntialiasD2Ev -_ZN6Magick23DrawableStrokeAntialiasD1Ev -_ZN6Magick23DrawableStrokeAntialiasD0Ev -_ZNK6Magick23DrawableStrokeAntialiasclEPN9MagickLib12_DrawContextE -_ZNK6Magick23DrawableStrokeAntialias4copyEv -_ZN6Magick19DrawableStrokeColorC2ERKNS_5ColorE -_ZN6Magick19DrawableStrokeColorC1ERKNS_5ColorE -_ZN6Magick19DrawableStrokeColorC2ERKS0_ -_ZN6Magick19DrawableStrokeColorC1ERKS0_ -_ZN6Magick19DrawableStrokeColorD2Ev -_ZN6Magick19DrawableStrokeColorD1Ev -_ZN6Magick19DrawableStrokeColorD0Ev -_ZNK6Magick19DrawableStrokeColorclEPN9MagickLib12_DrawContextE -_ZNK6Magick19DrawableStrokeColor4copyEv -_ZN6Magick21DrawableStrokeOpacityD2Ev -_ZN6Magick21DrawableStrokeOpacityD1Ev -_ZN6Magick21DrawableStrokeOpacityD0Ev -_ZNK6Magick21DrawableStrokeOpacityclEPN9MagickLib12_DrawContextE -_ZNK6Magick21DrawableStrokeOpacity4copyEv -_ZN6Magick19DrawableStrokeWidthD2Ev -_ZN6Magick19DrawableStrokeWidthD1Ev -_ZN6Magick19DrawableStrokeWidthD0Ev -_ZNK6Magick19DrawableStrokeWidthclEPN9MagickLib12_DrawContextE -_ZNK6Magick19DrawableStrokeWidth4copyEv -_ZN6Magick12DrawableTextC2EddRKSs -_ZN6Magick12DrawableTextC1EddRKSs -_ZN6Magick12DrawableTextC2ERKS0_ -_ZN6Magick12DrawableTextC1ERKS0_ -_ZN6Magick12DrawableTextD2Ev -_ZN6Magick12DrawableTextD1Ev -_ZN6Magick12DrawableTextD0Ev -_ZNK6Magick12DrawableTextclEPN9MagickLib12_DrawContextE -_ZNK6Magick12DrawableText4copyEv -_ZN6Magick21DrawableTextAntialiasD2Ev -_ZN6Magick21DrawableTextAntialiasD1Ev -_ZN6Magick21DrawableTextAntialiasD0Ev -_ZNK6Magick21DrawableTextAntialiasclEPN9MagickLib12_DrawContextE -_ZNK6Magick21DrawableTextAntialias4copyEv -_ZN6Magick22DrawableTextDecorationD2Ev -_ZN6Magick22DrawableTextDecorationD1Ev -_ZN6Magick22DrawableTextDecorationD0Ev -_ZNK6Magick22DrawableTextDecorationclEPN9MagickLib12_DrawContextE -_ZNK6Magick22DrawableTextDecoration4copyEv -_ZN6Magick22DrawableTextUnderColorC2ERKNS_5ColorE -_ZN6Magick22DrawableTextUnderColorC1ERKNS_5ColorE -_ZN6Magick22DrawableTextUnderColorC2ERKS0_ -_ZN6Magick22DrawableTextUnderColorC1ERKS0_ -_ZN6Magick22DrawableTextUnderColorD2Ev -_ZN6Magick22DrawableTextUnderColorD1Ev -_ZN6Magick22DrawableTextUnderColorD0Ev -_ZNK6Magick22DrawableTextUnderColorclEPN9MagickLib12_DrawContextE -_ZNK6Magick22DrawableTextUnderColor4copyEv -_ZN6Magick19DrawableTranslationD2Ev -_ZN6Magick19DrawableTranslationD1Ev -_ZN6Magick19DrawableTranslationD0Ev -_ZNK6Magick19DrawableTranslationclEPN9MagickLib12_DrawContextE -_ZNK6Magick19DrawableTranslation4copyEv -_ZN6Magick15DrawableViewboxD2Ev -_ZN6Magick15DrawableViewboxD1Ev -_ZN6Magick15DrawableViewboxD0Ev -_ZNK6Magick15DrawableViewboxclEPN9MagickLib12_DrawContextE -_ZNK6Magick15DrawableViewbox4copyEv -_ZN6Magick10PathArcAbsC2ERKNS_11PathArcArgsE -_ZN6Magick10PathArcAbsC1ERKNS_11PathArcArgsE -_ZN6Magick10PathArcAbsC2ERKSt4listINS_11PathArcArgsESaIS2_EE -_ZN6Magick10PathArcAbsC1ERKSt4listINS_11PathArcArgsESaIS2_EE -_ZN6Magick10PathArcAbsC2ERKS0_ -_ZN6Magick10PathArcAbsC1ERKS0_ -_ZN6Magick10PathArcAbsD2Ev -_ZN6Magick10PathArcAbsD1Ev -_ZN6Magick10PathArcAbsD0Ev -_ZNK6Magick10PathArcAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick10PathArcAbs4copyEv -_ZN6Magick10PathArcRelC2ERKNS_11PathArcArgsE -_ZN6Magick10PathArcRelC1ERKNS_11PathArcArgsE -_ZN6Magick10PathArcRelC2ERKSt4listINS_11PathArcArgsESaIS2_EE -_ZN6Magick10PathArcRelC1ERKSt4listINS_11PathArcArgsESaIS2_EE -_ZN6Magick10PathArcRelC2ERKS0_ -_ZN6Magick10PathArcRelC1ERKS0_ -_ZN6Magick10PathArcRelD2Ev -_ZN6Magick10PathArcRelD1Ev -_ZN6Magick10PathArcRelD0Ev -_ZNK6Magick10PathArcRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick10PathArcRel4copyEv -_ZN6Magick13PathClosePathD2Ev -_ZN6Magick13PathClosePathD1Ev -_ZN6Magick13PathClosePathD0Ev -_ZNK6Magick13PathClosePathclEPN9MagickLib12_DrawContextE -_ZNK6Magick13PathClosePath4copyEv -_ZN6Magick14PathCurvetoAbsC2ERKNS_15PathCurvetoArgsE -_ZN6Magick14PathCurvetoAbsC1ERKNS_15PathCurvetoArgsE -_ZN6Magick14PathCurvetoAbsC2ERKSt4listINS_15PathCurvetoArgsESaIS2_EE -_ZN6Magick14PathCurvetoAbsC1ERKSt4listINS_15PathCurvetoArgsESaIS2_EE -_ZN6Magick14PathCurvetoAbsC2ERKS0_ -_ZN6Magick14PathCurvetoAbsC1ERKS0_ -_ZN6Magick14PathCurvetoAbsD2Ev -_ZN6Magick14PathCurvetoAbsD1Ev -_ZN6Magick14PathCurvetoAbsD0Ev -_ZNK6Magick14PathCurvetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick14PathCurvetoAbs4copyEv -_ZN6Magick14PathCurvetoRelC2ERKNS_15PathCurvetoArgsE -_ZN6Magick14PathCurvetoRelC1ERKNS_15PathCurvetoArgsE -_ZN6Magick14PathCurvetoRelC2ERKSt4listINS_15PathCurvetoArgsESaIS2_EE -_ZN6Magick14PathCurvetoRelC1ERKSt4listINS_15PathCurvetoArgsESaIS2_EE -_ZN6Magick14PathCurvetoRelC2ERKS0_ -_ZN6Magick14PathCurvetoRelC1ERKS0_ -_ZN6Magick14PathCurvetoRelD2Ev -_ZN6Magick14PathCurvetoRelD1Ev -_ZN6Magick14PathCurvetoRelD0Ev -_ZNK6Magick14PathCurvetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick14PathCurvetoRel4copyEv -_ZN6Magick20PathSmoothCurvetoAbsC2ERKNS_10CoordinateE -_ZN6Magick20PathSmoothCurvetoAbsC1ERKNS_10CoordinateE -_ZN6Magick20PathSmoothCurvetoAbsC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick20PathSmoothCurvetoAbsC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick20PathSmoothCurvetoAbsC2ERKS0_ -_ZN6Magick20PathSmoothCurvetoAbsC1ERKS0_ -_ZN6Magick20PathSmoothCurvetoAbsD2Ev -_ZN6Magick20PathSmoothCurvetoAbsD1Ev -_ZN6Magick20PathSmoothCurvetoAbsD0Ev -_ZNK6Magick20PathSmoothCurvetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick20PathSmoothCurvetoAbs4copyEv -_ZN6Magick20PathSmoothCurvetoRelC2ERKNS_10CoordinateE -_ZN6Magick20PathSmoothCurvetoRelC1ERKNS_10CoordinateE -_ZN6Magick20PathSmoothCurvetoRelC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick20PathSmoothCurvetoRelC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick20PathSmoothCurvetoRelC2ERKS0_ -_ZN6Magick20PathSmoothCurvetoRelC1ERKS0_ -_ZN6Magick20PathSmoothCurvetoRelD2Ev -_ZN6Magick20PathSmoothCurvetoRelD1Ev -_ZN6Magick20PathSmoothCurvetoRelD0Ev -_ZNK6Magick20PathSmoothCurvetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick20PathSmoothCurvetoRel4copyEv -_ZN6Magick23PathQuadraticCurvetoAbsC2ERKNS_24PathQuadraticCurvetoArgsE -_ZN6Magick23PathQuadraticCurvetoAbsC1ERKNS_24PathQuadraticCurvetoArgsE -_ZN6Magick23PathQuadraticCurvetoAbsC2ERKSt4listINS_24PathQuadraticCurvetoArgsESaIS2_EE -_ZN6Magick23PathQuadraticCurvetoAbsC1ERKSt4listINS_24PathQuadraticCurvetoArgsESaIS2_EE -_ZN6Magick23PathQuadraticCurvetoAbsC2ERKS0_ -_ZN6Magick23PathQuadraticCurvetoAbsC1ERKS0_ -_ZN6Magick23PathQuadraticCurvetoAbsD2Ev -_ZN6Magick23PathQuadraticCurvetoAbsD1Ev -_ZN6Magick23PathQuadraticCurvetoAbsD0Ev -_ZNK6Magick23PathQuadraticCurvetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick23PathQuadraticCurvetoAbs4copyEv -_ZN6Magick23PathQuadraticCurvetoRelC2ERKNS_24PathQuadraticCurvetoArgsE -_ZN6Magick23PathQuadraticCurvetoRelC1ERKNS_24PathQuadraticCurvetoArgsE -_ZN6Magick23PathQuadraticCurvetoRelC2ERKSt4listINS_24PathQuadraticCurvetoArgsESaIS2_EE -_ZN6Magick23PathQuadraticCurvetoRelC1ERKSt4listINS_24PathQuadraticCurvetoArgsESaIS2_EE -_ZN6Magick23PathQuadraticCurvetoRelC2ERKS0_ -_ZN6Magick23PathQuadraticCurvetoRelC1ERKS0_ -_ZN6Magick23PathQuadraticCurvetoRelD2Ev -_ZN6Magick23PathQuadraticCurvetoRelD1Ev -_ZN6Magick23PathQuadraticCurvetoRelD0Ev -_ZNK6Magick23PathQuadraticCurvetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick23PathQuadraticCurvetoRel4copyEv -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC2ERKNS_10CoordinateE -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC1ERKNS_10CoordinateE -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC2ERKS0_ -_ZN6Magick29PathSmoothQuadraticCurvetoAbsC1ERKS0_ -_ZN6Magick29PathSmoothQuadraticCurvetoAbsD2Ev -_ZN6Magick29PathSmoothQuadraticCurvetoAbsD1Ev -_ZN6Magick29PathSmoothQuadraticCurvetoAbsD0Ev -_ZNK6Magick29PathSmoothQuadraticCurvetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick29PathSmoothQuadraticCurvetoAbs4copyEv -_ZN6Magick29PathSmoothQuadraticCurvetoRelC2ERKNS_10CoordinateE -_ZN6Magick29PathSmoothQuadraticCurvetoRelC1ERKNS_10CoordinateE -_ZN6Magick29PathSmoothQuadraticCurvetoRelC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick29PathSmoothQuadraticCurvetoRelC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick29PathSmoothQuadraticCurvetoRelC2ERKS0_ -_ZN6Magick29PathSmoothQuadraticCurvetoRelC1ERKS0_ -_ZN6Magick29PathSmoothQuadraticCurvetoRelD2Ev -_ZN6Magick29PathSmoothQuadraticCurvetoRelD1Ev -_ZN6Magick29PathSmoothQuadraticCurvetoRelD0Ev -_ZNK6Magick29PathSmoothQuadraticCurvetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick29PathSmoothQuadraticCurvetoRel4copyEv -_ZN6Magick13PathLinetoAbsC2ERKNS_10CoordinateE -_ZN6Magick13PathLinetoAbsC1ERKNS_10CoordinateE -_ZN6Magick13PathLinetoAbsC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathLinetoAbsC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathLinetoAbsC2ERKS0_ -_ZN6Magick13PathLinetoAbsC1ERKS0_ -_ZN6Magick13PathLinetoAbsD2Ev -_ZN6Magick13PathLinetoAbsD1Ev -_ZN6Magick13PathLinetoAbsD0Ev -_ZNK6Magick13PathLinetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick13PathLinetoAbs4copyEv -_ZN6Magick13PathLinetoRelC2ERKNS_10CoordinateE -_ZN6Magick13PathLinetoRelC1ERKNS_10CoordinateE -_ZN6Magick13PathLinetoRelC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathLinetoRelC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathLinetoRelC2ERKS0_ -_ZN6Magick13PathLinetoRelC1ERKS0_ -_ZN6Magick13PathLinetoRelD2Ev -_ZN6Magick13PathLinetoRelD1Ev -_ZN6Magick13PathLinetoRelD0Ev -_ZNK6Magick13PathLinetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick13PathLinetoRel4copyEv -_ZN6Magick23PathLinetoHorizontalAbsD2Ev -_ZN6Magick23PathLinetoHorizontalAbsD1Ev -_ZN6Magick23PathLinetoHorizontalAbsD0Ev -_ZNK6Magick23PathLinetoHorizontalAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick23PathLinetoHorizontalAbs4copyEv -_ZN6Magick23PathLinetoHorizontalRelD2Ev -_ZN6Magick23PathLinetoHorizontalRelD1Ev -_ZN6Magick23PathLinetoHorizontalRelD0Ev -_ZNK6Magick23PathLinetoHorizontalRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick23PathLinetoHorizontalRel4copyEv -_ZN6Magick21PathLinetoVerticalAbsD2Ev -_ZN6Magick21PathLinetoVerticalAbsD1Ev -_ZN6Magick21PathLinetoVerticalAbsD0Ev -_ZNK6Magick21PathLinetoVerticalAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick21PathLinetoVerticalAbs4copyEv -_ZN6Magick21PathLinetoVerticalRelD2Ev -_ZN6Magick21PathLinetoVerticalRelD1Ev -_ZN6Magick21PathLinetoVerticalRelD0Ev -_ZNK6Magick21PathLinetoVerticalRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick21PathLinetoVerticalRel4copyEv -_ZN6Magick13PathMovetoAbsC2ERKNS_10CoordinateE -_ZN6Magick13PathMovetoAbsC1ERKNS_10CoordinateE -_ZN6Magick13PathMovetoAbsC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathMovetoAbsC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathMovetoAbsC2ERKS0_ -_ZN6Magick13PathMovetoAbsC1ERKS0_ -_ZN6Magick13PathMovetoAbsD2Ev -_ZN6Magick13PathMovetoAbsD1Ev -_ZN6Magick13PathMovetoAbsD0Ev -_ZNK6Magick13PathMovetoAbsclEPN9MagickLib12_DrawContextE -_ZNK6Magick13PathMovetoAbs4copyEv -_ZN6Magick13PathMovetoRelC2ERKNS_10CoordinateE -_ZN6Magick13PathMovetoRelC1ERKNS_10CoordinateE -_ZN6Magick13PathMovetoRelC2ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathMovetoRelC1ERKSt4listINS_10CoordinateESaIS2_EE -_ZN6Magick13PathMovetoRelC2ERKS0_ -_ZN6Magick13PathMovetoRelC1ERKS0_ -_ZN6Magick13PathMovetoRelD2Ev -_ZN6Magick13PathMovetoRelD1Ev -_ZN6Magick13PathMovetoRelD0Ev -_ZNK6Magick13PathMovetoRelclEPN9MagickLib12_DrawContextE -_ZNK6Magick13PathMovetoRel4copyEv -_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EE5clearEv -_ZNSt4listIN6Magick10CoordinateESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSt10_List_baseIN6Magick5VPathESaIS1_EE5clearEv -_ZNSt4listIN6Magick5VPathESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EE5clearEv -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EE5clearEv -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSt4listIN6Magick10CoordinateESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE5clearEv -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_ -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZN6Magick10CoordinateD1Ev -_ZN6Magick10CoordinateD0Ev -_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EED2Ev -_ZSt10__distanceISt14_List_iteratorIN6Magick10CoordinateERKS2_PS3_EENSt15iterator_traitsIT_E15difference_typeES8_S8_St18input_iterator_tag -_ZNSt10_List_baseIN6Magick5VPathESaIS1_EED2Ev -_ZNSt14__simple_allocISt10_List_nodeIN6Magick5VPathEESt24__default_alloc_templateILb1ELi0EEE10deallocateEPS3_j -_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EED2Ev -_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EED2Ev -_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EED2Ev -_ZNSt4listIN6Magick10CoordinateESaIS1_EE14_M_create_nodeERKS1_ -_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_ -_ZN6Magick9ExceptionC2ERKSs -_ZN6Magick9ExceptionC1ERKSs -_ZN6Magick9ExceptionC2ERKS0_ -_ZN6Magick9ExceptionC1ERKS0_ -_ZN6Magick9ExceptionaSERKS0_ -_ZNK6Magick9Exception4whatEv -_ZN6Magick7WarningC2ERKSs -_ZN6Magick7WarningC1ERKSs -_ZN6Magick16WarningUndefinedC2ERKSs -_ZN6Magick16WarningUndefinedC1ERKSs -_ZN6Magick20WarningResourceLimitC2ERKSs -_ZN6Magick20WarningResourceLimitC1ERKSs -_ZN6Magick14WarningXServerC2ERKSs -_ZN6Magick14WarningXServerC1ERKSs -_ZN6Magick13WarningOptionC2ERKSs -_ZN6Magick13WarningOptionC1ERKSs -_ZN6Magick15WarningDelegateC2ERKSs -_ZN6Magick15WarningDelegateC1ERKSs -_ZN6Magick22WarningMissingDelegateC2ERKSs -_ZN6Magick22WarningMissingDelegateC1ERKSs -_ZN6Magick19WarningCorruptImageC2ERKSs -_ZN6Magick19WarningCorruptImageC1ERKSs -_ZN6Magick15WarningFileOpenC2ERKSs -_ZN6Magick15WarningFileOpenC1ERKSs -_ZN6Magick11WarningBlobC2ERKSs -_ZN6Magick11WarningBlobC1ERKSs -_ZN6Magick12WarningCacheC2ERKSs -_ZN6Magick12WarningCacheC1ERKSs -_ZN6Magick5ErrorC2ERKSs -_ZN6Magick5ErrorC1ERKSs -_ZN6Magick14ErrorUndefinedC2ERKSs -_ZN6Magick14ErrorUndefinedC1ERKSs -_ZN6Magick18ErrorResourceLimitC2ERKSs -_ZN6Magick18ErrorResourceLimitC1ERKSs -_ZN6Magick12ErrorXServerC2ERKSs -_ZN6Magick12ErrorXServerC1ERKSs -_ZN6Magick11ErrorOptionC2ERKSs -_ZN6Magick11ErrorOptionC1ERKSs -_ZN6Magick13ErrorDelegateC2ERKSs -_ZN6Magick13ErrorDelegateC1ERKSs -_ZN6Magick20ErrorMissingDelegateC2ERKSs -_ZN6Magick20ErrorMissingDelegateC1ERKSs -_ZN6Magick17ErrorCorruptImageC2ERKSs -_ZN6Magick17ErrorCorruptImageC1ERKSs -_ZN6Magick13ErrorFileOpenC2ERKSs -_ZN6Magick13ErrorFileOpenC1ERKSs -_ZN6Magick9ErrorBlobC2ERKSs -_ZN6Magick9ErrorBlobC1ERKSs -_ZN6Magick10ErrorCacheC2ERKSs -_ZN6Magick10ErrorCacheC1ERKSs -_ZN6Magick22throwExceptionExplicitEN9MagickLib13ExceptionTypeEPKcS3_ -_ZN6Magick14throwExceptionERN9MagickLib14_ExceptionInfoE -_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_EPKS3_RKS6_ -_ZN6Magick16WarningUndefinedD1Ev -_ZN6Magick16WarningUndefinedD0Ev -_ZN6Magick9ExceptionD1Ev -_ZN6Magick9ExceptionD0Ev -_ZN6Magick7WarningD0Ev -_ZN6Magick7WarningD1Ev -_ZN6Magick20WarningResourceLimitD0Ev -_ZN6Magick20WarningResourceLimitD1Ev -_ZN6Magick14WarningXServerD0Ev -_ZN6Magick14WarningXServerD1Ev -_ZN6Magick13WarningOptionD0Ev -_ZN6Magick13WarningOptionD1Ev -_ZN6Magick15WarningDelegateD0Ev -_ZN6Magick15WarningDelegateD1Ev -_ZN6Magick22WarningMissingDelegateD0Ev -_ZN6Magick22WarningMissingDelegateD1Ev -_ZN6Magick19WarningCorruptImageD0Ev -_ZN6Magick19WarningCorruptImageD1Ev -_ZN6Magick15WarningFileOpenD0Ev -_ZN6Magick15WarningFileOpenD1Ev -_ZN6Magick11WarningBlobD0Ev -_ZN6Magick11WarningBlobD1Ev -_ZN6Magick12WarningCacheD0Ev -_ZN6Magick12WarningCacheD1Ev -_ZN6Magick5ErrorD0Ev -_ZN6Magick5ErrorD1Ev -_ZN6Magick14ErrorUndefinedD0Ev -_ZN6Magick14ErrorUndefinedD1Ev -_ZN6Magick18ErrorResourceLimitD0Ev -_ZN6Magick18ErrorResourceLimitD1Ev -_ZN6Magick12ErrorXServerD0Ev -_ZN6Magick12ErrorXServerD1Ev -_ZN6Magick11ErrorOptionD0Ev -_ZN6Magick11ErrorOptionD1Ev -_ZN6Magick13ErrorDelegateD0Ev -_ZN6Magick13ErrorDelegateD1Ev -_ZN6Magick20ErrorMissingDelegateD0Ev -_ZN6Magick20ErrorMissingDelegateD1Ev -_ZN6Magick17ErrorCorruptImageD0Ev -_ZN6Magick17ErrorCorruptImageD1Ev -_ZN6Magick13ErrorFileOpenD0Ev -_ZN6Magick13ErrorFileOpenD1Ev -_ZN6Magick9ErrorBlobD0Ev -_ZN6Magick9ErrorBlobD1Ev -_ZN6Magick10ErrorCacheD0Ev -_ZN6Magick10ErrorCacheD1Ev -_ZN6Magick11CloneStringEPPcRKSs -_ZN6MagickeqERKNS_8GeometryES2_ -_ZN6MagickneERKNS_8GeometryES2_ -_ZN6MagickgtERKNS_8GeometryES2_ -_ZN6MagickltERKNS_8GeometryES2_ -_ZN6MagickgeERKNS_8GeometryES2_ -_ZN6MagickleERKNS_8GeometryES2_ -_ZN6Magick8GeometryC2Ejjjjbb -_ZN6Magick8GeometryC1Ejjjjbb -_ZN6Magick8GeometryC2ERKSs -_ZN6Magick8GeometryC1ERKSs -_ZN6Magick8GeometryC2EPKc -_ZN6Magick8GeometryC1EPKc -_ZN6Magick8GeometryC2ERKS0_ -_ZN6Magick8GeometryC1ERKS0_ -_ZN6Magick8GeometryC2Ev -_ZN6Magick8GeometryC1Ev -_ZN6Magick8GeometryD2Ev -_ZN6Magick8GeometryD1Ev -_ZN6Magick8GeometryaSERKS0_ -_ZN6Magick8GeometryaSERKSs -_ZN6Magick8GeometryaSEPKc -_ZNK6Magick8GeometrycvSsEv -_ZN6Magick8GeometryC2ERKN9MagickLib14_RectangleInfoE -_ZN6Magick8GeometryC1ERKN9MagickLib14_RectangleInfoE -_ZNK6Magick8GeometrycvN9MagickLib14_RectangleInfoEEv -_ZN6MagickeqERKNS_5ImageES2_ -_ZN6MagickneERKNS_5ImageES2_ -_ZN6MagickgtERKNS_5ImageES2_ -_ZN6MagickltERKNS_5ImageES2_ -_ZN6MagickgeERKNS_5ImageES2_ -_ZN6MagickleERKNS_5ImageES2_ -_ZN6Magick5ImageC2ERKSs -_ZN6Magick5ImageC1ERKSs -_ZN6Magick5ImageC2ERKNS_8GeometryERKNS_5ColorE -_ZN6Magick5ImageC1ERKNS_8GeometryERKNS_5ColorE -_ZN6Magick5ImageC2ERKNS_4BlobE -_ZN6Magick5ImageC1ERKNS_4BlobE -_ZN6Magick5ImageC2ERKNS_4BlobERKNS_8GeometryE -_ZN6Magick5ImageC1ERKNS_4BlobERKNS_8GeometryE -_ZN6Magick5ImageC2ERKNS_4BlobERKNS_8GeometryEj -_ZN6Magick5ImageC1ERKNS_4BlobERKNS_8GeometryEj -_ZN6Magick5ImageC2ERKNS_4BlobERKNS_8GeometryEjRKSs -_ZN6Magick5ImageC1ERKNS_4BlobERKNS_8GeometryEjRKSs -_ZN6Magick5ImageC2ERKNS_4BlobERKNS_8GeometryERKSs -_ZN6Magick5ImageC1ERKNS_4BlobERKNS_8GeometryERKSs -_ZN6Magick5ImageC2EjjRKSsN9MagickLib11StorageTypeEPKv -_ZN6Magick5ImageC1EjjRKSsN9MagickLib11StorageTypeEPKv -_ZN6Magick5ImageC2Ev -_ZN6Magick5ImageC1Ev -_ZN6Magick5ImageD2Ev -_ZN6Magick5ImageD1Ev -_ZN6Magick5ImageD0Ev -_ZN6Magick5Image8addNoiseEN9MagickLib9NoiseTypeE -_ZN6Magick5Image8annotateERKSsRKNS_8GeometryE -_ZN6Magick5Image8annotateERKSsRKNS_8GeometryEN9MagickLib11GravityTypeE -_ZN6Magick5Image8annotateERKSsRKNS_8GeometryEN9MagickLib11GravityTypeEd -_ZN6Magick5Image8annotateERKSsN9MagickLib11GravityTypeE -_ZN6Magick5Image4blurEdd -_ZN6Magick5Image6borderERKNS_8GeometryE -_ZN6Magick5Image7channelEN9MagickLib11ChannelTypeE -_ZN6Magick5Image8charcoalEdd -_ZN6Magick5Image4chopERKNS_8GeometryE -_ZN6Magick5Image8colorizeEjjjRKNS_5ColorE -_ZN6Magick5Image8colorizeEjRKNS_5ColorE -_ZN6Magick5Image9compositeERKS0_iiN9MagickLib17CompositeOperatorE -_ZN6Magick5Image9compositeERKS0_RKNS_8GeometryEN9MagickLib17CompositeOperatorE -_ZN6Magick5Image9compositeERKS0_N9MagickLib11GravityTypeENS3_17CompositeOperatorE -_ZN6Magick5Image8contrastEj -_ZN6Magick5Image8convolveEjPKd -_ZN6Magick5Image4cropERKNS_8GeometryE -_ZN6Magick5Image13cycleColormapEi -_ZN6Magick5Image9despeckleEv -_ZN6Magick5Image7displayEv -_ZN6Magick5Image4drawERKNS_8DrawableE -_ZN6Magick5Image4drawERKSt4listINS_8DrawableESaIS2_EE -_ZN6Magick5Image4edgeEd -_ZN6Magick5Image6embossEdd -_ZN6Magick5Image7enhanceEv -_ZN6Magick5Image8equalizeEv -_ZN6Magick5Image5eraseEv -_ZN6Magick5Image4flipEv -_ZN6Magick5Image14floodFillColorEjjRKNS_5ColorE -_ZN6Magick5Image14floodFillColorERKNS_8GeometryERKNS_5ColorE -_ZN6Magick5Image14floodFillColorEjjRKNS_5ColorES3_ -_ZN6Magick5Image14floodFillColorERKNS_8GeometryERKNS_5ColorES6_ -_ZN6Magick5Image16floodFillOpacityEjjjN9MagickLib11PaintMethodE -_ZN6Magick5Image16floodFillTextureEjjRKS0_ -_ZN6Magick5Image16floodFillTextureERKNS_8GeometryERKS0_ -_ZN6Magick5Image16floodFillTextureEjjRKS0_RKNS_5ColorE -_ZN6Magick5Image16floodFillTextureERKNS_8GeometryERKS0_RKNS_5ColorE -_ZN6Magick5Image4flopEv -_ZN6Magick5Image5frameERKNS_8GeometryE -_ZN6Magick5Image5frameEjjii -_ZN6Magick5Image5gammaEd -_ZN6Magick5Image5gammaEddd -_ZN6Magick5Image12gaussianBlurEdd -_ZN6Magick5Image7implodeEd -_ZN6Magick5Image7magnifyEv -_ZN6Magick5Image3mapERKS0_b -_ZN6Magick5Image14matteFloodfillERKNS_5ColorEjiiN9MagickLib11PaintMethodE -_ZN6Magick5Image12medianFilterEd -_ZN6Magick5Image6minifyEv -_ZN6Magick5Image8modulateEddd -_ZN6Magick5Image6negateEb -_ZN6Magick5Image9normalizeEv -_ZN6Magick5Image8oilPaintEd -_ZN6Magick5Image7opacityEj -_ZN6Magick5Image6opaqueERKNS_5ColorES3_ -_ZN6Magick5Image4pingERKSs -_ZN6Magick5Image4pingERKNS_4BlobE -_ZN6Magick5Image8quantizeEb -_ZN6Magick5Image5raiseERKNS_8GeometryEb -_ZN6Magick5Image4readERKSs -_ZN6Magick5Image4readERKNS_8GeometryERKSs -_ZN6Magick5Image4readERKNS_4BlobE -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryE -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryEj -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryEjRKSs -_ZN6Magick5Image4readERKNS_4BlobERKNS_8GeometryERKSs -_ZN6Magick5Image4readEjjRKSsN9MagickLib11StorageTypeEPKv -_ZN6Magick5Image11reduceNoiseEd -_ZN6Magick5Image4rollERKNS_8GeometryE -_ZN6Magick5Image4rollEjj -_ZN6Magick5Image6rotateEd -_ZN6Magick5Image6sampleERKNS_8GeometryE -_ZN6Magick5Image5scaleERKNS_8GeometryE -_ZN6Magick5Image7segmentEdd -_ZN6Magick5Image5shadeEddb -_ZN6Magick5Image7sharpenEdd -_ZN6Magick5Image5shaveERKNS_8GeometryE -_ZN6Magick5Image5shearEdd -_ZN6Magick5Image8solarizeEd -_ZN6Magick5Image6spreadEj -_ZN6Magick5Image7steganoERKS0_ -_ZN6Magick5Image6stereoERKS0_ -_ZN6Magick5Image5swirlEd -_ZN6Magick5Image7textureERKS0_ -_ZN6Magick5Image9thresholdEd -_ZN6Magick5Image9transformERKNS_8GeometryE -_ZN6Magick5Image9transformERKNS_8GeometryES3_ -_ZN6Magick5Image11transparentERKNS_5ColorE -_ZN6Magick5Image4trimEv -_ZN6Magick5Image11unsharpmaskEdddd -_ZN6Magick5Image4waveEdd -_ZN6Magick5Image5writeERKSs -_ZN6Magick5Image5writeEPNS_4BlobE -_ZN6Magick5Image5writeEPNS_4BlobERKSs -_ZN6Magick5Image5writeEPNS_4BlobERKSsj -_ZN6Magick5Image5writeEiijjRKSsN9MagickLib11StorageTypeEPv -_ZN6Magick5Image4zoomERKNS_8GeometryE -_ZN6Magick5Image6adjoinEb -_ZNK6Magick5Image6adjoinEv -_ZN6Magick5Image9antiAliasEb -_ZN6Magick5Image9antiAliasEv -_ZN6Magick5Image14animationDelayEj -_ZNK6Magick5Image14animationDelayEv -_ZN6Magick5Image19animationIterationsEj -_ZNK6Magick5Image19animationIterationsEv -_ZN6Magick5Image15backgroundColorERKNS_5ColorE -_ZNK6Magick5Image15backgroundColorEv -_ZN6Magick5Image17backgroundTextureERKSs -_ZNK6Magick5Image17backgroundTextureEv -_ZNK6Magick5Image11baseColumnsEv -_ZNK6Magick5Image12baseFilenameEv -_ZNK6Magick5Image8baseRowsEv -_ZN6Magick5Image11borderColorERKNS_5ColorE -_ZNK6Magick5Image11borderColorEv -_ZNK6Magick5Image11boundingBoxEv -_ZN6Magick5Image8boxColorERKNS_5ColorE -_ZNK6Magick5Image8boxColorEv -_ZN6Magick5Image14cacheThresholdEj -_ZN6Magick5Image17chromaBluePrimaryEdd -_ZNK6Magick5Image17chromaBluePrimaryEPdS1_ -_ZN6Magick5Image18chromaGreenPrimaryEdd -_ZNK6Magick5Image18chromaGreenPrimaryEPdS1_ -_ZN6Magick5Image16chromaRedPrimaryEdd -_ZNK6Magick5Image16chromaRedPrimaryEPdS1_ -_ZN6Magick5Image16chromaWhitePointEdd -_ZNK6Magick5Image16chromaWhitePointEPdS1_ -_ZN6Magick5Image9classTypeEN9MagickLib9ClassTypeE -_ZN6Magick5Image8clipMaskERKS0_ -_ZNK6Magick5Image8clipMaskEv -_ZN6Magick5Image9colorFuzzEd -_ZNK6Magick5Image9colorFuzzEv -_ZN6Magick5Image8colorMapEjRKNS_5ColorE -_ZNK6Magick5Image8colorMapEj -_ZN6Magick5Image10colorSpaceEN9MagickLib14ColorspaceTypeE -_ZNK6Magick5Image10colorSpaceEv -_ZN6Magick5Image7commentERKSs -_ZNK6Magick5Image7commentEv -_ZN6Magick5Image12compressTypeEN9MagickLib15CompressionTypeE -_ZNK6Magick5Image12compressTypeEv -_ZN6Magick5Image5debugEb -_ZNK6Magick5Image5debugEv -_ZN6Magick5Image7densityERKNS_8GeometryE -_ZNK6Magick5Image7densityEv -_ZN6Magick5Image5depthEj -_ZNK6Magick5Image5depthEv -_ZNK6Magick5Image9directoryEv -_ZN6Magick5Image6endianEN9MagickLib10EndianTypeE -_ZNK6Magick5Image6endianEv -_ZN6Magick5Image8fileNameERKSs -_ZNK6Magick5Image8fileNameEv -_ZNK6Magick5Image8fileSizeEv -_ZN6Magick5Image9fillColorERKNS_5ColorE -_ZNK6Magick5Image9fillColorEv -_ZN6Magick5Image8fillRuleERKN9MagickLib8FillRuleE -_ZNK6Magick5Image8fillRuleEv -_ZN6Magick5Image11fillPatternERKS0_ -_ZNK6Magick5Image11fillPatternEv -_ZN6Magick5Image10filterTypeEN9MagickLib11FilterTypesE -_ZNK6Magick5Image10filterTypeEv -_ZN6Magick5Image4fontERKSs -_ZNK6Magick5Image4fontEv -_ZN6Magick5Image13fontPointsizeEd -_ZNK6Magick5Image13fontPointsizeEv -_ZN6Magick5Image15fontTypeMetricsERKSsPNS_10TypeMetricE -_ZNK6Magick5Image6formatEv -_ZNK6Magick5Image5gammaEv -_ZNK6Magick5Image8geometryEv -_ZN6Magick5Image16gifDisposeMethodEj -_ZNK6Magick5Image16gifDisposeMethodEv -_ZN6Magick5Image15iccColorProfileERKNS_4BlobE -_ZNK6Magick5Image15iccColorProfileEv -_ZN6Magick5Image13interlaceTypeEN9MagickLib13InterlaceTypeE -_ZNK6Magick5Image13interlaceTypeEv -_ZN6Magick5Image11iptcProfileERKNS_4BlobE -_ZNK6Magick5Image11iptcProfileEv -_ZN6Magick5Image7isValidEb -_ZNK6Magick5Image7isValidEv -_ZN6Magick5Image5labelERKSs -_ZNK6Magick5Image5labelEv -_ZN6Magick5Image6magickERKSs -_ZNK6Magick5Image6magickEv -_ZN6Magick5Image5matteEb -_ZNK6Magick5Image5matteEv -_ZN6Magick5Image10matteColorERKNS_5ColorE -_ZNK6Magick5Image10matteColorEv -_ZNK6Magick5Image17meanErrorPerPixelEv -_ZN6Magick5Image10monochromeEb -_ZNK6Magick5Image10monochromeEv -_ZNK6Magick5Image15montageGeometryEv -_ZNK6Magick5Image18normalizedMaxErrorEv -_ZNK6Magick5Image19normalizedMeanErrorEv -_ZN6Magick5Image8penColorERKNS_5ColorE -_ZNK6Magick5Image8penColorEv -_ZN6Magick5Image10penTextureERKS0_ -_ZNK6Magick5Image10penTextureEv -_ZN6Magick5Image10pixelColorEjjRKNS_5ColorE -_ZNK6Magick5Image10pixelColorEjj -_ZN6Magick5Image4pageERKNS_8GeometryE -_ZNK6Magick5Image4pageEv -_ZN6Magick5Image7qualityEj -_ZNK6Magick5Image7qualityEv -_ZN6Magick5Image14quantizeColorsEj -_ZNK6Magick5Image14quantizeColorsEv -_ZN6Magick5Image18quantizeColorSpaceEN9MagickLib14ColorspaceTypeE -_ZNK6Magick5Image18quantizeColorSpaceEv -_ZN6Magick5Image14quantizeDitherEb -_ZNK6Magick5Image14quantizeDitherEv -_ZN6Magick5Image17quantizeTreeDepthEj -_ZNK6Magick5Image17quantizeTreeDepthEv -_ZN6Magick5Image15renderingIntentEN9MagickLib15RenderingIntentE -_ZNK6Magick5Image15renderingIntentEv -_ZN6Magick5Image15resolutionUnitsEN9MagickLib14ResolutionTypeE -_ZNK6Magick5Image15resolutionUnitsEv -_ZN6Magick5Image5sceneEj -_ZNK6Magick5Image5sceneEv -_ZNK6Magick5Image9signatureEb -_ZN6Magick5Image4sizeERKNS_8GeometryE -_ZNK6Magick5Image4sizeEv -_ZN6Magick5Image15strokeAntiAliasEb -_ZNK6Magick5Image15strokeAntiAliasEv -_ZN6Magick5Image11strokeColorERKNS_5ColorE -_ZNK6Magick5Image11strokeColorEv -_ZN6Magick5Image15strokeDashArrayEPKd -_ZNK6Magick5Image15strokeDashArrayEv -_ZN6Magick5Image16strokeDashOffsetEd -_ZNK6Magick5Image16strokeDashOffsetEv -_ZN6Magick5Image13strokeLineCapEN9MagickLib7LineCapE -_ZNK6Magick5Image13strokeLineCapEv -_ZN6Magick5Image14strokeLineJoinEN9MagickLib8LineJoinE -_ZNK6Magick5Image14strokeLineJoinEv -_ZN6Magick5Image16strokeMiterLimitEj -_ZNK6Magick5Image16strokeMiterLimitEv -_ZN6Magick5Image13strokePatternERKS0_ -_ZNK6Magick5Image13strokePatternEv -_ZN6Magick5Image11strokeWidthEd -_ZNK6Magick5Image11strokeWidthEv -_ZN6Magick5Image8subImageEj -_ZNK6Magick5Image8subImageEv -_ZN6Magick5Image8subRangeEj -_ZNK6Magick5Image8subRangeEv -_ZN6Magick5Image8tileNameERKSs -_ZNK6Magick5Image8tileNameEv -_ZN6Magick5Image11totalColorsEv -_ZN6Magick5Image15transformOriginEdd -_ZN6Magick5Image17transformRotationEd -_ZN6Magick5Image14transformResetEv -_ZN6Magick5Image14transformScaleEdd -_ZN6Magick5Image14transformSkewXEd -_ZN6Magick5Image14transformSkewYEd -_ZNK6Magick5Image4typeEv -_ZN6Magick5Image4typeEN9MagickLib9ImageTypeE -_ZN6Magick5Image7verboseEb -_ZNK6Magick5Image7verboseEv -_ZN6Magick5Image4viewERKSs -_ZNK6Magick5Image4viewEv -_ZN6Magick5Image10x11DisplayERKSs -_ZNK6Magick5Image10x11DisplayEv -_ZNK6Magick5Image11xResolutionEv -_ZNK6Magick5Image11yResolutionEv -_ZN6Magick5ImageC2ERKS0_ -_ZN6Magick5ImageC1ERKS0_ -_ZN6Magick5ImageaSERKS0_ -_ZNK6Magick5Image14getConstPixelsEiijj -_ZNK6Magick5Image15getConstIndexesEv -_ZNK6Magick5Image10getIndexesEv -_ZN6Magick5Image9getPixelsEiijj -_ZN6Magick5Image9setPixelsEiijj -_ZN6Magick5Image10syncPixelsEv -_ZN6Magick5Image10readPixelsEN9MagickLib11QuantumTypeEPKh -_ZN6Magick5Image11writePixelsEN9MagickLib11QuantumTypeEPh -_ZN6Magick5ImageC2EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZN6Magick5ImageC1EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZN6Magick5Image12replaceImageEPN9MagickLib6_ImageE -_ZN6Magick5Image11modifyImageEv -_ZNK6Magick5Image19throwImageExceptionEv -_ZN6Magick5Image10registerIdEv -_ZN6Magick5Image12unregisterIdEv -_ZN6Magick8ImageRefC2EPN9MagickLib6_ImageE -_ZN6Magick8ImageRefC1EPN9MagickLib6_ImageE -_ZN6Magick8ImageRefC2EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZN6Magick8ImageRefC1EPN9MagickLib6_ImageEPKNS_7OptionsE -_ZN6Magick8ImageRefC2Ev -_ZN6Magick8ImageRefC1Ev -_ZN6Magick8ImageRefD2Ev -_ZN6Magick8ImageRefD1Ev -_ZN6Magick8ImageRef5imageEPN9MagickLib6_ImageE -_ZN6Magick8ImageRef7optionsEPNS_7OptionsE -_ZN6Magick8ImageRef2idEl -_ZN6Magick13MagickCleanUpC2Ev -_ZN6Magick13MagickCleanUpC1Ev -_ZN6Magick13MagickCleanUpD2Ev -_ZN6Magick13MagickCleanUpD1Ev -_Z41__static_initialization_and_destruction_0ii -_ZN6Magick7MontageC2Ev -_ZN6Magick7MontageC1Ev -_ZN6Magick13MontageFramedC2Ev -_ZN6Magick13MontageFramedC1Ev -_ZNK6Magick7Montage17updateMontageInfoERN9MagickLib12_MontageInfoE -_ZNK6Magick13MontageFramed17updateMontageInfoERN9MagickLib12_MontageInfoE -_ZN6Magick7MontageD1Ev -_ZN6Magick7MontageD0Ev -_ZN6Magick13MontageFramedD1Ev -_ZN6Magick13MontageFramedD0Ev -_ZN6Magick7OptionsC2Ev -_ZN6Magick7OptionsC1Ev -_ZN6Magick7OptionsC2ERKS0_ -_ZN6Magick7OptionsC1ERKS0_ -_ZN6Magick7OptionsC2EPKN9MagickLib10_ImageInfoEPKNS1_13_QuantizeInfoEPKNS1_9_DrawInfoE -_ZN6Magick7OptionsC1EPKN9MagickLib10_ImageInfoEPKNS1_13_QuantizeInfoEPKNS1_9_DrawInfoE -_ZN6Magick7OptionsD2Ev -_ZN6Magick7OptionsD1Ev -_ZN6Magick7Options15backgroundColorERKNS_5ColorE -_ZNK6Magick7Options15backgroundColorEv -_ZN6Magick7Options17backgroundTextureERKSs -_ZNK6Magick7Options17backgroundTextureEv -_ZN6Magick7Options11borderColorERKNS_5ColorE -_ZNK6Magick7Options11borderColorEv -_ZN6Magick7Options8boxColorERKNS_5ColorE -_ZNK6Magick7Options8boxColorEv -_ZN6Magick7Options5debugEb -_ZNK6Magick7Options5debugEv -_ZN6Magick7Options7densityERKNS_8GeometryE -_ZNK6Magick7Options7densityEv -_ZN6Magick7Options6endianEN9MagickLib10EndianTypeE -_ZNK6Magick7Options6endianEv -_ZN6Magick7Options8fileNameERKSs -_ZNK6Magick7Options8fileNameEv -_ZN6Magick7Options9fillColorERKNS_5ColorE -_ZNK6Magick7Options9fillColorEv -_ZN6Magick7Options11fillPatternEPKN9MagickLib6_ImageE -_ZNK6Magick7Options11fillPatternEv -_ZN6Magick7Options8fillRuleERKN9MagickLib8FillRuleE -_ZNK6Magick7Options8fillRuleEv -_ZN6Magick7Options4fontERKSs -_ZNK6Magick7Options4fontEv -_ZNK6Magick7Options6formatEv -_ZN6Magick7Options6magickERKSs -_ZNK6Magick7Options6magickEv -_ZN6Magick7Options10matteColorERKNS_5ColorE -_ZNK6Magick7Options10matteColorEv -_ZN6Magick7Options4pageERKNS_8GeometryE -_ZNK6Magick7Options4pageEv -_ZN6Magick7Options15resolutionUnitsEN9MagickLib14ResolutionTypeE -_ZNK6Magick7Options15resolutionUnitsEv -_ZN6Magick7Options4sizeERKNS_8GeometryE -_ZNK6Magick7Options4sizeEv -_ZN6Magick7Options11strokeColorERKNS_5ColorE -_ZNK6Magick7Options11strokeColorEv -_ZN6Magick7Options15strokeDashArrayEPKd -_ZNK6Magick7Options15strokeDashArrayEv -_ZN6Magick7Options13strokePatternEPKN9MagickLib6_ImageE -_ZNK6Magick7Options13strokePatternEv -_ZN6Magick7Options8tileNameERKSs -_ZNK6Magick7Options8tileNameEv -_ZN6Magick7Options15transformOriginEdd -_ZN6Magick7Options14transformResetEv -_ZN6Magick7Options17transformRotationEd -_ZN6Magick7Options14transformScaleEdd -_ZN6Magick7Options14transformSkewXEd -_ZN6Magick7Options14transformSkewYEd -_ZN6Magick7Options4viewERKSs -_ZNK6Magick7Options4viewEv -_ZN6Magick7Options10x11DisplayERKSs -_ZNK6Magick7Options10x11DisplayEv -_ZN6Magick6PixelsC2ERNS_5ImageE -_ZN6Magick6PixelsC1ERNS_5ImageE -_ZN6Magick6PixelsD2Ev -_ZN6Magick6PixelsD1Ev -_ZN6Magick6Pixels3getEiijj -_ZN6Magick6Pixels8getConstEiijj -_ZN6Magick6Pixels4syncEv -_ZN6Magick6Pixels3setEiijj -_ZN6Magick6Pixels7indexesEv -_ZN6Magick13addNoiseImageC2EN9MagickLib9NoiseTypeE -_ZN6Magick13addNoiseImageC1EN9MagickLib9NoiseTypeE -_ZNK6Magick13addNoiseImageclERNS_5ImageE -_ZN6Magick13annotateImageC2ERKSsRKNS_8GeometryE -_ZN6Magick13annotateImageC1ERKSsRKNS_8GeometryE -_ZN6Magick13annotateImageC2ERKSsRKNS_8GeometryEN9MagickLib11GravityTypeE -_ZN6Magick13annotateImageC1ERKSsRKNS_8GeometryEN9MagickLib11GravityTypeE -_ZN6Magick13annotateImageC2ERKSsRKNS_8GeometryEN9MagickLib11GravityTypeEd -_ZN6Magick13annotateImageC1ERKSsRKNS_8GeometryEN9MagickLib11GravityTypeEd -_ZN6Magick13annotateImageC2ERKSsN9MagickLib11GravityTypeE -_ZN6Magick13annotateImageC1ERKSsN9MagickLib11GravityTypeE -_ZNK6Magick13annotateImageclERNS_5ImageE -_ZN6Magick9blurImageC2Edd -_ZN6Magick9blurImageC1Edd -_ZNK6Magick9blurImageclERNS_5ImageE -_ZN6Magick11borderImageC2ERKNS_8GeometryE -_ZN6Magick11borderImageC1ERKNS_8GeometryE -_ZNK6Magick11borderImageclERNS_5ImageE -_ZN6Magick13charcoalImageC2Edd -_ZN6Magick13charcoalImageC1Edd -_ZNK6Magick13charcoalImageclERNS_5ImageE -_ZN6Magick9chopImageC2ERKNS_8GeometryE -_ZN6Magick9chopImageC1ERKNS_8GeometryE -_ZNK6Magick9chopImageclERNS_5ImageE -_ZN6Magick13colorizeImageC2EjjjRKNS_5ColorE -_ZN6Magick13colorizeImageC1EjjjRKNS_5ColorE -_ZN6Magick13colorizeImageC2EjRKNS_5ColorE -_ZN6Magick13colorizeImageC1EjRKNS_5ColorE -_ZNK6Magick13colorizeImageclERNS_5ImageE -_ZN6Magick15colorSpaceImageC2EN9MagickLib14ColorspaceTypeE -_ZN6Magick15colorSpaceImageC1EN9MagickLib14ColorspaceTypeE -_ZNK6Magick15colorSpaceImageclERNS_5ImageE -_ZN6Magick12commentImageC2ERKSs -_ZN6Magick12commentImageC1ERKSs -_ZNK6Magick12commentImageclERNS_5ImageE -_ZN6Magick14compositeImageC2ERKNS_5ImageEiiN9MagickLib17CompositeOperatorE -_ZN6Magick14compositeImageC1ERKNS_5ImageEiiN9MagickLib17CompositeOperatorE -_ZN6Magick14compositeImageC2ERKNS_5ImageERKNS_8GeometryEN9MagickLib17CompositeOperatorE -_ZN6Magick14compositeImageC1ERKNS_5ImageERKNS_8GeometryEN9MagickLib17CompositeOperatorE -_ZNK6Magick14compositeImageclERNS_5ImageE -_ZN6Magick13contrastImageC2Ej -_ZN6Magick13contrastImageC1Ej -_ZNK6Magick13contrastImageclERNS_5ImageE -_ZN6Magick9cropImageC2ERKNS_8GeometryE -_ZN6Magick9cropImageC1ERKNS_8GeometryE -_ZNK6Magick9cropImageclERNS_5ImageE -_ZN6Magick18cycleColormapImageC2Ei -_ZN6Magick18cycleColormapImageC1Ei -_ZNK6Magick18cycleColormapImageclERNS_5ImageE -_ZN6Magick14despeckleImageC2Ev -_ZN6Magick14despeckleImageC1Ev -_ZNK6Magick14despeckleImageclERNS_5ImageE -_ZN6Magick9drawImageC2ERKNS_8DrawableE -_ZN6Magick9drawImageC1ERKNS_8DrawableE -_ZN6Magick9drawImageC2ERKSt4listINS_8DrawableESaIS2_EE -_ZN6Magick9drawImageC1ERKSt4listINS_8DrawableESaIS2_EE -_ZNK6Magick9drawImageclERNS_5ImageE -_ZN6Magick9edgeImageC2Ed -_ZN6Magick9edgeImageC1Ed -_ZNK6Magick9edgeImageclERNS_5ImageE -_ZN6Magick11embossImageC2Ev -_ZN6Magick11embossImageC1Ev -_ZN6Magick11embossImageC2Edd -_ZN6Magick11embossImageC1Edd -_ZNK6Magick11embossImageclERNS_5ImageE -_ZN6Magick12enhanceImageC2Ev -_ZN6Magick12enhanceImageC1Ev -_ZNK6Magick12enhanceImageclERNS_5ImageE -_ZN6Magick13equalizeImageC2Ev -_ZN6Magick13equalizeImageC1Ev -_ZNK6Magick13equalizeImageclERNS_5ImageE -_ZN6Magick14fillColorImageC2ERKNS_5ColorE -_ZN6Magick14fillColorImageC1ERKNS_5ColorE -_ZNK6Magick14fillColorImageclERNS_5ImageE -_ZN6Magick9flipImageC2Ev -_ZN6Magick9flipImageC1Ev -_ZNK6Magick9flipImageclERNS_5ImageE -_ZN6Magick19floodFillColorImageC2EjjRKNS_5ColorE -_ZN6Magick19floodFillColorImageC1EjjRKNS_5ColorE -_ZN6Magick19floodFillColorImageC2ERKNS_8GeometryERKNS_5ColorE -_ZN6Magick19floodFillColorImageC1ERKNS_8GeometryERKNS_5ColorE -_ZN6Magick19floodFillColorImageC2EjjRKNS_5ColorES3_ -_ZN6Magick19floodFillColorImageC1EjjRKNS_5ColorES3_ -_ZN6Magick19floodFillColorImageC2ERKNS_8GeometryERKNS_5ColorES6_ -_ZN6Magick19floodFillColorImageC1ERKNS_8GeometryERKNS_5ColorES6_ -_ZNK6Magick19floodFillColorImageclERNS_5ImageE -_ZN6Magick21floodFillTextureImageC2EjjRKNS_5ImageE -_ZN6Magick21floodFillTextureImageC1EjjRKNS_5ImageE -_ZN6Magick21floodFillTextureImageC2ERKNS_8GeometryERKNS_5ImageE -_ZN6Magick21floodFillTextureImageC1ERKNS_8GeometryERKNS_5ImageE -_ZN6Magick21floodFillTextureImageC2EjjRKNS_5ImageERKNS_5ColorE -_ZN6Magick21floodFillTextureImageC1EjjRKNS_5ImageERKNS_5ColorE -_ZN6Magick21floodFillTextureImageC2ERKNS_8GeometryERKNS_5ImageERKNS_5ColorE -_ZN6Magick21floodFillTextureImageC1ERKNS_8GeometryERKNS_5ImageERKNS_5ColorE -_ZNK6Magick21floodFillTextureImageclERNS_5ImageE -_ZN6Magick9flopImageC2Ev -_ZN6Magick9flopImageC1Ev -_ZNK6Magick9flopImageclERNS_5ImageE -_ZN6Magick10frameImageC2ERKNS_8GeometryE -_ZN6Magick10frameImageC1ERKNS_8GeometryE -_ZN6Magick10frameImageC2Ejjii -_ZN6Magick10frameImageC1Ejjii -_ZNK6Magick10frameImageclERNS_5ImageE -_ZN6Magick10gammaImageC2Ed -_ZN6Magick10gammaImageC1Ed -_ZN6Magick10gammaImageC2Eddd -_ZN6Magick10gammaImageC1Eddd -_ZNK6Magick10gammaImageclERNS_5ImageE -_ZN6Magick17gaussianBlurImageC2Edd -_ZN6Magick17gaussianBlurImageC1Edd -_ZNK6Magick17gaussianBlurImageclERNS_5ImageE -_ZN6Magick12implodeImageC2Ed -_ZN6Magick12implodeImageC1Ed -_ZNK6Magick12implodeImageclERNS_5ImageE -_ZN6Magick12isValidImageC2Eb -_ZN6Magick12isValidImageC1Eb -_ZNK6Magick12isValidImageclERNS_5ImageE -_ZN6Magick10labelImageC2ERKSs -_ZN6Magick10labelImageC1ERKSs -_ZNK6Magick10labelImageclERNS_5ImageE -_ZN6Magick12channelImageC2EN9MagickLib11ChannelTypeE -_ZN6Magick12channelImageC1EN9MagickLib11ChannelTypeE -_ZNK6Magick12channelImageclERNS_5ImageE -_ZN6Magick12magnifyImageC2Ev -_ZN6Magick12magnifyImageC1Ev -_ZNK6Magick12magnifyImageclERNS_5ImageE -_ZN6Magick8mapImageC2ERKNS_5ImageEb -_ZN6Magick8mapImageC1ERKNS_5ImageEb -_ZNK6Magick8mapImageclERNS_5ImageE -_ZN6Magick19matteFloodfillImageC2ERKNS_5ColorEjiiN9MagickLib11PaintMethodE -_ZN6Magick19matteFloodfillImageC1ERKNS_5ColorEjiiN9MagickLib11PaintMethodE -_ZNK6Magick19matteFloodfillImageclERNS_5ImageE -_ZN6Magick17medianFilterImageC2Ed -_ZN6Magick17medianFilterImageC1Ed -_ZNK6Magick17medianFilterImageclERNS_5ImageE -_ZN6Magick11minifyImageC2Ev -_ZN6Magick11minifyImageC1Ev -_ZNK6Magick11minifyImageclERNS_5ImageE -_ZN6Magick13modulateImageC2Eddd -_ZN6Magick13modulateImageC1Eddd -_ZNK6Magick13modulateImageclERNS_5ImageE -_ZN6Magick11negateImageC2Eb -_ZN6Magick11negateImageC1Eb -_ZNK6Magick11negateImageclERNS_5ImageE -_ZN6Magick14normalizeImageC2Ev -_ZN6Magick14normalizeImageC1Ev -_ZNK6Magick14normalizeImageclERNS_5ImageE -_ZN6Magick13oilPaintImageC2Ed -_ZN6Magick13oilPaintImageC1Ed -_ZNK6Magick13oilPaintImageclERNS_5ImageE -_ZN6Magick12opacityImageC2Ej -_ZN6Magick12opacityImageC1Ej -_ZNK6Magick12opacityImageclERNS_5ImageE -_ZN6Magick11opaqueImageC2ERKNS_5ColorES3_ -_ZN6Magick11opaqueImageC1ERKNS_5ColorES3_ -_ZNK6Magick11opaqueImageclERNS_5ImageE -_ZN6Magick13quantizeImageC2Eb -_ZN6Magick13quantizeImageC1Eb -_ZNK6Magick13quantizeImageclERNS_5ImageE -_ZN6Magick10raiseImageC2ERKNS_8GeometryEb -_ZN6Magick10raiseImageC1ERKNS_8GeometryEb -_ZNK6Magick10raiseImageclERNS_5ImageE -_ZN6Magick16reduceNoiseImageC2Ev -_ZN6Magick16reduceNoiseImageC1Ev -_ZN6Magick16reduceNoiseImageC2Ej -_ZN6Magick16reduceNoiseImageC1Ej -_ZNK6Magick16reduceNoiseImageclERNS_5ImageE -_ZN6Magick9rollImageC2ERKNS_8GeometryE -_ZN6Magick9rollImageC1ERKNS_8GeometryE -_ZN6Magick9rollImageC2Eii -_ZN6Magick9rollImageC1Eii -_ZNK6Magick9rollImageclERNS_5ImageE -_ZN6Magick11rotateImageC2Ed -_ZN6Magick11rotateImageC1Ed -_ZNK6Magick11rotateImageclERNS_5ImageE -_ZN6Magick11sampleImageC2ERKNS_8GeometryE -_ZN6Magick11sampleImageC1ERKNS_8GeometryE -_ZNK6Magick11sampleImageclERNS_5ImageE -_ZN6Magick10scaleImageC2ERKNS_8GeometryE -_ZN6Magick10scaleImageC1ERKNS_8GeometryE -_ZNK6Magick10scaleImageclERNS_5ImageE -_ZN6Magick12segmentImageC2Edd -_ZN6Magick12segmentImageC1Edd -_ZNK6Magick12segmentImageclERNS_5ImageE -_ZN6Magick10shadeImageC2Edd -_ZN6Magick10shadeImageC1Edd -_ZNK6Magick10shadeImageclERNS_5ImageE -_ZN6Magick12sharpenImageC2Edd -_ZN6Magick12sharpenImageC1Edd -_ZNK6Magick12sharpenImageclERNS_5ImageE -_ZN6Magick10shaveImageC2ERKNS_8GeometryE -_ZN6Magick10shaveImageC1ERKNS_8GeometryE -_ZNK6Magick10shaveImageclERNS_5ImageE -_ZN6Magick10shearImageC2Edd -_ZN6Magick10shearImageC1Edd -_ZNK6Magick10shearImageclERNS_5ImageE -_ZN6Magick13solarizeImageC2Ed -_ZN6Magick13solarizeImageC1Ed -_ZNK6Magick13solarizeImageclERNS_5ImageE -_ZN6Magick11spreadImageC2Ej -_ZN6Magick11spreadImageC1Ej -_ZNK6Magick11spreadImageclERNS_5ImageE -_ZN6Magick12steganoImageC2ERKNS_5ImageE -_ZN6Magick12steganoImageC1ERKNS_5ImageE -_ZNK6Magick12steganoImageclERNS_5ImageE -_ZN6Magick11stereoImageC2ERKNS_5ImageE -_ZN6Magick11stereoImageC1ERKNS_5ImageE -_ZNK6Magick11stereoImageclERNS_5ImageE -_ZN6Magick16strokeColorImageC2ERKNS_5ColorE -_ZN6Magick16strokeColorImageC1ERKNS_5ColorE -_ZNK6Magick16strokeColorImageclERNS_5ImageE -_ZN6Magick10swirlImageC2Ed -_ZN6Magick10swirlImageC1Ed -_ZNK6Magick10swirlImageclERNS_5ImageE -_ZN6Magick12textureImageC2ERKNS_5ImageE -_ZN6Magick12textureImageC1ERKNS_5ImageE -_ZNK6Magick12textureImageclERNS_5ImageE -_ZN6Magick14thresholdImageC2Ed -_ZN6Magick14thresholdImageC1Ed -_ZNK6Magick14thresholdImageclERNS_5ImageE -_ZN6Magick14transformImageC2ERKNS_8GeometryE -_ZN6Magick14transformImageC1ERKNS_8GeometryE -_ZN6Magick14transformImageC2ERKNS_8GeometryES3_ -_ZN6Magick14transformImageC1ERKNS_8GeometryES3_ -_ZNK6Magick14transformImageclERNS_5ImageE -_ZN6Magick16transparentImageC2ERKNS_5ColorE -_ZN6Magick16transparentImageC1ERKNS_5ColorE -_ZNK6Magick16transparentImageclERNS_5ImageE -_ZN6Magick9trimImageC2Ev -_ZN6Magick9trimImageC1Ev -_ZNK6Magick9trimImageclERNS_5ImageE -_ZN6Magick9waveImageC2Edd -_ZN6Magick9waveImageC1Edd -_ZNK6Magick9waveImageclERNS_5ImageE -_ZN6Magick9zoomImageC2ERKNS_8GeometryE -_ZN6Magick9zoomImageC1ERKNS_8GeometryE -_ZNK6Magick9zoomImageclERNS_5ImageE -_ZN6Magick14antiAliasImageC2Eb -_ZN6Magick14antiAliasImageC1Eb -_ZNK6Magick14antiAliasImageclERNS_5ImageE -_ZN6Magick11adjoinImageC2Eb -_ZN6Magick11adjoinImageC1Eb -_ZNK6Magick11adjoinImageclERNS_5ImageE -_ZN6Magick19animationDelayImageC2Ej -_ZN6Magick19animationDelayImageC1Ej -_ZNK6Magick19animationDelayImageclERNS_5ImageE -_ZN6Magick24animationIterationsImageC2Ej -_ZN6Magick24animationIterationsImageC1Ej -_ZNK6Magick24animationIterationsImageclERNS_5ImageE -_ZN6Magick20backgroundColorImageC2ERKNS_5ColorE -_ZN6Magick20backgroundColorImageC1ERKNS_5ColorE -_ZNK6Magick20backgroundColorImageclERNS_5ImageE -_ZN6Magick22backgroundTextureImageC2ERKSs -_ZN6Magick22backgroundTextureImageC1ERKSs -_ZNK6Magick22backgroundTextureImageclERNS_5ImageE -_ZN6Magick16borderColorImageC2ERKNS_5ColorE -_ZN6Magick16borderColorImageC1ERKNS_5ColorE -_ZNK6Magick16borderColorImageclERNS_5ImageE -_ZN6Magick13boxColorImageC2ERKNS_5ColorE -_ZN6Magick13boxColorImageC1ERKNS_5ColorE -_ZNK6Magick13boxColorImageclERNS_5ImageE -_ZN6Magick22chromaBluePrimaryImageC2Edd -_ZN6Magick22chromaBluePrimaryImageC1Edd -_ZNK6Magick22chromaBluePrimaryImageclERNS_5ImageE -_ZN6Magick23chromaGreenPrimaryImageC2Edd -_ZN6Magick23chromaGreenPrimaryImageC1Edd -_ZNK6Magick23chromaGreenPrimaryImageclERNS_5ImageE -_ZN6Magick21chromaRedPrimaryImageC2Edd -_ZN6Magick21chromaRedPrimaryImageC1Edd -_ZNK6Magick21chromaRedPrimaryImageclERNS_5ImageE -_ZN6Magick21chromaWhitePointImageC2Edd -_ZN6Magick21chromaWhitePointImageC1Edd -_ZNK6Magick21chromaWhitePointImageclERNS_5ImageE -_ZN6Magick14colorFuzzImageC2Ed -_ZN6Magick14colorFuzzImageC1Ed -_ZNK6Magick14colorFuzzImageclERNS_5ImageE -_ZN6Magick13colorMapImageC2EjRKNS_5ColorE -_ZN6Magick13colorMapImageC1EjRKNS_5ColorE -_ZNK6Magick13colorMapImageclERNS_5ImageE -_ZN6Magick17compressTypeImageC2EN9MagickLib15CompressionTypeE -_ZN6Magick17compressTypeImageC1EN9MagickLib15CompressionTypeE -_ZNK6Magick17compressTypeImageclERNS_5ImageE -_ZN6Magick12densityImageC2ERKNS_8GeometryE -_ZN6Magick12densityImageC1ERKNS_8GeometryE -_ZNK6Magick12densityImageclERNS_5ImageE -_ZN6Magick10depthImageC2Ej -_ZN6Magick10depthImageC1Ej -_ZNK6Magick10depthImageclERNS_5ImageE -_ZN6Magick11endianImageC2EN9MagickLib10EndianTypeE -_ZN6Magick11endianImageC1EN9MagickLib10EndianTypeE -_ZNK6Magick11endianImageclERNS_5ImageE -_ZN6Magick13fileNameImageC2ERKSs -_ZN6Magick13fileNameImageC1ERKSs -_ZNK6Magick13fileNameImageclERNS_5ImageE -_ZN6Magick15filterTypeImageC2EN9MagickLib11FilterTypesE -_ZN6Magick15filterTypeImageC1EN9MagickLib11FilterTypesE -_ZNK6Magick15filterTypeImageclERNS_5ImageE -_ZN6Magick9fontImageC2ERKSs -_ZN6Magick9fontImageC1ERKSs -_ZNK6Magick9fontImageclERNS_5ImageE -_ZN6Magick18fontPointsizeImageC2Ej -_ZN6Magick18fontPointsizeImageC1Ej -_ZNK6Magick18fontPointsizeImageclERNS_5ImageE -_ZN6Magick21gifDisposeMethodImageC2Ej -_ZN6Magick21gifDisposeMethodImageC1Ej -_ZNK6Magick21gifDisposeMethodImageclERNS_5ImageE -_ZN6Magick18interlaceTypeImageC2EN9MagickLib13InterlaceTypeE -_ZN6Magick18interlaceTypeImageC1EN9MagickLib13InterlaceTypeE -_ZNK6Magick18interlaceTypeImageclERNS_5ImageE -_ZN6Magick14lineWidthImageC2Ed -_ZN6Magick14lineWidthImageC1Ed -_ZNK6Magick14lineWidthImageclERNS_5ImageE -_ZN6Magick11magickImageC2ERKSs -_ZN6Magick11magickImageC1ERKSs -_ZNK6Magick11magickImageclERNS_5ImageE -_ZN6Magick10matteImageC2Eb -_ZN6Magick10matteImageC1Eb -_ZNK6Magick10matteImageclERNS_5ImageE -_ZN6Magick15matteColorImageC2ERKNS_5ColorE -_ZN6Magick15matteColorImageC1ERKNS_5ColorE -_ZNK6Magick15matteColorImageclERNS_5ImageE -_ZN6Magick15monochromeImageC2Eb -_ZN6Magick15monochromeImageC1Eb -_ZNK6Magick15monochromeImageclERNS_5ImageE -_ZN6Magick13penColorImageC2ERKNS_5ColorE -_ZN6Magick13penColorImageC1ERKNS_5ColorE -_ZNK6Magick13penColorImageclERNS_5ImageE -_ZN6Magick15penTextureImageC2ERKNS_5ImageE -_ZN6Magick15penTextureImageC1ERKNS_5ImageE -_ZNK6Magick15penTextureImageclERNS_5ImageE -_ZN6Magick15pixelColorImageC2EjjRKNS_5ColorE -_ZN6Magick15pixelColorImageC1EjjRKNS_5ColorE -_ZNK6Magick15pixelColorImageclERNS_5ImageE -_ZN6Magick9pageImageC2ERKNS_8GeometryE -_ZN6Magick9pageImageC1ERKNS_8GeometryE -_ZNK6Magick9pageImageclERNS_5ImageE -_ZN6Magick12qualityImageC2Ej -_ZN6Magick12qualityImageC1Ej -_ZNK6Magick12qualityImageclERNS_5ImageE -_ZN6Magick19quantizeColorsImageC2Ej -_ZN6Magick19quantizeColorsImageC1Ej -_ZNK6Magick19quantizeColorsImageclERNS_5ImageE -_ZN6Magick23quantizeColorSpaceImageC2EN9MagickLib14ColorspaceTypeE -_ZN6Magick23quantizeColorSpaceImageC1EN9MagickLib14ColorspaceTypeE -_ZNK6Magick23quantizeColorSpaceImageclERNS_5ImageE -_ZN6Magick19quantizeDitherImageC2Eb -_ZN6Magick19quantizeDitherImageC1Eb -_ZNK6Magick19quantizeDitherImageclERNS_5ImageE -_ZN6Magick22quantizeTreeDepthImageC2Ej -_ZN6Magick22quantizeTreeDepthImageC1Ej -_ZNK6Magick22quantizeTreeDepthImageclERNS_5ImageE -_ZN6Magick20renderingIntentImageC2EN9MagickLib15RenderingIntentE -_ZN6Magick20renderingIntentImageC1EN9MagickLib15RenderingIntentE -_ZNK6Magick20renderingIntentImageclERNS_5ImageE -_ZN6Magick20resolutionUnitsImageC2EN9MagickLib14ResolutionTypeE -_ZN6Magick20resolutionUnitsImageC1EN9MagickLib14ResolutionTypeE -_ZNK6Magick20resolutionUnitsImageclERNS_5ImageE -_ZN6Magick10sceneImageC2Ej -_ZN6Magick10sceneImageC1Ej -_ZNK6Magick10sceneImageclERNS_5ImageE -_ZN6Magick9sizeImageC2ERKNS_8GeometryE -_ZN6Magick9sizeImageC1ERKNS_8GeometryE -_ZNK6Magick9sizeImageclERNS_5ImageE -_ZN6Magick13subImageImageC2Ej -_ZN6Magick13subImageImageC1Ej -_ZNK6Magick13subImageImageclERNS_5ImageE -_ZN6Magick13subRangeImageC2Ej -_ZN6Magick13subRangeImageC1Ej -_ZNK6Magick13subRangeImageclERNS_5ImageE -_ZN6Magick13tileNameImageC2ERKSs -_ZN6Magick13tileNameImageC1ERKSs -_ZNK6Magick13tileNameImageclERNS_5ImageE -_ZN6Magick9typeImageC2EN9MagickLib9ImageTypeE -_ZN6Magick9typeImageC1EN9MagickLib9ImageTypeE -_ZNK6Magick9typeImageclERNS_5ImageE -_ZN6Magick12verboseImageC2Eb -_ZN6Magick12verboseImageC1Eb -_ZNK6Magick12verboseImageclERNS_5ImageE -_ZN6Magick9viewImageC2ERKSs -_ZN6Magick9viewImageC1ERKSs -_ZNK6Magick9viewImageclERNS_5ImageE -_ZN6Magick15x11DisplayImageC2ERKSs -_ZN6Magick15x11DisplayImageC1ERKSs -_ZNK6Magick15x11DisplayImageclERNS_5ImageE -_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EE5clearEv -_ZNSt4listIN6Magick8DrawableESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEvS5_IS1_RS1_PS1_ET_SD_12__false_type -_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EED2Ev -_ZNSt14__simple_allocISt10_List_nodeIN6Magick8DrawableEESt24__default_alloc_templateILb1ELi0EEE10deallocateEPS3_j -_ZNSt4listIN6Magick8DrawableESaIS1_EE14_M_create_nodeERKS1_ -_ZN6Magick9MutexLockC2Ev -_ZN6Magick9MutexLockC1Ev -_ZN6Magick9MutexLockD2Ev -_ZN6Magick9MutexLockD1Ev -_ZN6Magick9MutexLock4lockEv -_ZN6Magick9MutexLock6unlockEv -_ZN6Magick10TypeMetricC2Ev -_ZN6Magick10TypeMetricC1Ev -_ZN6Magick10TypeMetricD2Ev -_ZN6Magick10TypeMetricD1Ev -_ZNK6Magick10TypeMetric6ascentEv -_ZNK6Magick10TypeMetric7descentEv -_ZNK6Magick10TypeMetric9textWidthEv -_ZNK6Magick10TypeMetric10textHeightEv -_ZNK6Magick10TypeMetric20maxHorizontalAdvanceEv -_ZTSN6Magick4BlobE -_ZTSN6Magick8ColorYUVE -_ZTSN6Magick8ColorRGBE -_ZTSN6Magick9ColorMonoE -_ZTSN6Magick9ColorGrayE -_ZTSN6Magick8ColorHSLE -_ZTSN6Magick5ColorE -_ZTSN6Magick13PathMovetoRelE -_ZTSN6Magick13PathMovetoAbsE -_ZTSN6Magick21PathLinetoVerticalRelE -_ZTSN6Magick21PathLinetoVerticalAbsE -_ZTSN6Magick23PathLinetoHorizontalRelE -_ZTSN6Magick23PathLinetoHorizontalAbsE -_ZTSN6Magick13PathLinetoRelE -_ZTSN6Magick13PathLinetoAbsE -_ZTSN6Magick29PathSmoothQuadraticCurvetoRelE -_ZTSN6Magick29PathSmoothQuadraticCurvetoAbsE -_ZTSN6Magick23PathQuadraticCurvetoRelE -_ZTSN6Magick23PathQuadraticCurvetoAbsE -_ZTSN6Magick20PathSmoothCurvetoRelE -_ZTSN6Magick20PathSmoothCurvetoAbsE -_ZTSN6Magick14PathCurvetoRelE -_ZTSN6Magick14PathCurvetoAbsE -_ZTSN6Magick13PathClosePathE -_ZTSN6Magick10PathArcRelE -_ZTSN6Magick10PathArcAbsE -_ZTSN6Magick15DrawableViewboxE -_ZTSN6Magick19DrawableTranslationE -_ZTSN6Magick22DrawableTextUnderColorE -_ZTSN6Magick22DrawableTextDecorationE -_ZTSN6Magick21DrawableTextAntialiasE -_ZTSN6Magick12DrawableTextE -_ZTSN6Magick19DrawableStrokeWidthE -_ZTSN6Magick21DrawableStrokeOpacityE -_ZTSN6Magick19DrawableStrokeColorE -_ZTSN6Magick23DrawableStrokeAntialiasE -_ZTSN6Magick18DrawableMiterLimitE -_ZTSN6Magick22DrawableStrokeLineJoinE -_ZTSN6Magick21DrawableStrokeLineCapE -_ZTSN6Magick18DrawableDashOffsetE -_ZTSN6Magick17DrawableDashArrayE -_ZTSN6Magick13DrawableSkewYE -_ZTSN6Magick13DrawableSkewXE -_ZTSN6Magick15DrawableScalingE -_ZTSN6Magick22DrawableRoundRectangleE -_ZTSN6Magick16DrawableRotationE -_ZTSN6Magick17DrawableRectangleE -_ZTSN6Magick19DrawablePushPatternE -_ZTSN6Magick18DrawablePopPatternE -_ZTSN6Magick26DrawablePushGraphicContextE -_ZTSN6Magick25DrawablePopGraphicContextE -_ZTSN6Magick16DrawablePolylineE -_ZTSN6Magick15DrawablePolygonE -_ZTSN6Magick17DrawablePointSizeE -_ZTSN6Magick13DrawablePointE -_ZTSN6Magick12DrawablePathE -_ZTSN6Magick13DrawableMatteE -_ZTSN6Magick12DrawableLineE -_ZTSN6Magick15DrawableGravityE -_ZTSN6Magick12DrawableFontE -_ZTSN6Magick19DrawableFillOpacityE -_ZTSN6Magick16DrawableFillRuleE -_ZTSN6Magick17DrawableFillColorE -_ZTSN6Magick15DrawableEllipseE -_ZTSN6Magick22DrawableCompositeImageE -_ZTSN6Magick13DrawableColorE -_ZTSN6Magick14DrawableCircleE -_ZTSN6Magick14DrawableBezierE -_ZTSN6Magick11DrawableArcE -_ZTSN6Magick14DrawableAffineE -_ZTSN6Magick5VPathE -_ZTSN6Magick9VPathBaseE -_ZTSN6Magick12DrawableBaseE -_ZTSN6Magick10CoordinateE -_ZTSSt14unary_functionIPN9MagickLib12_DrawContextEvE -_ZTSN6Magick10ErrorCacheE -_ZTSN6Magick9ErrorBlobE -_ZTSN6Magick13ErrorFileOpenE -_ZTSN6Magick17ErrorCorruptImageE -_ZTSN6Magick20ErrorMissingDelegateE -_ZTSN6Magick13ErrorDelegateE -_ZTSN6Magick11ErrorOptionE -_ZTSN6Magick12ErrorXServerE -_ZTSN6Magick18ErrorResourceLimitE -_ZTSN6Magick14ErrorUndefinedE -_ZTSN6Magick5ErrorE -_ZTSN6Magick12WarningCacheE -_ZTSN6Magick11WarningBlobE -_ZTSN6Magick15WarningFileOpenE -_ZTSN6Magick19WarningCorruptImageE -_ZTSN6Magick22WarningMissingDelegateE -_ZTSN6Magick15WarningDelegateE -_ZTSN6Magick13WarningOptionE -_ZTSN6Magick14WarningXServerE -_ZTSN6Magick20WarningResourceLimitE -_ZTSN6Magick16WarningUndefinedE -_ZTSN6Magick7WarningE -_ZTSN6Magick9ExceptionE -_ZTSN6Magick5ImageE -_ZTSN6Magick13MontageFramedE -_ZTSN6Magick7MontageE -_ZTVN6Magick4BlobE -_ZTIN6Magick4BlobE -_ZTVN6Magick8ColorYUVE -_ZTVN6Magick8ColorRGBE -_ZTVN6Magick9ColorMonoE -_ZTVN6Magick9ColorGrayE -_ZTVN6Magick8ColorHSLE -_ZTVN6Magick5ColorE -_ZTIN6Magick5ColorE -_ZTIN6Magick8ColorHSLE -_ZTIN6Magick9ColorGrayE -_ZTIN6Magick9ColorMonoE -_ZTIN6Magick8ColorRGBE -_ZTIN6Magick8ColorYUVE -_ZZ18__gthread_active_pvE20__gthread_active_ptr -_ZTVN6Magick13PathMovetoRelE -_ZTVN6Magick13PathMovetoAbsE -_ZTVN6Magick21PathLinetoVerticalRelE -_ZTVN6Magick21PathLinetoVerticalAbsE -_ZTVN6Magick23PathLinetoHorizontalRelE -_ZTVN6Magick23PathLinetoHorizontalAbsE -_ZTVN6Magick13PathLinetoRelE -_ZTVN6Magick13PathLinetoAbsE -_ZTVN6Magick29PathSmoothQuadraticCurvetoRelE -_ZTVN6Magick29PathSmoothQuadraticCurvetoAbsE -_ZTVN6Magick23PathQuadraticCurvetoRelE -_ZTVN6Magick23PathQuadraticCurvetoAbsE -_ZTVN6Magick20PathSmoothCurvetoRelE -_ZTVN6Magick20PathSmoothCurvetoAbsE -_ZTVN6Magick14PathCurvetoRelE -_ZTVN6Magick14PathCurvetoAbsE -_ZTVN6Magick13PathClosePathE -_ZTVN6Magick10PathArcRelE -_ZTVN6Magick10PathArcAbsE -_ZTVN6Magick15DrawableViewboxE -_ZTVN6Magick19DrawableTranslationE -_ZTVN6Magick22DrawableTextUnderColorE -_ZTVN6Magick22DrawableTextDecorationE -_ZTVN6Magick21DrawableTextAntialiasE -_ZTVN6Magick12DrawableTextE -_ZTVN6Magick19DrawableStrokeWidthE -_ZTVN6Magick21DrawableStrokeOpacityE -_ZTVN6Magick19DrawableStrokeColorE -_ZTVN6Magick23DrawableStrokeAntialiasE -_ZTVN6Magick18DrawableMiterLimitE -_ZTVN6Magick22DrawableStrokeLineJoinE -_ZTVN6Magick21DrawableStrokeLineCapE -_ZTVN6Magick18DrawableDashOffsetE -_ZTVN6Magick17DrawableDashArrayE -_ZTVN6Magick13DrawableSkewYE -_ZTVN6Magick13DrawableSkewXE -_ZTVN6Magick15DrawableScalingE -_ZTVN6Magick22DrawableRoundRectangleE -_ZTVN6Magick16DrawableRotationE -_ZTVN6Magick17DrawableRectangleE -_ZTVN6Magick19DrawablePushPatternE -_ZTVN6Magick18DrawablePopPatternE -_ZTVN6Magick26DrawablePushGraphicContextE -_ZTVN6Magick25DrawablePopGraphicContextE -_ZTVN6Magick16DrawablePolylineE -_ZTVN6Magick15DrawablePolygonE -_ZTVN6Magick17DrawablePointSizeE -_ZTVN6Magick13DrawablePointE -_ZTVN6Magick12DrawablePathE -_ZTVN6Magick13DrawableMatteE -_ZTVN6Magick12DrawableLineE -_ZTVN6Magick15DrawableGravityE -_ZTVN6Magick12DrawableFontE -_ZTVN6Magick19DrawableFillOpacityE -_ZTVN6Magick16DrawableFillRuleE -_ZTVN6Magick17DrawableFillColorE -_ZTVN6Magick15DrawableEllipseE -_ZTVN6Magick22DrawableCompositeImageE -_ZTVN6Magick13DrawableColorE -_ZTVN6Magick14DrawableCircleE -_ZTVN6Magick14DrawableBezierE -_ZTVN6Magick11DrawableArcE -_ZTVN6Magick14DrawableAffineE -_ZTVN6Magick5VPathE -_ZTVN6Magick9VPathBaseE -_ZTVN6Magick12DrawableBaseE -_ZTVN6Magick10CoordinateE -_ZTIN6Magick10CoordinateE -_ZTIN6Magick12DrawableBaseE -_ZTIN6Magick9VPathBaseE -_ZTIN6Magick5VPathE -_ZTIN6Magick14DrawableAffineE -_ZTIN6Magick11DrawableArcE -_ZTIN6Magick14DrawableBezierE -_ZTIN6Magick14DrawableCircleE -_ZTIN6Magick13DrawableColorE -_ZTIN6Magick22DrawableCompositeImageE -_ZTIN6Magick15DrawableEllipseE -_ZTIN6Magick17DrawableFillColorE -_ZTIN6Magick16DrawableFillRuleE -_ZTIN6Magick19DrawableFillOpacityE -_ZTIN6Magick12DrawableFontE -_ZTIN6Magick15DrawableGravityE -_ZTIN6Magick12DrawableLineE -_ZTIN6Magick13DrawableMatteE -_ZTIN6Magick12DrawablePathE -_ZTIN6Magick13DrawablePointE -_ZTIN6Magick17DrawablePointSizeE -_ZTIN6Magick15DrawablePolygonE -_ZTIN6Magick16DrawablePolylineE -_ZTIN6Magick25DrawablePopGraphicContextE -_ZTIN6Magick26DrawablePushGraphicContextE -_ZTIN6Magick18DrawablePopPatternE -_ZTIN6Magick19DrawablePushPatternE -_ZTIN6Magick17DrawableRectangleE -_ZTIN6Magick16DrawableRotationE -_ZTIN6Magick22DrawableRoundRectangleE -_ZTIN6Magick15DrawableScalingE -_ZTIN6Magick13DrawableSkewXE -_ZTIN6Magick13DrawableSkewYE -_ZTIN6Magick17DrawableDashArrayE -_ZTIN6Magick18DrawableDashOffsetE -_ZTIN6Magick21DrawableStrokeLineCapE -_ZTIN6Magick22DrawableStrokeLineJoinE -_ZTIN6Magick18DrawableMiterLimitE -_ZTIN6Magick23DrawableStrokeAntialiasE -_ZTIN6Magick19DrawableStrokeColorE -_ZTIN6Magick21DrawableStrokeOpacityE -_ZTIN6Magick19DrawableStrokeWidthE -_ZTIN6Magick12DrawableTextE -_ZTIN6Magick21DrawableTextAntialiasE -_ZTIN6Magick22DrawableTextDecorationE -_ZTIN6Magick22DrawableTextUnderColorE -_ZTIN6Magick19DrawableTranslationE -_ZTIN6Magick15DrawableViewboxE -_ZTIN6Magick10PathArcAbsE -_ZTIN6Magick10PathArcRelE -_ZTIN6Magick13PathClosePathE -_ZTIN6Magick14PathCurvetoAbsE -_ZTIN6Magick14PathCurvetoRelE -_ZTIN6Magick20PathSmoothCurvetoAbsE -_ZTIN6Magick20PathSmoothCurvetoRelE -_ZTIN6Magick23PathQuadraticCurvetoAbsE -_ZTIN6Magick23PathQuadraticCurvetoRelE -_ZTIN6Magick29PathSmoothQuadraticCurvetoAbsE -_ZTIN6Magick29PathSmoothQuadraticCurvetoRelE -_ZTIN6Magick13PathLinetoAbsE -_ZTIN6Magick13PathLinetoRelE -_ZTIN6Magick23PathLinetoHorizontalAbsE -_ZTIN6Magick23PathLinetoHorizontalRelE -_ZTIN6Magick21PathLinetoVerticalAbsE -_ZTIN6Magick21PathLinetoVerticalRelE -_ZTIN6Magick13PathMovetoAbsE -_ZTIN6Magick13PathMovetoRelE -_ZTISt14unary_functionIPN9MagickLib12_DrawContextEvE -_ZTVN6Magick10ErrorCacheE -_ZTVN6Magick9ErrorBlobE -_ZTVN6Magick13ErrorFileOpenE -_ZTVN6Magick17ErrorCorruptImageE -_ZTVN6Magick20ErrorMissingDelegateE -_ZTVN6Magick13ErrorDelegateE -_ZTVN6Magick11ErrorOptionE -_ZTVN6Magick12ErrorXServerE -_ZTVN6Magick18ErrorResourceLimitE -_ZTVN6Magick14ErrorUndefinedE -_ZTVN6Magick5ErrorE -_ZTVN6Magick12WarningCacheE -_ZTVN6Magick11WarningBlobE -_ZTVN6Magick15WarningFileOpenE -_ZTVN6Magick19WarningCorruptImageE -_ZTVN6Magick22WarningMissingDelegateE -_ZTVN6Magick15WarningDelegateE -_ZTVN6Magick13WarningOptionE -_ZTVN6Magick14WarningXServerE -_ZTVN6Magick20WarningResourceLimitE -_ZTVN6Magick16WarningUndefinedE -_ZTVN6Magick7WarningE -_ZTVN6Magick9ExceptionE -_ZTIN6Magick9ExceptionE -_ZTIN6Magick7WarningE -_ZTIN6Magick16WarningUndefinedE -_ZTIN6Magick20WarningResourceLimitE -_ZTIN6Magick14WarningXServerE -_ZTIN6Magick13WarningOptionE -_ZTIN6Magick15WarningDelegateE -_ZTIN6Magick22WarningMissingDelegateE -_ZTIN6Magick19WarningCorruptImageE -_ZTIN6Magick15WarningFileOpenE -_ZTIN6Magick11WarningBlobE -_ZTIN6Magick12WarningCacheE -_ZTIN6Magick5ErrorE -_ZTIN6Magick14ErrorUndefinedE -_ZTIN6Magick18ErrorResourceLimitE -_ZTIN6Magick12ErrorXServerE -_ZTIN6Magick11ErrorOptionE -_ZTIN6Magick13ErrorDelegateE -_ZTIN6Magick20ErrorMissingDelegateE -_ZTIN6Magick17ErrorCorruptImageE -_ZTIN6Magick13ErrorFileOpenE -_ZTIN6Magick9ErrorBlobE -_ZTIN6Magick10ErrorCacheE -_ZTVN6Magick5ImageE -_ZTIN6Magick5ImageE -_ZTVN6Magick13MontageFramedE -_ZTVN6Magick7MontageE -_ZTIN6Magick7MontageE -_ZTIN6Magick13MontageFramedE -_ZN6Magick21borderGeometryDefaultE -_ZN6Magick20frameGeometryDefaultE -_ZN6Magick20raiseGeometryDefaultE -_ZN6Magick18magickCleanUpGuardE -_ZNSt24__default_alloc_templateILb1ELi0EE8allocateEj -_Znaj -_ZNSt24__default_alloc_templateILb1ELi0EE12_S_free_listE -_ZNSt9exceptionD2Ev -_ZNSs4_Rep11_S_terminalE -_ZNKSs4copyEPcjj -_ZNSs4_Rep10_M_disposeERKSaIcE -_ZNSsC1ERKSs -_ZNSs6assignERKSs -_ZTVN10__cxxabiv120__si_class_type_infoE -_ZNSsD1Ev -_ZdlPv -_ZSt9terminatev -_ZNSs7replaceEjjPKcj -_ZTISt9exception -_ZNSs7reserveEj -_ZNSs20_S_empty_rep_storageE -_ZNSs6appendEjc -_ZTVN10__cxxabiv117__class_type_infoE -_ZdaPv -_ZNSs6appendERKSs -_ZNSsC1EPKcRKSaIcE -_ZNSt24__default_alloc_templateILb1ELi0EE22_S_node_allocator_lockE -_ZNSt24__default_alloc_templateILb1ELi0EE10deallocateEPvj -_ZNSsC1EPKcjRKSaIcE -_Znwj -_ZNSs4_Rep10_M_destroyERKSaIcE -_ZNSs6appendEPKcj diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java index f866d0e637..f9d4dc26ec 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java @@ -602,7 +602,10 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { if (descriptorName == null) { return null; } - DemangledType typeNamespace = new DemangledType(descriptorName); + + String demangledSource = mdComplexType.toString(); + DemangledType typeNamespace = + new DemangledType(originalTypeName, demangledSource, descriptorName); DemangledType parentNamespace = getParentNamespace(); // Can be null; if (parentNamespace != null) { typeNamespace.setNamespace(parentNamespace); @@ -614,8 +617,8 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { return namespace; } - private boolean isNamespaceDeleted(Namespace namespace2) { - Symbol nsSymbol = namespace2.getSymbol(); + private boolean isNamespaceDeleted(Namespace other) { + Symbol nsSymbol = other.getSymbol(); if (nsSymbol == null) { return false; // global namespace. } diff --git a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java index 41bb8536dc..431bce0319 100644 --- a/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java +++ b/Ghidra/Features/MicrosoftDemangler/src/main/java/ghidra/app/util/demangler/microsoft/MicrosoftDemangler.java @@ -21,7 +21,6 @@ import ghidra.app.util.opinion.PeLoader; import ghidra.program.model.listing.Program; import mdemangler.MDException; import mdemangler.MDMangGhidra; -import util.demangler.GenericDemangledException; /** * A class for demangling debug symbols created using Microsoft Visual Studio. @@ -46,7 +45,7 @@ public class MicrosoftDemangler implements Demangler { DemangledObject demangled = demangleMS(mangled, demangleOnlyKnownPatterns); return demangled; } - catch (GenericDemangledException e) { + catch (DemangledException e) { throw new DemangledException(true); } } @@ -59,15 +58,15 @@ public class MicrosoftDemangler implements Demangler { DemangledObject demangled = demangleMS(mangled, options.demangleOnlyKnownPatterns()); return demangled; } - catch (GenericDemangledException e) { + catch (DemangledException e) { throw new DemangledException(true); } } private DemangledObject demangleMS(String mangled, boolean demangleOnlyKnownPatterns) - throws GenericDemangledException { + throws DemangledException { if (mangled == null || mangled.length() == 0) { - throw new GenericDemangledException(true); + throw new DemangledException(true); } MDMangGhidra demangler = new MDMangGhidra(); @@ -77,10 +76,10 @@ public class MicrosoftDemangler implements Demangler { return object; } catch (MDException e) { - GenericDemangledException gde = - new GenericDemangledException("Unable to demangle symbol: " + mangled); - gde.initCause(e); - throw gde; + DemangledException de = + new DemangledException("Unable to demangle symbol: " + mangled); + de.initCause(e); + throw de; } } } diff --git a/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java b/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java index 32f4df73f9..730e9f927a 100644 --- a/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java +++ b/Ghidra/Features/MicrosoftDmang/src/main/java/mdemangler/MDMangGhidra.java @@ -38,6 +38,9 @@ public class MDMangGhidra extends MDMang { private DemangledObject objectResult; private DemangledDataType dataTypeResult; + private String mangledSource; + private String demangledSource; + public DemangledObject getObject() { return objectResult; } @@ -46,31 +49,6 @@ public class MDMangGhidra extends MDMang { return dataTypeResult; } - public DemangledType processNamespace(MDQualifiedName qualifiedName) { - return processNamespace(qualifiedName.getQualification()); - } - - private DemangledType processNamespace(MDQualification qualification) { - Iterator it = qualification.iterator(); - if (!it.hasNext()) { - return null; - } - - MDQualifier qual = it.next(); - DemangledType type = new DemangledType(qual.toString()); - DemangledType parentType = type; - while (it.hasNext()) { - qual = it.next(); - DemangledType newType = new DemangledType(qual.toString()); - if (qual.isNested()) { - newType.setOriginalMangled(qual.getNested().getMangled()); - } - parentType.setNamespace(newType); - parentType = newType; - } - return type; - } - @Override public MDParsableItem demangle(String mangledArg, boolean demangleOnlyKnownPatterns) throws MDException { @@ -83,16 +61,47 @@ public class MDMangGhidra extends MDMang { return null; } } + + this.mangledSource = mangledArg; + MDParsableItem returnedItem = super.demangle(mangledArg, true); + + this.demangledSource = item.toString(); + objectResult = processItem(); - if (objectResult != null) { - objectResult.setOriginalMangled(mangledArg); - // Make our version of the demangled string available (could be large). - objectResult.setUtilDemangled(item.toString()); - } return returnedItem; } + public DemangledType processNamespace(MDQualifiedName qualifiedName) { + return processNamespace(qualifiedName.getQualification()); + } + + private DemangledType processNamespace(MDQualification qualification) { + Iterator it = qualification.iterator(); + if (!it.hasNext()) { + return null; + } + + MDQualifier qual = it.next(); + DemangledType type = new DemangledType(mangledSource, demangledSource, qual.toString()); + DemangledType parentType = type; + while (it.hasNext()) { + qual = it.next(); + DemangledType newType; + if (qual.isNested()) { + String subMangled = qual.getNested().getMangled(); + newType = new DemangledType(subMangled, demangledSource, qual.toString()); + } + else { + newType = + new DemangledType(mangledSource, demangledSource, qual.toString()); + } + parentType.setNamespace(newType); + parentType = newType; + } + return type; + } + private DemangledObject processItem() { objectResult = null; if (item instanceof MDObjectReserved) { @@ -137,7 +146,7 @@ public class MDMangGhidra extends MDMang { } //TODO: put other objectReserved derivative types here and return something that Ghidra can use. else { - object = new DemangledUnknown(); + object = new DemangledUnknown(mangledSource, demangledSource, null); } return object; } @@ -175,10 +184,10 @@ public class MDMangGhidra extends MDMang { MDType mdtype = variableInfo.getMDType(); DemangledDataType dt = processDataType(null, (MDDataType) mdtype); if ("std::nullptr_t".equals(dt.getName())) { - variable = new DemangledVariable(""); + variable = new DemangledVariable(mangledSource, demangledSource, ""); } else { - variable = new DemangledVariable( + variable = new DemangledVariable(mangledSource, demangledSource, objectCPP.getName()); variable.setNamespace(processNamespace(objectCPP.getQualfication())); } @@ -200,7 +209,7 @@ public class MDMangGhidra extends MDMang { } else if (typeinfo instanceof MDFunctionInfo) { DemangledFunction function = - new DemangledFunction(objectCPP.getName()); + new DemangledFunction(mangledSource, demangledSource, objectCPP.getName()); function.setNamespace(processNamespace(objectCPP.getQualfication())); resultObject = function; objectResult = processFunction((MDFunctionInfo) typeinfo, function); @@ -229,7 +238,7 @@ public class MDMangGhidra extends MDMang { else if (typeinfo instanceof MDVxTable) { //Includes VFTable, VBTable, and RTTI4 MDVxTable vxtable = (MDVxTable) typeinfo; DemangledVariable variable = - new DemangledVariable(objectCPP.getName()); + new DemangledVariable(mangledSource, demangledSource, objectCPP.getName()); variable.setNamespace(processNamespace(objectCPP.getQualfication())); variable.setConst(vxtable.isConst()); variable.setVolatile(vxtable.isVolatile()); @@ -241,7 +250,7 @@ public class MDMangGhidra extends MDMang { } else if (typeinfo instanceof AbstractMDMetaClass) { //Includes all RTTI, except RTTI4 DemangledVariable variable = - new DemangledVariable(objectCPP.getName()); + new DemangledVariable(mangledSource, demangledSource, objectCPP.getName()); variable.setNamespace(processNamespace(objectCPP.getQualfication())); resultObject = variable; // The following code would be an alternative, depending on whether we get @@ -250,7 +259,7 @@ public class MDMangGhidra extends MDMang { } else if (typeinfo instanceof MDGuard) { DemangledVariable variable = - new DemangledVariable(objectCPP.getName()); + new DemangledVariable(mangledSource, demangledSource, objectCPP.getName()); variable.setNamespace(processNamespace(objectCPP.getQualfication())); resultObject = variable; // The following code would be an alternative, depending on whether we get @@ -260,7 +269,7 @@ public class MDMangGhidra extends MDMang { else { // Any others (e.g., case '9') DemangledVariable variable = - new DemangledVariable(objectCPP.getName()); + new DemangledVariable(mangledSource, demangledSource, objectCPP.getName()); variable.setNamespace(processNamespace(objectCPP.getQualfication())); resultObject = variable; // The following code would be an alternative, depending on whether we get @@ -287,13 +296,14 @@ public class MDMangGhidra extends MDMang { String baseName = objectCPP.getName(); if (objectCPP.isString()) { MDString mstring = objectCPP.getMDString(); - DemangledString demangledString = new DemangledString(mstring.getName(), - mstring.toString(), mstring.getLength(), mstring.isUnicode()); + DemangledString demangledString = + new DemangledString(mangledSource, demangledSource, mstring.getName(), + mstring.toString(), mstring.getLength(), mstring.isUnicode()); resultObject = demangledString; } else if (baseName.length() != 0) { DemangledVariable variable; - variable = new DemangledVariable(baseName); + variable = new DemangledVariable(mangledSource, demangledSource, baseName); variable.setNamespace(processNamespace(objectCPP.getQualfication())); resultObject = variable; } @@ -314,7 +324,8 @@ public class MDMangGhidra extends MDMang { // doesn't match // well to the current DemangledObject hierarchy. private DemangledVariable processTemplate(MDTemplateNameAndArguments template) { - DemangledVariable variable = new DemangledVariable(template.toString()); + DemangledVariable variable = + new DemangledVariable(mangledSource, demangledSource, template.toString()); // NO NAMESPACE for high level template: variable.setNamespace(XXX); // DemangledTemplate objectTemplate = new DemangledTemplate(); // DemangledDataType dataType = new DemangledDataType((String) null); @@ -397,7 +408,8 @@ public class MDMangGhidra extends MDMang { } private DemangledFunctionPointer processDemangledFunctionPointer(MDPointerType pointerType) { - DemangledFunctionPointer functionPointer = new DemangledFunctionPointer(); + DemangledFunctionPointer functionPointer = + new DemangledFunctionPointer(mangledSource, demangledSource); MDFunctionType functionType = (MDFunctionType) pointerType.getReferencedType(); functionPointer.setCallingConvention(functionType.getCallingConvention().toString()); functionPointer.setModifier(pointerType.getCVMod().toString()); @@ -432,7 +444,8 @@ public class MDMangGhidra extends MDMang { if (!((refType instanceof MDReferenceType) || (refType instanceof MDDataRefRefType))) { return null; // Not planning on anything else yet. } - DemangledFunctionReference functionReference = new DemangledFunctionReference(); + DemangledFunctionReference functionReference = + new DemangledFunctionReference(mangledSource, demangledSource); MDFunctionType functionType = (MDFunctionType) refType.getReferencedType(); functionReference.setCallingConvention(functionType.getCallingConvention().toString()); functionReference.setModifier(refType.getCVMod().toString()); @@ -447,7 +460,8 @@ public class MDMangGhidra extends MDMang { private DemangledFunctionIndirect processDemangledFunctionIndirect( MDFunctionIndirectType functionIndirectType) { - DemangledFunctionIndirect functionDefinition = new DemangledFunctionIndirect(); + DemangledFunctionIndirect functionDefinition = + new DemangledFunctionIndirect(mangledSource, demangledSource); MDFunctionType functionType = (MDFunctionType) functionIndirectType.getReferencedType(); functionDefinition.setCallingConvention(functionType.getCallingConvention().toString()); functionDefinition.setModifier(functionIndirectType.getCVMod().toString()); @@ -466,7 +480,8 @@ public class MDMangGhidra extends MDMang { // indirect might be clouded between the real, two underlying types. private DemangledFunctionIndirect processDemangledFunctionQuestion( MDModifierType modifierType) { - DemangledFunctionIndirect functionDefinition = new DemangledFunctionIndirect(); + DemangledFunctionIndirect functionDefinition = + new DemangledFunctionIndirect(mangledSource, demangledSource); MDFunctionType functionType = (MDFunctionType) modifierType.getReferencedType(); functionDefinition.setCallingConvention(functionType.getCallingConvention().toString()); functionDefinition.setModifier(modifierType.getCVMod().toString()); @@ -488,7 +503,8 @@ public class MDMangGhidra extends MDMang { private DemangledDataType processDataType(DemangledDataType resultDataType, MDDataType datatype) { if (resultDataType == null) { - resultDataType = new DemangledDataType(datatype.getTypeName()); + resultDataType = + new DemangledDataType(mangledSource, demangledSource, datatype.getTypeName()); } if (datatype.isSpecifiedSigned()) { // Returns true if default signed or specified signed. TODO: There is no place to @@ -805,4 +821,3 @@ public class MDMangGhidra extends MDMang { /******************************************************************************/ /******************************************************************************/ - diff --git a/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDBaseTestConfiguration.java b/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDBaseTestConfiguration.java index 92da2e0c9a..ae74fe6b5b 100644 --- a/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDBaseTestConfiguration.java +++ b/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDBaseTestConfiguration.java @@ -15,6 +15,8 @@ */ package mdemangler; +import static org.junit.Assert.*; + import ghidra.util.Msg; import mdemangler.datatype.MDDataType; @@ -65,7 +67,7 @@ public class MDBaseTestConfiguration { * @param mstruth Truth that was output from one of the Microsoft tools (e.g., undname). * @param ghtruth Truth that we would like to see for Ghidra version of the tool. * @param ms2013truth Like mstruth, but from Visual Studio 2013 version of tool. - * @throws Exception + * @throws Exception if any exceptions are thrown */ public void demangleAndTest(String mangledArg, String mdtruth, String mstruth, String ghtruth, String ms2013truth) throws Exception { @@ -105,24 +107,24 @@ public class MDBaseTestConfiguration { // expect to be able to demangle the input (truth not equal to mangleArg), then we // expect the output to be that which we desire ("truth".equals(demangled)). if ((truth.equals(mangledArg)) && isMangled(mangledArg)) { - assert (demangled.isEmpty()); + assertTrue(demangled.isEmpty()); } else { - assert(truth.equals(demangled)); + assertEquals(truth, demangled); } if (mangledArg.startsWith(".?A")) { - assert ((demangItem != null) && (demangItem instanceof MDDataType)); // Test for data type. + assertTrue((demangItem != null) && (demangItem instanceof MDDataType)); // Test for data type. } } - private boolean isMangled(String mangled) { - if (mangled.charAt(0) == '?') { + private boolean isMangled(String s) { + if (s.charAt(0) == '?') { return true; } - else if (mangled.startsWith("__")) { + else if (s.startsWith("__")) { return true; } - else if ((mangled.charAt(0) == '_') || Character.isUpperCase(mangled.charAt(1))) { + else if ((s.charAt(0) == '_') || Character.isUpperCase(s.charAt(1))) { return true; } return false; diff --git a/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDMangExtraTests.java b/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDMangExtraTests.java index 864884b080..af21d6ed53 100644 --- a/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDMangExtraTests.java +++ b/Ghidra/Features/MicrosoftDmang/src/test/java/mdemangler/MDMangExtraTests.java @@ -15,7 +15,7 @@ */ package mdemangler; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import org.junit.Test; @@ -46,7 +46,7 @@ public class MDMangExtraTests extends AbstractGenericTest { String demangled = item.toString(); assertEquals(wholeTruth, demangled); DemangledObject obj = demangler.getObject(); - String mangledFunctionNamespace = obj.getNamespace().getNamespace().getOriginalMangled(); + String mangledFunctionNamespace = obj.getNamespace().getNamespace().getMangledString(); assertEquals(functionNamespaceMangledTruth, mangledFunctionNamespace); item = demangler.demangle(mangledFunctionNamespace, true); diff --git a/Ghidra/Framework/Demangler/Module.manifest b/Ghidra/Framework/Demangler/Module.manifest deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Ghidra/Framework/Demangler/build.gradle b/Ghidra/Framework/Demangler/build.gradle deleted file mode 100644 index 4614e824cc..0000000000 --- a/Ghidra/Framework/Demangler/build.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" -apply from: "$rootProject.projectDir/gradle/javaProject.gradle" -apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle" -apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle" -apply plugin: 'eclipse' - -eclipse.project.name = 'Framework Demangler' - -dependencies { - compile project(':Utility') -} - diff --git a/Ghidra/Framework/Demangler/certification.manifest b/Ghidra/Framework/Demangler/certification.manifest deleted file mode 100644 index e9c2fe2942..0000000000 --- a/Ghidra/Framework/Demangler/certification.manifest +++ /dev/null @@ -1,3 +0,0 @@ -##VERSION: 2.0 -Module.manifest||GHIDRA||reviewed||END| -build.gradle||GHIDRA||||END| diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/CharacterIterator.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/CharacterIterator.java deleted file mode 100644 index 3a8fd0fcef..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/CharacterIterator.java +++ /dev/null @@ -1,249 +0,0 @@ -/* ### - * 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 util.demangler; - -/** - * A class for bidirectional iteration over a string. - * - * Iterators maintain a current character index, whose valid range is from - * 0 to string.length()-1. - * - * The current index can be retrieved by calling getIndex() and set directly - * by calling setIndex(). - * - * The methods previous() and next() are used for iteration. They return DONE if - * they would move outside the range from 0 to string.length()-1. - */ -public class CharacterIterator { - /** - * Constant that is returned when the iterator has reached either the end - * or the beginning of the text. The value is '\\uFFFF', the "not a - * character" value which should not occur in any valid Unicode string. - */ - public static final char DONE = '\uFFFF'; - - private String string; - private int index; - - /** - * Constructs a new character iterator using str. - * @param str the string to iterate - */ - public CharacterIterator(String str) { - this.string = str; - } - - /** - * Returns the underlying string. - * @return the underlying string - */ - public String getString() { - return string; - } - - /** - * Returns the current index. - * @return the current index. - */ - public int getIndex() { - return index; - } - - /** - * Returns the length of the iterator. - * @return the length of the iterator - */ - public int getLength() { - return string.length(); - } - - /** - * Sets the position to the specified position in the text. - * @param index the position within the text. - * @throws IllegalArgumentException if index is not in range from 0 to string.length()-1 - */ - public void setIndex(int index) { - if (index < 0 || index > string.length() - 1) { - throw new IllegalArgumentException(); - } - this.index = index; - } - - /** - * Returns true if there are more characters to read - * @return true if there are more characters to read - */ - public boolean hasNext() { - return index < string.length() - 1; - } - - /** - * Returns the next character without incrementing the current index. - * @return the next character without incrementing the current index - */ - public char peek() { - try { - return string.charAt(index); - } - catch (IndexOutOfBoundsException e) { - return DONE; - } - } - - /** - * Peeks at the character current index + lookAhead. - * Returns DONE if the computed position is out of range. - * @param lookAhead number of characters to look ahead - * @return the character at index+lookAhead - */ - public char peek(int lookAhead) { - try { - return string.charAt(index + lookAhead); - } - catch (IndexOutOfBoundsException e) { - return DONE; - } - } - - /** - * Increments the current index by one and returns the character - * at the new index. If the resulting index is greater or equal - * to the end index, the current index is reset to the end index and - * a value of DONE is returned. - * @return the character at the new position or DONE - */ - public char next() { - try { - return string.charAt(++index); - } - catch (IndexOutOfBoundsException e) { - index = string.length(); - return DONE; - } - } - - /** - * Returns the character at the current index and then increments the index by one. - * If the resulting index is greater or equal - * to the end index, the current index is reset to the end index and - * a value of DONE is returned. - * @return the character at the new position or DONE - */ - public char getAndIncrement() { - try { - return string.charAt(index++); - } - catch (IndexOutOfBoundsException e) { - index = string.length(); - return DONE; - } - } - - /** - * Decrements the current index by one and returns the character - * at the new index. If the current index is 0, the index - * remains at 0 and a value of DONE is returned. - * @return the character at the new position or DONE - */ - public char previous() { - try { - return string.charAt(--index); - } - catch (IndexOutOfBoundsException e) { - index = 0; - return DONE; - } - } - - /** - * Returns the next ascii string of the specified length starting - * at the current index. - * @param len the length of the string to read - * @return the next ascii string - */ - public String nextString(int len) { - String s = string.substring(index, index + len); - index = index + len; - return s; - } - - /** - * Returns the next integer. The radix must be 10 (decimal). - * For example, given "...12fred..". If current index is pointing - * to the '1', then this value will return 12. - * @return the next base-10 integer. - */ - public int nextInteger() { - int origIndex = index; - while (Character.isDigit(peek())) { - getAndIncrement(); - } - if (origIndex == index) { - return string.charAt(index) - '0'; - } - String s = string.substring(origIndex, index); - try { - return Integer.parseInt(s); - } - catch (NumberFormatException e) { - index = origIndex; - throw e; - } - } - - /** - * Looks for the next occurrence of 'c' starting - * at the current index. Returns the character - * position in the underlying string or -1 if 'c' - * is not found. - */ - public int find(char c) { - for (int i = index; i < string.length(); ++i) { - if (string.charAt(i) == c) { - return i; - } - } - return -1; - } - - @Override - public String toString() { - return "currnt = " + peek() + "; next = " + peek(1); - } - - public String getContext() { - StringBuilder buffy = new StringBuilder(); - - int amount = 5; - int start = index - amount; - start = Math.max(start, 0); - for (int i = start; i < index; i++) { - buffy.append(string.charAt(i)); - } - - buffy.append('[').append(string.charAt(index)).append(']'); - - int end = index + amount + 1; - end = Math.min(end, string.length()); - for (int i = index + 1; i < end; i++) { - buffy.append(string.charAt(i)); - } - - buffy.append(" @ ").append(index); - - return buffy.toString(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledAddressTable.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledAddressTable.java deleted file mode 100644 index 4fcd8f7c2a..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledAddressTable.java +++ /dev/null @@ -1,57 +0,0 @@ -/* ### - * 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 util.demangler; - -public class GenericDemangledAddressTable extends GenericDemangledObject { - - private int length; - - public GenericDemangledAddressTable(String name, int length) { - this.name = name; - this.length = length; - } - - /** - * Returns the length of the address table. - * -1 indicates the length is unknown. - * @return the length of the address table - */ - public int getLength() { - return length; - } - - @Override - public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); - - if (specialPrefix != null) { - buffer.append(specialPrefix); - buffer.append(' '); - } - - if (namespace != null) { - String namespaceStr = namespace.toSignature(); - buffer.append(namespaceStr); - if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) { - buffer.append(NAMESPACE_SEPARATOR); - } - } - - buffer.append(name); - - return buffer.toString(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledArray.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledArray.java deleted file mode 100644 index 9baccc6381..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledArray.java +++ /dev/null @@ -1,191 +0,0 @@ -/* ### - * 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 util.demangler; - -import java.util.regex.Matcher; - -public class GenericDemangledArray extends GenericDemangledDataType { - - private String dataType; - - public GenericDemangledArray(String name) { - super(name); - setArray(); - } - - public void setDataType(String dataType) { - this.dataType = dataType; - } - - public String getDataType() { - return dataType; - } - - @Override - public void copyInto(GenericDemangledVariable destination) { - super.copyInto(destination); - - if (dataType != null) { - GenericDemangledDataType dt = new GenericDemangledDataType(dataType); - destination.setDatatype(dt); - } - } - - /** - * Note: this code is a modified form of what was in the parent class, specifically to - * handle arrays. Also, feel free to jigger this around, as long as the tests pass, we are - * probably OK. There is probably a lot of code in this method that is not needed. - */ - @Override - public String toSignature() { - StringBuffer buffer = new StringBuffer(); - - if (isUnion) { - buffer.append(UNION).append(SPACE); - } - if (isStruct) { - buffer.append(STRUCT).append(SPACE); - } - if (isEnum) { - buffer.append(ENUM).append(SPACE); - } - if (isClass) { - buffer.append(CLASS).append(SPACE); - } - if (isComplex) { - buffer.append(COMPLEX).append(SPACE); - } - if (isVolatile) { - buffer.append(VOLATILE).append(SPACE); - } - if (isSigned) { - buffer.append(SIGNED).append(SPACE); - } - if (isUnsigned) { - buffer.append(UNSIGNED).append(SPACE); - } - - String space = ""; - if (dataType != null) { - buffer.append(space).append(dataType); - space = String.valueOf(SPACE); - } - - if (isConst()) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - - if (getNamespace() != null) { - buffer.append(getNamespace().toNamespace()); - } - - if (getName() != null) { - buffer.append(getName()); - space = String.valueOf(SPACE); - } - - if (getTemplate() != null) { - buffer.append(getTemplate().toTemplate()); - space = String.valueOf(SPACE); - } - - if (isUnaligned) { - buffer.append(space).append(UNALIGNED); - space = String.valueOf(SPACE); - } - - if (isFar) { - buffer.append(space).append(FAR); - space = String.valueOf(SPACE); - } - - if (isRestrict) { - buffer.append(space).append(RESTRICT); - space = String.valueOf(SPACE); - } - - handlePointer(buffer, space); - - if (isReference) { - - // ugly, but MS does this - boolean hasPointers = pointerLevels >= 1; - if (isConst() && hasPointers) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - - buffer.append(space).append(REF_NOTATION); - space = String.valueOf(SPACE); - } - - handleTrailingPointer(buffer, space); - - if (isArray) { - Matcher matcher = ARRAY_SUBSCRIPT_PATTERN.matcher(getName()); - if (!matcher.find()) { - // only put subscript on if the name doesn't have it - buffer.append(ARR_NOTATION); - } - } - return buffer.toString(); - } - - private void handlePointer(StringBuffer buffer, String space) { - String myName = getName(); - if (myName.contains("*")) { - return; // don't add pointer notation if it is already in the name - } - - boolean hasPointers = pointerLevels >= 1; - if (hasPointers) { - buffer.append(space + PTR_NOTATION); - space = String.valueOf(SPACE); - } - } - - private void handleTrailingPointer(StringBuffer buffer, String space) { -// not sure if we need this here -// String myName = getName(); -// if (myName.contains("*")) { -// return; // don't add pointer notation if it is already in the name -// } - - if (isPointer64) { - buffer.append(space).append(PTR64); - space = String.valueOf(SPACE); - } - - for (int i = 1; i < pointerLevels; i++) { - - // ugly, but MS does this - if (isConst()) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - - buffer.append(space).append(PTR_NOTATION); - space = String.valueOf(SPACE); - - // ugly, but MS does this - if (isPointer64) { - buffer.append(space).append(PTR64); - space = String.valueOf(SPACE); - } - } - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledConstants.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledConstants.java deleted file mode 100644 index 549cefbf3b..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledConstants.java +++ /dev/null @@ -1,59 +0,0 @@ -/* ### - * 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. - * 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 util.demangler; - -public final class GenericDemangledConstants { - - public final static String VISIBILITY_public = "public"; - public final static String VISIBILITY_protected = "protected"; - public final static String VISIBILITY_private = "private"; - public final static String VISIBILITY_static = "static"; - public final static String VISIBILITY_global = "global"; - public final static String VISIBILITY_virtual = "virtual"; - - public final static String[] VISIBILITY_ARR = { VISIBILITY_public, VISIBILITY_protected, - VISIBILITY_private, VISIBILITY_static, VISIBILITY_global, VISIBILITY_virtual, }; - - public final static boolean isVisibility(String visibility) { - return contains(VISIBILITY_ARR, visibility); - } - - ///////////////////////////////////////////////////// - - public final static String STORAGE_CLASS_const = "const"; - public final static String STORAGE_CLASS_volatile = "volatile"; - public final static String STORAGE_CLASS_far = "far"; - public final static String STORAGE_CLASS_restrict = "restrict"; - - public final static String[] STORAGE_CLASS_ARR = { STORAGE_CLASS_const, STORAGE_CLASS_volatile, - STORAGE_CLASS_far, STORAGE_CLASS_restrict, }; - - public final static boolean isStorageClass(String storageClass) { - return contains(STORAGE_CLASS_ARR, storageClass); - } - - ///////////////////////////////////////////////////// - - private final static boolean contains(String[] array, String target) { - for (String element : array) { - if (element.equals(target)) { - return true; - } - } - return false; - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledDataType.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledDataType.java deleted file mode 100644 index b8857f710a..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledDataType.java +++ /dev/null @@ -1,579 +0,0 @@ -/* ### - * 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 util.demangler; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A class to represent a demangled data type. - */ -public class GenericDemangledDataType extends GenericDemangledType { - - protected static final Pattern ARRAY_SUBSCRIPT_PATTERN = Pattern.compile("\\[\\d*\\]"); - - public static final char SPACE = ' '; - - private static final String STATIC = "static"; - - public static final String UNALIGNED = "__unaligned"; - public static final String UNSIGNED = "unsigned"; - public static final String SIGNED = "signed"; - - public static final String ARR_NOTATION = "[]"; - public static final String REF_NOTATION = "&"; - public static final String PTR_NOTATION = "*"; - - public static final String VOLATILE = "volatile"; - public static final String COMPLEX = "complex"; - public static final String CLASS = "class"; - public static final String ENUM = "enum"; - public static final String STRUCT = "struct"; - public static final String UNION = "union"; - public static final String COCLASS = "coclass"; - public static final String COINTERFACE = "cointerface"; - public static final String CONST = "const"; - protected static final String FAR = "far"; - protected static final String RESTRICT = "restrict"; - - public final static String VARARGS = "..."; - public final static String VOID = "void"; - public final static String BOOL = "bool"; - public final static String CHAR = "char"; - public final static String WCHAR_T = "wchar_t"; - public final static String SHORT = "short"; - public final static String INT = "int"; - public final static String INT0_T = "int0_t";//TODO - public final static String LONG = "long"; - public final static String LONG_LONG = "long long"; - public final static String FLOAT = "float"; - public final static String DOUBLE = "double"; - public final static String INT64 = "__int64"; - public final static String INT128 = "__int128";//TODO - public final static String FLOAT128 = "__float128";//TODO - public final static String LONG_DOUBLE = "long double"; - public final static String PTR64 = "__ptr64"; - public final static String STRING = "string"; - - public final static String[] PRIMITIVES = { VOID, BOOL, CHAR, WCHAR_T, SHORT, INT, INT0_T, LONG, - LONG_LONG, FLOAT, DOUBLE, INT128, FLOAT128, LONG_DOUBLE, }; - - /** private/protected/public */ - protected String access; - - protected boolean isStatic; - protected boolean isArray; - protected boolean isClass; - protected boolean isComplex; - protected boolean isEnum; - protected boolean isPointer64; - protected boolean isReference; - protected boolean isSigned;//explicitly signed! - protected boolean isStruct; - protected boolean isTemplate; - protected boolean isUnaligned; - protected boolean isUnion; - protected boolean isUnsigned; - protected boolean isVarArgs; - protected boolean isVolatile; - protected int pointerLevels = 0; - protected boolean isFar; - protected boolean isRestrict; - //This basedAttributte is an attribute on a modified type (such as a pointer) in the - // Microsoft model, which declares what the modified type is based on. Search the - // Internet for "Microsoft based pointer" to get a better explanation of its usage - // (I imagine that it is implemented as a hidden pointer index). - protected String basedAttribute; - protected String memberScope; - protected boolean isCoclass; - protected boolean isCointerface; - - /** - * Constructs a new demangled datatype. - * @param name the name of the datatype - */ - public GenericDemangledDataType(String name) { - super(name); - } - - public GenericDemangledDataType copy() { - GenericDemangledDataType copy = new GenericDemangledDataType(getName()); - copyInto(copy); - return copy; - } - - public void copyInto(GenericDemangledDataType destination) { - GenericDemangledDataType source = this; - - // note: for now this copy is additive for the attributes in that it won't turn off - // an attribute that was already on. If this is not what we want, then we may - // need a second copy method. - - destination.isStatic |= source.isStatic; - destination.isArray |= source.isArray; - destination.isClass |= source.isClass; - destination.isComplex |= source.isComplex; - destination.isEnum |= source.isEnum; - destination.isPointer64 |= source.isPointer64; - destination.isReference |= source.isReference; - destination.isSigned |= source.isSigned; - destination.isStruct |= source.isStruct; - destination.isTemplate |= source.isTemplate; - destination.isUnaligned |= source.isUnaligned; - destination.isUnion |= source.isUnion; - destination.isUnsigned |= source.isUnsigned; - destination.isVarArgs |= source.isVarArgs; - destination.isVolatile |= source.isVolatile; - - destination.pointerLevels = destination.pointerLevels + source.pointerLevels; // ? - destination.isFar |= source.isFar; - destination.isRestrict |= source.isRestrict; - - updateAccess(destination, source); - destination.setNamespace(source.getNamespace()); - destination.setTemplate(source.getTemplate()); - destination.basedAttribute = source.basedAttribute; - destination.memberScope = source.memberScope; - - destination.isCoclass |= source.isCoclass; - destination.isCointerface |= source.isCointerface; - - if (source.isConst()) { - destination.setConst(); - } - if (source.isVolatile()) { - destination.setVolatile(); - } - } - - private void updateAccess(GenericDemangledDataType destination, - GenericDemangledDataType source) { - - String currentAccess = destination.getAccess(); - if (currentAccess != null && !currentAccess.trim().isEmpty()) { - // don't overwrite the current access (if we need to, we can write a combining algorithm) - return; - } - - destination.setAccess(source.getAccess()); - } - - public void copyInto(GenericDemangledVariable destination) { - - GenericDemangledDataType source = this; - - List list = new ArrayList<>(); - if (source.isConst()) { - list.add("const"); - } - if (source.isVolatile) { - list.add("volatile"); - } - if (source.isFar) { - list.add("far"); - } - if (source.isRestrict) { - list.add("restrict"); - } - - StringBuilder buffy = new StringBuilder(); - for (String string : list) { - buffy.append(string).append(' '); - } - - // - // Note: this method is crossing a bridge from one hierarchy to another. The values - // in the other type are not a one-to-one match, as is the case when copying - // into variables in this class's type hierarchy. So, we just add values to this - // method as we find them. - // - String storage = buffy.toString().trim(); - destination.setStorageClass(storage.isEmpty() ? null : storage); - - destination.setStatic(source.isStatic()); - destination.setVisibilty(source.getAccess()); - - // TODO merge the hierarchies!! so that we don't have to different signature generation - // and this method becomes like the one above. - - if (source.isStruct) { - destination.setStruct(); - } - - if (source.isUnsigned) { - destination.setUnsigned(); - } - } - - public int getPointerLevels() { - return pointerLevels; - } - - public void setPointerLevels(int levels) { - this.pointerLevels = levels; - } - - public void incrementPointerLevels() { - pointerLevels++; - } - - public void setAccess(String access) { - this.access = access; - } - - public String getAccess() { - return access; - } - - public void setStatic() { - isStatic = true; - } - - public boolean isStatic() { - return isStatic; - } - - public void setArray() { - isArray = true; - } - - public void setClass() { - isClass = true; - } - - public void setComplex() { - isComplex = true; - } - - public void setEnum() { - isEnum = true; - } - - public void setPointer64() { - isPointer64 = true; - } - - public void setReference() { - isReference = true; - } - - public void setSigned() { - isSigned = true; - } - - public void setStruct() { - isStruct = true; - } - - public void setTemplate() { - isTemplate = true; - } - - public void setUnion() { - isUnion = true; - } - - public void setCoclass() { - isCoclass = true; - } - - public void setCointerface() { - isCointerface = true; - } - - public void setUnsigned() { - isUnsigned = true; - } - - public void setUnaligned() { - isUnaligned = true; - } - - public boolean isUnaligned() { - return isUnaligned; - } - - public void setVarArgs() { - isVarArgs = true; - } - - @Override - public void setVolatile() { - isVolatile = true; - } - - public void setFar() { - isFar = true; - } - - public boolean isFar() { - return isFar; - } - - public void setRestrict() { - isRestrict = true; - } - - public boolean isRestrict() { - return isRestrict; - } - - public boolean isArray() { - return isArray; - } - - public boolean isClass() { - return isClass; - } - - public boolean isComplex() { - return isComplex; - } - - public boolean isEnum() { - return isEnum; - } - - public boolean isPointer() { - return pointerLevels > 0; - } - - public boolean isPointer64() { - return isPointer64; - } - - public boolean isReference() { - return isReference; - } - - public boolean isSigned() { - return isSigned; - } - - public boolean isStruct() { - return isStruct; - } - - public boolean isTemplate() { - return isTemplate; - } - - public boolean isUnion() { - return isUnion; - } - - public boolean isCoclass() { - return isCoclass; - } - - public boolean isCointerface() { - return isCointerface; - } - - public boolean isUnsigned() { - return isUnsigned; - } - - public boolean isVarArgs() { - return isVarArgs; - } - - public boolean isVoid() { - return VOID.equals(getName()); - } - - @Override - public boolean isVolatile() { - return isVolatile; - } - - public String getBasedName() { - return basedAttribute; - } - - public void setBasedName(String basedName) { - this.basedAttribute = basedName; - } - - public String getMemberScope() { - return memberScope; - } - - public void setMemberScope(String memberScope) { - this.memberScope = memberScope; - } - - public boolean isPrimitive() { - boolean isPrimitiveDT = - !(isArray || isClass || isComplex || isEnum || isPointer() || isPointer64 || isSigned || - isTemplate || isUnion || isCoclass || isCointerface || isVarArgs || isVolatile); - if (isPrimitiveDT) { - for (String primitiveNames : PRIMITIVES) { - if (getName().equals(primitiveNames)) { - return true; - } - } - } - return false; - } - - @Override - public String toSignature() { - StringBuffer buffer = new StringBuffer(); - - if (access != null) { - buffer.append(access).append(SPACE); - } - - if (isStatic) { - buffer.append(STATIC).append(SPACE); - } - - if (isUnion) { - buffer.append(UNION).append(SPACE); - } - if (isStruct) { - buffer.append(STRUCT).append(SPACE); - } - if (isEnum) { - buffer.append(ENUM).append(SPACE); - } - if (isClass) { - buffer.append(CLASS).append(SPACE); - } - if (isCoclass) { - buffer.append(COCLASS).append(SPACE); - } - if (isCointerface) { - buffer.append(COINTERFACE).append(SPACE); - } - if (isComplex) { - buffer.append(COMPLEX).append(SPACE); - } - if (isSigned) { - buffer.append(SIGNED).append(SPACE); - } - if (isUnsigned) { - buffer.append(UNSIGNED).append(SPACE); - } - - if (getNamespace() != null) { - buffer.append(getNamespace().toNamespace()); - } - - String space = ""; - if (getName() != null) { - buffer.append(getName()); - space = String.valueOf(SPACE); - } - - if (getTemplate() != null) { - buffer.append(getTemplate().toTemplate()); - space = String.valueOf(SPACE); - } - - if (isConst()) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - - if (isVolatile()) { - buffer.append(space).append(VOLATILE); - space = String.valueOf(SPACE); - } - - if (isUnaligned) { - buffer.append(space).append(UNALIGNED); - space = String.valueOf(SPACE); - } - - if (isFar) { - buffer.append(space).append(FAR); - space = String.valueOf(SPACE); - } - - if (isRestrict) { - buffer.append(space).append(RESTRICT); - space = String.valueOf(SPACE); - } - - boolean hasPointers = pointerLevels >= 1; - if (hasPointers) { - buffer.append(space + PTR_NOTATION); - space = String.valueOf(SPACE); - } - - if (isReference) { - - // ugly, but MS does this - if (isConst() && hasPointers) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - if (isVolatile() && hasPointers) { - buffer.append(space).append(VOLATILE); - space = String.valueOf(SPACE); - } - - buffer.append(space).append(REF_NOTATION); - space = String.valueOf(SPACE); - } - - if (isPointer64) { - buffer.append(space).append(PTR64); - space = String.valueOf(SPACE); - } - - for (int i = 1; i < pointerLevels; i++) { - - // ugly, but MS does this - if (isConst()) { - buffer.append(space).append(CONST); - space = String.valueOf(SPACE); - } - if (isVolatile()) { - buffer.append(space).append(VOLATILE); - space = String.valueOf(SPACE); - } - - buffer.append(space).append(PTR_NOTATION); - space = String.valueOf(SPACE); - - // ugly, but MS does this - if (isPointer64) { - buffer.append(space).append(PTR64); - space = String.valueOf(SPACE); - } - } - - if (isArray) { - Matcher matcher = ARRAY_SUBSCRIPT_PATTERN.matcher(getName()); - if (!matcher.find()) { - // only put subscript on if the name doesn't have it - buffer.append(ARR_NOTATION); - } - } - return buffer.toString(); - } - - @Override - public String toString() { - return toSignature(); - } - -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledException.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledException.java deleted file mode 100644 index 44bcb4e158..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledException.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ### - * 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. - * 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 util.demangler; - -/** - * A class to handle exceptions that occur demangling. - */ -public class GenericDemangledException extends Exception { - private boolean invalidMangledName; - - /** - * Use this constructor to indicate a demangler exception - * due to an exception thrown during the demangling process. - * @param cause the exception thrown during the demangling process - */ - public GenericDemangledException(Exception cause) { - super(cause); - } - - /** - * Use this constructor to indicate a demangler exception - * due to some general invalid or unsupported mangled string - * characteristic. For example, unrecognized datatype. - * @param message the invalid or unsupported mangled message - */ - public GenericDemangledException(String message) { - super(message); - } - - /** - * Use this constructor to indicate the demangler failed - * because the string to demangle does not appear to represent - * a valid mangled name. - * @param invalidMangledName true to indicate the string to - * demangle does not appear to represent a valid mangled name - */ - public GenericDemangledException(boolean invalidMangledName) { - this.invalidMangledName = invalidMangledName; - } - - /** - * Returns true if the string to demangle does not appear to represent - * a valid mangled name - * @return true if the string to demangle does not appear to represent - * a valid mangled name - */ - public boolean isInvalidMangledName() { - return invalidMangledName; - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunction.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunction.java deleted file mode 100644 index 7582047469..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunction.java +++ /dev/null @@ -1,241 +0,0 @@ -/* ### - * 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 util.demangler; - -import java.util.*; - -/** - * A class to represent a demangled function. - */ -public class GenericDemangledFunction extends GenericDemangledObject implements ParameterReceiver { - - protected GenericDemangledDataType returnType; - protected String callingConvention;// __cdecl, __thiscall, etc. - protected boolean thisPassedOnStack = true; - protected List parameterList = - new ArrayList(); - protected GenericDemangledTemplate template; - protected boolean isOverloadedOperator = false; - private boolean virtual = false; - - /** Special constructor where it has a templated type before the parameter list */ - private String templatedConstructorType; - - /** - * Constructs a new demangled function. - * @param name the name of the function - */ - public GenericDemangledFunction(String name) throws GenericDemangledException { - if (name == null) { - throw new GenericDemangledException( - "Function name cannot be null; failed to parse mangled name properly"); - } - this.name = name; - } - - /** - * Sets the function return type. - * @param returnType the function return type - */ - public void setReturnType(GenericDemangledDataType returnType) { - this.returnType = returnType; - } - - /** - * Sets the function calling convention. For example, "__cdecl". - * @param callingConvention the function calling convention - */ - public void setCallingConvention(String callingConvention) { - this.callingConvention = callingConvention; - } - - /** - * 'this' is passed on the stack or false if in a register - * - */ - public void setThisPassedOnStack(boolean thisPassedOnStack) { - this.thisPassedOnStack = thisPassedOnStack; - } - - public boolean isPassedOnStack() { - return thisPassedOnStack; - } - - public void setTemplate(GenericDemangledTemplate template) { - this.template = template; - } - - public GenericDemangledTemplate getTemplate() { - return template; - } - - public void setVirtual() { - this.virtual = true; - } - - public boolean isVirtual() { - return virtual; - } - - /** - * Sets whether this demangled function represents - * an overloaded operator. For example, "operator+()". - * @param isOverloadedOperator true if overloaded operator - */ - public void setOverloadedOperator(boolean isOverloadedOperator) { - this.isOverloadedOperator = isOverloadedOperator; - } - - public boolean isOverloadedOperator() { - return isOverloadedOperator; - } - - /** - * @see ghidra.app.util.demangler.ParameterReceiver - */ - @Override - public void addParameter(GenericDemangledDataType parameter) { - parameterList.add(parameter); - } - - /** - * @see ghidra.app.util.demangler.ParameterReceiver - */ - @Override - public List getParameters() { - return new ArrayList(parameterList); - } - - /** - * Returns the return type or null, if unspecified. - * @return the return type or null, if unspecified - */ - public GenericDemangledDataType getReturnType() { - return returnType; - } - - /** - * Returns the calling convention or null, if unspecified. - * @return the calling convention or null, if unspecified - */ - public String getCallingConvention() { - return callingConvention; - } - - /** Special constructor where it has a templated type before the parameter list */ - public void setTemplatedConstructorType(String type) { - this.templatedConstructorType = type; - } - - @Override - public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); - - if (!(returnType instanceof GenericDemangledFunctionPointer)) { - buffer.append(specialPrefix == null ? "" : specialPrefix + " "); - buffer.append(visibility == null || "global".equals(visibility) ? "" : visibility + " "); - - if (isStatic()) { - buffer.append("static "); - } - - if (virtual) { - buffer.append("virtual "); - } - buffer.append(returnType == null ? "" : returnType.toSignature() + " "); - } - - buffer.append(callingConvention == null ? "" : callingConvention + " "); - if (namespace != null) { - buffer.append(namespace.toNamespace()); - } - - buffer.append(name); - if (template != null) { - buffer.append(template.toTemplate()); - } - - if (specialMidfix != null) { - buffer.append('[').append(specialMidfix).append(']'); - } - - // check for special case of 'conversion operator' where we only want to display '()' and - // not (void) - if (name.endsWith("()")) { - if (name.equals("operator")) { - buffer.append("()"); - } - } - else { - if (templatedConstructorType != null) { - buffer.append('<').append(templatedConstructorType).append('>'); - } - - Iterator paramIterator = parameterList.iterator(); - buffer.append('('); - String pad = format ? pad(buffer.length()) : ""; - if (!paramIterator.hasNext()) { - buffer.append("void"); - } - - while (paramIterator.hasNext()) { - buffer.append(paramIterator.next().toSignature()); - if (paramIterator.hasNext()) { - buffer.append(','); - if (format) { - buffer.append('\n'); - } - buffer.append(pad); - } - } - buffer.append(')'); - buffer.append(storageClass == null ? "" : " " + storageClass); - } - - if (returnType instanceof GenericDemangledFunctionPointer) { - GenericDemangledFunctionPointer funcPtr = (GenericDemangledFunctionPointer) returnType; - String partialSig = funcPtr.toSignature(buffer.toString()); - buffer = new StringBuffer(); - buffer.append(specialPrefix == null ? "" : specialPrefix + " "); - buffer.append(visibility == null || "global".equals(visibility) ? "" : visibility + " "); - if (virtual) { - buffer.append("virtual "); - } - buffer.append(partialSig); - } - else { - if (specialSuffix != null) { - buffer.append(specialSuffix); - } - } - return buffer.toString(); - } - - public String getParameterString() { - StringBuffer buffer = new StringBuffer(); - buffer.append('('); - Iterator dditer = parameterList.iterator(); - while (dditer.hasNext()) { - buffer.append(dditer.next().toSignature()); - if (dditer.hasNext()) { - buffer.append(','); - } - } - buffer.append(')'); - return buffer.toString(); - } - -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunctionPointer.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunctionPointer.java deleted file mode 100644 index 29c359c48f..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledFunctionPointer.java +++ /dev/null @@ -1,273 +0,0 @@ -/* ### - * 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 util.demangler; - -import java.util.ArrayList; -import java.util.List; - -/** - * A class to represent a demangled function pointer. - */ -public class GenericDemangledFunctionPointer extends GenericDemangledDataType - implements ParameterReceiver { - - private static final String DEFAULT_NAME_PREFIX = "FuncDef"; - private static final String EMPTY_STRING = ""; - private static final Object NAMESPACE_DELIMITER = "::"; - private static int ID = 0; - private GenericDemangledDataType returnType; - protected String callingConvention;// __cdecl, __thiscall, etc. - private List parameters = new ArrayList<>(); - - private boolean isConstPointer; - private String parentName; - private boolean isTrailingPointer64; - - /** - * Constructs a new demangled function pointer. - */ - public GenericDemangledFunctionPointer() { - super(DEFAULT_NAME_PREFIX + nextID()); - } - - /** - * Returns the return type. - * @return the return type - */ - public GenericDemangledDataType getReturnType() { - return returnType; - } - - /** - * Sets the return type. - * @param returnType the return type - */ - public void setReturnType(GenericDemangledDataType returnType) { - this.returnType = returnType; - } - - /** - * Returns the calling convention or null, if unspecified. - * @return the calling convention or null, if unspecified - */ - public String getCallingConvention() { - return callingConvention; - } - - /** - * Sets the function calling convention. For example, "__cdecl". - * @param callingConvention the function calling convention - */ - public void setCallingConvention(String callingConvention) { - this.callingConvention = callingConvention; - } - - /** - * Adds a parameters to the end of the parameter list for - * this demangled function. - * @param parameter the new parameter to add - */ - @Override - public void addParameter(GenericDemangledDataType parameter) { - parameters.add(parameter); - } - - /** - * Returns a list of the parameters for this demangled functions. - * @return a list of the parameters for this demangled functions - */ - @Override - public List getParameters() { - return new ArrayList<>(parameters); - } - - @Override - public GenericDemangledDataType copy() { - GenericDemangledFunctionPointer copy = new GenericDemangledFunctionPointer(); - copyInto(copy); - return copy; - } - - @Override - public void copyInto(GenericDemangledDataType destination) { - super.copyInto(destination); - - GenericDemangledFunctionPointer source = this; - - if (destination instanceof GenericDemangledFunctionPointer) { - GenericDemangledFunctionPointer copySource = source; - GenericDemangledFunctionPointer copyDestination = - (GenericDemangledFunctionPointer) destination; - - if (copySource.returnType != null) { - copyDestination.returnType = copySource.returnType.copy(); - } - for (GenericDemangledDataType parameter : copySource.parameters) { - copyDestination.parameters.add(parameter.copy()); - } - - copyDestination.callingConvention = copySource.callingConvention; - - copyDestination.isConstPointer |= copySource.isConstPointer; - } - } - - @Override - public String toSignature() { - return toSignature(null); - } - - public String toSignature(String name) { - StringBuffer buffer = new StringBuffer(); - - if (returnType != null) { - buffer.append(returnType.toSignature()).append(SPACE); - } - - String s = getConventionPointerNameString(name); - if (s.contains(" ") || s.isEmpty()) { - // spaces--add parens - buffer.append('(').append(s).append(')'); - } - else {// this allows the '__cdecl' in templates to not have parens - buffer.append(s); - } - - buffer.append('('); - for (int i = 0; i < parameters.size(); ++i) { - buffer.append(parameters.get(i).toSignature()); - if (i < parameters.size() - 1) { - buffer.append(','); - } - } - buffer.append(')'); - - if (isConst()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(CONST); - } - - if (isVolatile()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(VOLATILE); - } - - if (isTrailingPointer64) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - return buffer.toString(); - } - - private String getConventionPointerNameString(String name) { - StringBuilder buffer = new StringBuilder(); - buffer.append(callingConvention == null ? EMPTY_STRING : callingConvention); - - int pointerLevels = getPointerLevels(); - if (pointerLevels > 0) { - if (callingConvention != null) { - buffer.append(SPACE); - } - - addParentName(buffer); - - for (int i = 0; i < pointerLevels; ++i) { - buffer.append('*'); - } - } - - if (isConstPointer) { - buffer.append(CONST); - } - - if (isPointer64()) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(PTR64); - } - - if (name != null) { - if (buffer.length() > 2) { - buffer.append(SPACE); - } - buffer.append(name); - } - - return buffer.toString(); - } - - private void addParentName(StringBuilder buffer) { - if (parentName == null) { - return; - } - - if (parentName.startsWith(DEFAULT_NAME_PREFIX)) { - return; - } - - if (buffer.length() > 2) { - char lastChar = buffer.charAt(buffer.length() - 1); - if (SPACE != lastChar) { - buffer.append(SPACE); - } - } - buffer.append(parentName).append(NAMESPACE_DELIMITER); - } - - public void setConstPointer() { - isConstPointer = true; - } - - public boolean isConstPointer() { - return isConstPointer; - } - - public void setParentName(String parentName) { - this.parentName = parentName; - } - - public String getParentName() { - return parentName; - } - - public void setTrailingPointer64() { - this.isTrailingPointer64 = true;// TODO get real construct name for this method/field - } - - public boolean isTrailingPointer64() { - return isTrailingPointer64; - } - - public void clearPointer64() { - this.isPointer64 = false; - } - - private synchronized static int nextID() { - return ID++; - } - - public int getID() { - return ID; - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledObject.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledObject.java deleted file mode 100644 index 54c8fab421..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledObject.java +++ /dev/null @@ -1,263 +0,0 @@ -/* ### - * 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 util.demangler; - -/** - * A class to represent a demangled object. - */ -public abstract class GenericDemangledObject { - - protected static final String NAMESPACE_SEPARATOR = "::"; - protected static final String AT = "@"; - - protected static final String EMPTY_STRING = ""; - protected static final String SPACE = " "; - - protected String originalMangled; - protected String specialPrefix; - protected String specialMidfix; - protected String specialSuffix; - protected GenericDemangledType namespace; - protected String visibility;//public, protected, etc. - protected String storageClass;//const, volatile, etc - protected String name; - protected boolean isConst; - protected boolean isVolatile; - protected boolean isStatic; - protected boolean isVirtual; - protected boolean isThunk; - protected boolean isPointer64; - // temp - protected boolean isStruct; - protected boolean isUnsigned; - protected boolean isUnaligned; - protected boolean isRestrict; - protected String basedName; - protected String memberScope; - - private String signature; - - /** - * Returns the name of the demangled object. - * @return the name of the demangled object - */ - public String getName() { - return name; - } - - public boolean isConst() { - return isConst; - } - - public void setConst(boolean isConst) { - this.isConst = isConst; - } - - public boolean isVolatile() { - return isVolatile; - } - - public void setVolatile(boolean isVolatile) { - this.isVolatile = isVolatile; - } - - public boolean isStatic() { - return isStatic; - } - - public void setStatic(boolean isStatic) { - this.isStatic = isStatic; - } - - public boolean isVirtual() { - return isVirtual; - } - - public void setVirtual(boolean isVirtual) { - this.isVirtual = isVirtual; - } - - public boolean isThunk() { - return isThunk; - } - - public void setThunk(boolean isThunk) { - this.isThunk = isThunk; - } - - public boolean isPointer64() { - return isPointer64; - } - - public void setPointer64(boolean isPointer64) { - this.isPointer64 = isPointer64; - } - - public void setUnsigned() { - isUnsigned = true; - } - - public void setStruct() { - isStruct = true; - } - - public void setUnaligned() { - isUnaligned = true; - } - - public boolean isUnaligned() { - return isUnaligned; - } - - public void setRestrict() { - isRestrict = true; - } - - public boolean isRestrict() { - return isRestrict; - } - - public String getBasedName() { - return basedName; - } - - public void setBasedName(String basedName) { - this.basedName = basedName; - } - - public String getMemberScope() { - return memberScope; - } - - public void setMemberScope(String memberScope) { - this.memberScope = memberScope; - } - - /** - * Sets the name of the demangled object - * @param name the new name - */ - public void setName(String name) { - this.name = name; - } - - /** - * Sets the original mangled name - * @param mangled the original mangled name - */ - public void setOriginalMangled(String mangled) { - this.originalMangled = mangled; - } - - public String getOriginalMangled() { - return originalMangled; - } - - /** - * Returns the namespace containing this demangled object. - * @return the namespace containing this demangled object - */ - public GenericDemangledType getNamespace() { - return namespace; - } - - /** - * - * @param namespace - */ - public void setNamespace(GenericDemangledType namespace) { - this.namespace = namespace; - } - - public String getVisibility() { - return visibility; - } - - public void setVisibilty(String visibility) { - this.visibility = visibility; - } - - public String getStorageClass() { - return storageClass; - } - - public void setStorageClass(String storageClass) { - this.storageClass = storageClass; - } - - public String getSpecialPrefix() { - return specialPrefix; - } - - public void setSpecialPrefix(String special) { - this.specialPrefix = special; - } - - public String getSpecialMidfix() { - return specialMidfix; - } - - public void setSpecialMidfix(String chargeType) { - this.specialMidfix = chargeType; - } - - public String getSpecialSuffix() { - return specialSuffix; - } - - public void setSpecialSuffix(String specialSuffix) { - this.specialSuffix = specialSuffix; - } - - /** - * Returns a complete signature for the demangled symbol. - *
For example: - * {@code "unsigned long foo" - * "unsigned char * ClassA::getFoo(float, short *)" - * "void * getBar(int **, MyStruct &)"} - *
Note: based on the underlying mangling scheme, the - * return type may or may not be specified in the signature. - * @param format true if signature should be pretty printed - * @return a complete signature for the demangled symbol - */ - public abstract String getSignature(boolean format); - - /** - * Sets the signature. Calling this method will - * override the auto-generated signature. - * @param signature the signature - */ - public void setSignature(String signature) { - this.signature = signature; - } - - @Override - public String toString() { - return getSignature(false); - } - - protected String generatePlateComment() { - return (signature == null) ? getSignature(true) : signature; - } - - protected String pad(int len) { - StringBuffer buffer = new StringBuffer(); - for (int i = 0; i < len; i++) { - buffer.append(' '); - } - return buffer.toString(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledString.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledString.java deleted file mode 100644 index 99f94cc703..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledString.java +++ /dev/null @@ -1,66 +0,0 @@ -/* ### - * 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. - * 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 util.demangler; - -public class GenericDemangledString extends GenericDemangledObject { - private String string; - private int length; - private boolean unicode; - - public GenericDemangledString(String string, int length, boolean unicode) { - this.string = string; - this.length = length; - this.unicode = unicode; - } - - @Override - public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); - if (specialPrefix != null) { - buffer.append(specialPrefix + " for "); - } - buffer.append(string); - if (specialSuffix != null) { - buffer.append(" " + specialSuffix); - } - return buffer.toString(); - } - - /** - * Returns the demangled string. - * @return the demangled string - */ - public String getString() { - return string; - } - - /** - * Returns the length in bytes of the demangled string. - * @return the length in bytes of the demangled string - */ - public int getLength() { - return length; - } - - /** - * Returns true if the demangled string is unicode. - * @return true if the demangled string is unicode - */ - public boolean isUnicode() { - return unicode; - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledTemplate.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledTemplate.java deleted file mode 100644 index 8dc13e7a23..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledTemplate.java +++ /dev/null @@ -1,55 +0,0 @@ -/* ### - * 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. - * 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 util.demangler; - -import java.util.ArrayList; -import java.util.List; - -public class GenericDemangledTemplate implements ParameterReceiver { - private List parameters = new ArrayList(); - - public GenericDemangledTemplate() { - } - - @Override - public void addParameter(GenericDemangledDataType parameter) { - parameters.add(parameter); - } - - @Override - public List getParameters() { - return new ArrayList(parameters); - } - - public String toTemplate() { - StringBuffer buffer = new StringBuffer(); - buffer.append('<'); - for (int i = 0; i < parameters.size(); ++i) { - buffer.append(parameters.get(i).toSignature()); - if (i < parameters.size() - 1) { - buffer.append(','); - } - } - buffer.append('>'); - return buffer.toString(); - } - - @Override - public String toString() { - return toTemplate(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledType.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledType.java deleted file mode 100644 index 42f585a9c1..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledType.java +++ /dev/null @@ -1,101 +0,0 @@ -/* ### - * 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 util.demangler; - -public class GenericDemangledType { - private GenericDemangledType namespace; - private String name; - private GenericDemangledTemplate template; - private boolean isConst; - private boolean isVolatile; - - public GenericDemangledType(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public boolean isConst() { - return isConst; - } - - public void setConst() { - isConst = true; - } - - public boolean isVolatile() { - return isVolatile; - } - - public void setVolatile() { - isVolatile = true; - } - - public GenericDemangledType getNamespace() { - return namespace; - } - - public void setNamespace(GenericDemangledType namespace) { - if (this == namespace) { - throw new IllegalArgumentException("Attempt to set this.namespace == this!"); - } - this.namespace = namespace; - } - - public GenericDemangledTemplate getTemplate() { - return template; - } - - public void setTemplate(GenericDemangledTemplate template) { - this.template = template; - } - - public String toSignature() { - StringBuffer buffer = new StringBuffer(); - if (namespace != null) { - buffer.append(namespace.toNamespace()); - } - buffer.append(name); - if (template != null) { - buffer.append(template.toTemplate()); - } - return buffer.toString(); - } - - public String toNamespace() { - StringBuffer buffer = new StringBuffer(); - if (namespace != null) { - buffer.append(namespace.toNamespace()); - } - buffer.append(name); - if (template != null) { - buffer.append(template.toTemplate()); - } - buffer.append("::"); - return buffer.toString(); - } - - @Override - public String toString() { - return toSignature(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledVariable.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledVariable.java deleted file mode 100644 index 8e2d98535f..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/GenericDemangledVariable.java +++ /dev/null @@ -1,116 +0,0 @@ -/* ### - * 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 util.demangler; - -/** - * An interface to represent a demangled global variable. - */ -public class GenericDemangledVariable extends GenericDemangledObject { - private GenericDemangledDataType datatype; - - public GenericDemangledVariable(String name) { - this.name = name; - } - - public void setDatatype(GenericDemangledDataType datatype) { - this.datatype = datatype; - } - - /** - * Returns the data type of this variable. - * @return the data type of this variable - */ - public GenericDemangledDataType getDataType() { - return datatype; - } - - @Override - public String getSignature(boolean format) { - StringBuffer buffer = new StringBuffer(); - - buffer.append(visibility == null || "global".equals(visibility) ? EMPTY_STRING - : visibility + SPACE); - - if (isStatic()) { - buffer.append("static "); - } - - String spacer = EMPTY_STRING; - if (isUnsigned) { - buffer.append("unsigned"); - spacer = SPACE; - } - - if (isStruct) { - buffer.append("struct"); - spacer = SPACE; - } - - if (specialPrefix != null) { - buffer.append(specialPrefix); - spacer = SPACE; - } - - boolean hasName = (name != null) && !name.isEmpty(); - if (!(datatype instanceof GenericDemangledFunctionPointer)) { - - if (datatype != null) { - buffer.append(spacer); - buffer.append(datatype.toSignature()); - spacer = SPACE; - } - } - - // e.g., 'const' - this appears after the data type in MS land - if (storageClass != null) { - buffer.append(spacer).append(storageClass); - spacer = SPACE; - } - - if (namespace != null) { - - buffer.append(spacer); - spacer = EMPTY_STRING; - - buffer.append(namespace.toNamespace()); - - if (!hasName) { - int end = buffer.length(); - buffer.delete(end - 2, end); // strip off the last namespace characters - } - } - - if (hasName) { - buffer.append(spacer); - spacer = EMPTY_STRING; - buffer.append(name); - } - - buffer.append(specialMidfix == null ? EMPTY_STRING : specialMidfix + SPACE); - buffer.append(specialSuffix == null ? EMPTY_STRING : SPACE + specialSuffix); - - if (datatype instanceof GenericDemangledFunctionPointer) { - GenericDemangledFunctionPointer funcPtr = (GenericDemangledFunctionPointer) datatype; - return funcPtr.toSignature(buffer.toString()); - } - - if (isConst()) { - buffer.append(" const"); - } - - return buffer.toString().trim(); - } -} diff --git a/Ghidra/Framework/Demangler/src/main/java/util/demangler/ParameterReceiver.java b/Ghidra/Framework/Demangler/src/main/java/util/demangler/ParameterReceiver.java deleted file mode 100644 index 2111d31fde..0000000000 --- a/Ghidra/Framework/Demangler/src/main/java/util/demangler/ParameterReceiver.java +++ /dev/null @@ -1,37 +0,0 @@ -/* ### - * 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. - * 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 util.demangler; - -import java.util.List; - -/** - * A generic interface to represent - * object that support parameters. - */ -public interface ParameterReceiver { - /** - * Adds the specified parameter to this object. - * @param parameter the parameter to add - */ - public void addParameter(GenericDemangledDataType parameter); - - /** - * Returns the parameters added to this object. - * @return the parameters added to this object - */ - public List getParameters(); -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java index fe34929bb5..4448193db7 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java @@ -15,29 +15,78 @@ */ package docking.test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; -import java.awt.*; -import java.awt.datatransfer.*; -import java.awt.event.*; +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Window; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.stream.Collectors; -import javax.swing.*; +import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JRadioButton; +import javax.swing.JTabbedPane; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; import javax.swing.text.JTextComponent; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; -import org.junit.*; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; -import docking.*; +import docking.ActionContext; +import docking.ComponentPlaceholder; +import docking.ComponentProvider; +import docking.DialogComponentProvider; +import docking.DockableComponent; +import docking.DockingDialog; +import docking.DockingErrorDisplay; +import docking.DockingWindowManager; +import docking.EmptyBorderToggleButton; +import docking.Tool; import docking.action.DockingActionIf; import docking.action.ToggleDockingActionIf; import docking.actions.DockingToolActions; @@ -55,7 +104,9 @@ import generic.test.ConcurrentTestExceptionHandler; import generic.util.image.ImageUtils; import ghidra.GhidraTestApplicationLayout; import ghidra.framework.ApplicationConfiguration; -import ghidra.util.*; +import ghidra.util.ConsoleErrorDisplay; +import ghidra.util.ErrorDisplay; +import ghidra.util.Msg; import ghidra.util.exception.AssertException; import ghidra.util.task.SwingUpdateManager; import ghidra.util.worker.Worker; @@ -217,25 +268,9 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { } public static Window waitForWindowByTitleContaining(String text) { - return waitForWindowByTitleContaining(null, text, DEFAULT_WAIT_TIMEOUT); - } - - /** - * Deprecated - * @param parentWindow the window; unused - * @param text the window title text part - * @param timeoutMS the timeout; unused - * @return window - * @deprecated Instead call one of the methods that does not take a timeout - * (we are standardizing timeouts). The timeouts passed to this method will - * be ignored in favor of the standard value. - */ - @Deprecated - public static Window waitForWindowByTitleContaining(Window parentWindow, String text, - int timeoutMS) { // try at least one time - Window window = getWindowByTitleContaining(parentWindow, text); + Window window = getWindowByTitleContaining(null, text); if (window != null) { return window;// we found it...no waiting required } @@ -244,7 +279,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { int timeout = DEFAULT_WAIT_TIMEOUT; while (totalTime <= timeout) { - window = getWindowByTitleContaining(parentWindow, text); + window = getWindowByTitleContaining(null, text); if (window != null) { return window; } @@ -256,43 +291,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { "Timed-out waiting for window containg title '" + text + "'"); } - /** - * Waits for a window with the given name. If parentWindow is not null, then it - * will be used to find subordinate windows. If parentWindow is null, then all - * existing frames will be searched. - * - * @param parentWindow The parent of the window for which to search, or null to search all - * open frames - * @param title The title of the window for which to search - * @param timeoutMS The timeout after which this method will wait no more - * @return The window, if found, null otherwise. - * - * @deprecated Instead call one of the methods that does not take a timeout - * (we are standardizing timeouts). The timeouts passed to this method will - * be ignored in favor of the standard value. - */ - @Deprecated - public static Window waitForWindow(Window parentWindow, String title, int timeoutMS) { - - Window window = getWindowByTitle(parentWindow, title); - if (window != null) { - return window;// we found it...no waiting required - } - - int totalTime = 0; - int timeout = DEFAULT_WAIT_TIMEOUT; - while (totalTime <= timeout) { - - window = getWindowByTitle(parentWindow, title); - if (window != null) { - return window; - } - - totalTime += sleep(DEFAULT_WAIT_DELAY); - } - throw new AssertionFailedError("Timed-out waiting for window with title '" + title + "'"); - } - /** * Waits for a window with the given name. * @@ -1134,9 +1132,8 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { public static Set getActionsByOwnerAndName(Tool tool, String owner, String name) { Set ownerActions = tool.getDockingActionsByOwnerName(owner); - return ownerActions.stream() - .filter(action -> action.getName().equals(name)) - .collect(Collectors.toSet()); + return ownerActions.stream().filter(action -> action.getName().equals(name)).collect( + Collectors.toSet()); } /** @@ -1840,25 +1837,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest { useErrorGUI = enable; } - /** - * Signals that the client expected the System Under Test (SUT) to report errors. Use this - * when you wish to verify that errors are reported and you do not want those errors to - * fail the test. The default value for this setting is false, which means that any - * errors reported will fail the running test. - * - * @param expected true if errors are expected. - */ - public static void setErrorsExpected(boolean expected) { - if (expected) { - Msg.error(AbstractDockingTest.class, ">>>>>>>>>>>>>>>> Expected Exception"); - ConcurrentTestExceptionHandler.disable(); - } - else { - Msg.error(AbstractDockingTest.class, "<<<<<<<<<<<<<<<< End Expected Exception"); - ConcurrentTestExceptionHandler.enable(); - } - } - /** * Turns off the gui displays for errors. This does not change the "isUseErrorGUI()" value for * other tests in the TestCase. diff --git a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java index f3de6c5da5..0f8d391b25 100644 --- a/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java +++ b/Ghidra/Framework/Generic/src/main/java/generic/test/AbstractGenericTest.java @@ -248,8 +248,9 @@ public abstract class AbstractGenericTest extends AbstractGTest { */ public static Set getAllWindows() { Set set = new HashSet<>(); - Frame sharedOwnerFrame = (Frame) AppContext.getAppContext().get( - new StringBuffer("SwingUtilities.sharedOwnerFrame")); + Frame sharedOwnerFrame = (Frame) AppContext.getAppContext() + .get( + new StringBuffer("SwingUtilities.sharedOwnerFrame")); if (sharedOwnerFrame != null) { set.addAll(getAllWindows(sharedOwnerFrame)); } @@ -1515,6 +1516,29 @@ public abstract class AbstractGenericTest extends AbstractGTest { UIManager.put("TextArea.font", f); } + /** + * Signals that the client expected the System Under Test (SUT) to report errors. Use this + * when you wish to verify that errors are reported and you do not want those errors to + * fail the test. The default value for this setting is false, which means that any + * errors reported will fail the running test. + * + * @param expected true if errors are expected. + */ + public static void setErrorsExpected(boolean expected) { + if (expected) { + Msg.error(AbstractGenericTest.class, ">>>>>>>>>>>>>>>> Expected Exception"); + ConcurrentTestExceptionHandler.disable(); + } + else { + Msg.error(AbstractGenericTest.class, "<<<<<<<<<<<<<<<< End Expected Exception"); + ConcurrentTestExceptionHandler.enable(); + } + } + +//================================================================================================== +// Swing Methods +//================================================================================================== + /** * Waits for the Swing thread to process any pending events. This method * also waits for any {@link SwingUpdateManager}s that have pending events diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java index 539fe6f1d7..0af2617da9 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/CodeBrowserPluginScreenShots.java @@ -15,7 +15,7 @@ */ package help.screenshot; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.awt.*; import java.awt.event.ActionListener; @@ -148,7 +148,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { makeSelection(0x0406be1, 0x0406bf1); performAction("Create Table From Selection", "CodeBrowserPlugin", true); - Window window = waitForWindowByTitleContaining(null, "Selection Table", 2000); + Window window = waitForWindowByTitleContaining("Selection Table"); Point loc = plugin.getListingPanel().getLocationOnScreen(); Dimension size = window.getSize(); window.setBounds(loc.x + 300, loc.y + 150, size.width, 300); @@ -240,7 +240,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator { JWindow popup = (JWindow) waitForWindowByName("ListingHoverProvider"); paintFix(popup); captureProvider(CodeViewerProvider.class); - + CodeViewerProvider provider = getProvider(CodeViewerProvider.class); captureProviderWithScreenShot(provider); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/NavigationScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/NavigationScreenShots.java index cd10649229..be00ab524c 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/NavigationScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/NavigationScreenShots.java @@ -142,7 +142,7 @@ public class NavigationScreenShots extends GhidraScreenShotGenerator { setGotoText(dialog, "LAB*"); pressOkOnDialog(); Window window = - waitForWindowByTitleContaining(null, "Search Limit Exceeded!", DEFAULT_WINDOW_TIMEOUT); + waitForWindowByTitleContaining("Search Limit Exceeded!"); assertNotNull(window); pressButtonByText(window, "OK"); waitForSwing(); diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/DemangledFunctionTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/DemangledFunctionTest.java index 7ba4755622..d3b1f81ddc 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/DemangledFunctionTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/DemangledFunctionTest.java @@ -51,7 +51,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest program.endTransaction(txID, false); } - /** + /* * Test that the DemangledFunction will properly create a cascade of namespaces for * functions that live inside of a class that lives inside of a namespace. * This test applies a demangled name where the mangled name does NOT exist. @@ -83,7 +83,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest assertEquals("ATL", ns.getName(false)); } - /** + /* * Test that the DemangledFunction will properly update a thunk function * with its namespace, and ripple through to the underlying default thunked * function. The thunk 'this' parameter should utilize the Class @@ -132,7 +132,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest } - /** + /* * Test that the DemangledFunction will properly create a cascade of namespaces for * functions that live inside of a class that lives inside of a namespace. * This test applies a demangled name where the mangled name exists. @@ -168,7 +168,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest assertEquals("ATL", ns.getName(false)); } - /** + /* * Test that the DemangledFunction will properly create a cascade of namespaces for * functions that live inside of a class that lives inside of a namespace. * This test applies a demangled name where the mangled name exists with address suffix. @@ -205,7 +205,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest assertEquals("ATL", ns.getName(false)); } - /** + /* * Test that the DemangledFunction will properly create a cascade of namespaces for * functions that live inside of a class that lives inside of a namespace. * This test applies a demangled name where both the mangled name exists and @@ -243,7 +243,51 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest assertEquals("ATL", ns.getName(false)); } - /** + @Test + public void testFunctionThisPointer() throws Exception { + + // + // Test a function within a class that has a 'this' pointer + // + + String mangled = + "??$?0V?$A@_NABW4B@C@@@D@E@@@?$F@V?$G@U?$H@Q6A_NABW4B@C@@@Z$0A@@D@E@@_NABW4B@C@@@D@E@@@E@@QAE@ABV?$F@V?$A@_NABW4B@C@@@D@E@@@1@@Z"; + Address addr = addr("0x0101"); + + SymbolTable symbolTable = program.getSymbolTable(); + symbolTable.createLabel(addr, mangled, SourceType.IMPORTED); + + DemangledObject demangled = DemanglerUtil.demangle(mangled); + assertTrue(demangled instanceof DemangledFunction); + assertTrue(demangled.applyTo(program, addr, new DemanglerOptions(), TaskMonitor.DUMMY)); + + String className = + "F,bool,enum_C::B_const&>_>"; + String functionName = + className + "_>"; + + Function function = assertFunction(functionName, addr); + assertNoBookmarkAt(addr); + + Symbol[] symbols = symbolTable.getSymbols(addr); + assertEquals(2, symbols.length); + assertEquals(functionName, symbols[0].getName()); + assertEquals(mangled, symbols[1].getName()); + + // Check for the Class 'this' pointer + Parameter[] parameters = function.getParameters(); + assertEquals(2, parameters.length); + Parameter p1 = parameters[0]; + assertEquals("this", p1.getName()); + assertEquals(className + " *", p1.getDataType().toString()); + + Namespace ns = symbols[0].getParentNamespace(); + assertEquals(className, ns.getName(false)); + ns = ns.getParentNamespace(); + assertEquals("E", ns.getName(false)); + } + + /* * Test that the DemangledFunction will properly create a cascade of namespaces for * functions that live inside of a class that lives inside of a namespace. * This test applies a demangled name where the mangled name exists on an external @@ -339,15 +383,16 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest private void assertSimpleNamespaceExists(String name) { SymbolTable symbolTable = program.getSymbolTable(); Namespace ns = symbolTable.getNamespace(name, program.getGlobalNamespace()); - assertNotNull(ns); + assertNotNull("Namespace not created: " + name, ns); assertEquals(SymbolType.NAMESPACE, ns.getSymbol().getSymbolType()); } - private void assertFunction(String name, Address addr) { + private Function assertFunction(String name, Address addr) { FunctionManager fm = program.getFunctionManager(); Function function = fm.getFunctionAt(addr); assertNotNull("Expected function to get created at " + addr, function); assertEquals(name, function.getName()); + return function; } private Address addr(String addr) { diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java index b461cb0414..e853173d5b 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/util/demangler/gnu/GnuDemanglerIntegrationTest.java @@ -57,7 +57,7 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati String mangled = "MyFunction__11MyNamespacePQ215$ParamNamespace9paramName"; GnuDemangler demangler = new GnuDemangler(); - demangler.canDemangle(program);// this perform initialization + demangler.canDemangle(program);// this performs initialization GnuDemanglerOptions options = new GnuDemanglerOptions(); options.setDemangleOnlyKnownPatterns(false);