mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-3545 - GNU Demangler - Fix Parsing Issues - Ready for Review
This commit is contained in:
parent
ed80be21c3
commit
11619169b4
33 changed files with 1359 additions and 3934 deletions
|
@ -15,29 +15,150 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.demangler;
|
package ghidra.app.util.demangler;
|
||||||
|
|
||||||
// TODO better name
|
/**
|
||||||
|
* A unifying top-level interface for all {@link DemangledObject}s and {@link DemangledType}s
|
||||||
|
*
|
||||||
|
* <p>This class and its children have many overlapping concepts that we wish to refine at a
|
||||||
|
* future date. Below is a listing of know uses:
|
||||||
|
* <TABLE>
|
||||||
|
* <TR>
|
||||||
|
* <TH ALIGN="left">Method</TH><TH ALIGN="left">Description</TH>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getName()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* A 'safe' name that is the {@link #getDemangledName()}, but with some characters
|
||||||
|
* changed to be valid for use within Ghidra.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getDemangledName()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* The unmodified name that was set upon this object.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getNamespaceName()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* The 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.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getNamespaceString()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* Similar to {@link #getNamespaceName()}, but contains all parent namespaces as well.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getSignature()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* Returns the complete string form of this object, with most known attributes. For
|
||||||
|
* functions, this will be a complete signature.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* <TR>
|
||||||
|
* <TD>
|
||||||
|
* {@link #getOriginalDemangled()}
|
||||||
|
* </TD>
|
||||||
|
* <TD>
|
||||||
|
* The original unmodified demangled string.
|
||||||
|
* </TD>
|
||||||
|
* </TR>
|
||||||
|
* </TABLE>
|
||||||
|
*/
|
||||||
public interface Demangled {
|
public interface Demangled {
|
||||||
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the namespace containing this demangled object
|
|
||||||
* @return the namespace containing this demangled object
|
|
||||||
*/
|
|
||||||
public Demangled getNamespace();
|
|
||||||
|
|
||||||
public void setNamespace(Demangled ns);
|
|
||||||
|
|
||||||
public String toNamespaceString();
|
|
||||||
|
|
||||||
// TODO doc difference
|
|
||||||
public String toNamespaceName();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the original mangled string
|
* Returns the original mangled string
|
||||||
* @return the string
|
* @return the string
|
||||||
*/
|
*/
|
||||||
public String getMangledString();
|
public String getMangledString();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the original mangled string
|
||||||
|
* @param mangled the mangled string
|
||||||
|
*/
|
||||||
public void setMangledString(String mangled);
|
public void setMangledString(String mangled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the original demangled string returned by the demangling service
|
||||||
|
* @return the original demangled string
|
||||||
|
*/
|
||||||
|
public String getOriginalDemangled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the original demangles string returned by the demangling service
|
||||||
|
* @param originalDemangled the original demangled string
|
||||||
|
*/
|
||||||
|
public void setOriginalDemangled(String originalDemangled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 a this object's namespace name without the full-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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ public class DemangledAddressTable extends DemangledObject {
|
||||||
buffer.append(specialPrefix);
|
buffer.append(specialPrefix);
|
||||||
buffer.append(' ');
|
buffer.append(' ');
|
||||||
}
|
}
|
||||||
String namespaceStr = namespace.toNamespaceString();
|
String namespaceStr = namespace.getNamespaceString();
|
||||||
buffer.append(namespaceStr);
|
buffer.append(namespaceStr);
|
||||||
if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) {
|
if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) {
|
||||||
buffer.append(NAMESPACE_SEPARATOR);
|
buffer.append(NAMESPACE_SEPARATOR);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package ghidra.app.util.demangler;
|
package ghidra.app.util.demangler;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -221,7 +222,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
dt = createPlaceHolderStructure(name, getNamespace());
|
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
|
// I don't know what this is
|
||||||
// If it isn't pointed to, or isn't a referent, then assume typedef.
|
// If it isn't pointed to, or isn't a referent, then assume typedef.
|
||||||
|
@ -367,41 +368,43 @@ public class DemangledDataType extends DemangledType {
|
||||||
*/
|
*/
|
||||||
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
||||||
String dtName) {
|
String dtName) {
|
||||||
// TODO: Should be able to search archives somehow
|
|
||||||
ArrayList<DataType> list = new ArrayList<>();
|
List<DataType> list = new ArrayList<>();
|
||||||
dataTypeManager.findDataTypes(dtName, list);
|
dataTypeManager.findDataTypes(dtName, list);
|
||||||
if (!list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
//use the datatype that exists in the root category,
|
return null;
|
||||||
//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;
|
|
||||||
}
|
}
|
||||||
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, Demangled namespace) {
|
private static boolean isNamespaceCategoryMatch(DataType dt, Demangled namespace) {
|
||||||
if (namespace == null) {
|
if (namespace == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Demangled ns = namespace;
|
Demangled ns = namespace;
|
||||||
CategoryPath categoryPath = dt.getCategoryPath();
|
CategoryPath categoryPath = dt.getCategoryPath();
|
||||||
while (ns != null) {
|
while (ns != null) {
|
||||||
|
@ -433,7 +436,6 @@ public class DemangledDataType extends DemangledType {
|
||||||
StructureDataType structDT = new StructureDataType(dtName, 0);
|
StructureDataType structDT = new StructureDataType(dtName, 0);
|
||||||
structDT.setDescription("PlaceHolder Structure");
|
structDT.setDescription("PlaceHolder Structure");
|
||||||
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
||||||
|
|
||||||
return structDT;
|
return structDT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,10 +619,6 @@ public class DemangledDataType extends DemangledType {
|
||||||
boolean isPrimitiveDT =
|
boolean isPrimitiveDT =
|
||||||
!isArray() && !isClass && !isComplex && !isEnum && !isPointer() && !isPointer64 &&
|
!isArray() && !isClass && !isComplex && !isEnum && !isPointer() && !isPointer64 &&
|
||||||
!isSigned && !isTemplate && !isUnion && !isCoclass && !isCointerface && !isVarArgs;
|
!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) {
|
if (isPrimitiveDT) {
|
||||||
for (String primitiveNames : PRIMITIVES) {
|
for (String primitiveNames : PRIMITIVES) {
|
||||||
if (getName().equals(primitiveNames)) {
|
if (getName().equals(primitiveNames)) {
|
||||||
|
@ -631,8 +629,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public String getSignature() {
|
||||||
public String toSignature() {
|
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
if (isUnion) {
|
if (isUnion) {
|
||||||
|
@ -659,9 +656,6 @@ public class DemangledDataType extends DemangledType {
|
||||||
if (isComplex) {
|
if (isComplex) {
|
||||||
buffer.append(COMPLEX + SPACE);
|
buffer.append(COMPLEX + SPACE);
|
||||||
}
|
}
|
||||||
// if (isVolatile) {
|
|
||||||
// buffer.append(VOLATILE + SPACE);
|
|
||||||
// }
|
|
||||||
if (isSigned) {
|
if (isSigned) {
|
||||||
buffer.append(SIGNED + SPACE);
|
buffer.append(SIGNED + SPACE);
|
||||||
}
|
}
|
||||||
|
@ -670,7 +664,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getNamespace() != null) {
|
if (getNamespace() != null) {
|
||||||
buffer.append(getNamespace().toNamespaceString());
|
buffer.append(getNamespace().getNamespaceString());
|
||||||
buffer.append(Namespace.DELIMITER);
|
buffer.append(Namespace.DELIMITER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,7 +678,6 @@ public class DemangledDataType extends DemangledType {
|
||||||
buffer.append(SPACE + CONST);
|
buffer.append(SPACE + CONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: The output of volatile belongs here, not above, so I put the commented code here for now.
|
|
||||||
if (isVolatile()) {
|
if (isVolatile()) {
|
||||||
buffer.append(SPACE + VOLATILE);
|
buffer.append(SPACE + VOLATILE);
|
||||||
}
|
}
|
||||||
|
@ -709,7 +702,8 @@ public class DemangledDataType extends DemangledType {
|
||||||
buffer.append(SPACE + REF_NOTATION);
|
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) {
|
if (isPointer64) {
|
||||||
buffer.append(SPACE + PTR64);
|
buffer.append(SPACE + PTR64);
|
||||||
}
|
}
|
||||||
|
@ -736,7 +730,7 @@ public class DemangledDataType extends DemangledType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toSignature();
|
return getSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,21 +21,23 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.cmd.function.*;
|
import ghidra.app.cmd.function.*;
|
||||||
|
import ghidra.app.util.NamespaceUtils;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSetView;
|
import ghidra.program.model.address.AddressSetView;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.lang.PrototypeModel;
|
import ghidra.program.model.lang.PrototypeModel;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.program.model.symbol.Symbol;
|
|
||||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to represent a demangled function.
|
* 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 VOLATILE = "volatile";
|
||||||
public static final String CONST = "const";
|
public static final String CONST = "const";
|
||||||
|
@ -104,18 +106,10 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
this.isOverloadedOperator = isOverloadedOperator;
|
this.isOverloadedOperator = isOverloadedOperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.util.demangler.ParameterReceiver
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledDataType parameter) {
|
||||||
parameters.add(parameter);
|
parameters.add(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.util.demangler.ParameterReceiver
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public List<DemangledDataType> getParameters() {
|
public List<DemangledDataType> getParameters() {
|
||||||
return new ArrayList<>(parameters);
|
return new ArrayList<>(parameters);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +192,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSignature(boolean format) {
|
public String getSignature(boolean format) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
|
||||||
if (!(returnType instanceof DemangledFunctionPointer)) {
|
if (!(returnType instanceof DemangledFunctionPointer)) {
|
||||||
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
||||||
|
@ -214,38 +208,26 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
buffer.append("static ");
|
buffer.append("static ");
|
||||||
}
|
}
|
||||||
if (!isTypeCast()) {
|
if (!isTypeCast()) {
|
||||||
buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
|
buffer.append(returnType == null ? "" : returnType.getSignature() + " ");
|
||||||
}
|
}
|
||||||
// buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
|
// buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append(callingConvention == null ? "" : callingConvention + " ");
|
buffer.append(callingConvention == null ? "" : callingConvention + " ");
|
||||||
if (namespace != null) {
|
if (namespace != null) {
|
||||||
buffer.append(namespace.toNamespaceString());
|
buffer.append(namespace.getNamespaceString());
|
||||||
buffer.append(NAMESPACE_SEPARATOR);
|
buffer.append(NAMESPACE_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append(getDemangledName());
|
buffer.append(getDemangledName());
|
||||||
if (isTypeCast()) {
|
if (isTypeCast()) {
|
||||||
buffer.append(returnType == null ? "" : " " + returnType.toSignature() + " ");
|
buffer.append(returnType == null ? "" : " " + returnType.getSignature() + " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (template != null) {
|
if (template != null) {
|
||||||
buffer.append(template.toTemplate());
|
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) {
|
if (templatedConstructorType != null) {
|
||||||
buffer.append('<').append(templatedConstructorType).append('>');
|
buffer.append('<').append(templatedConstructorType).append('>');
|
||||||
}
|
}
|
||||||
|
@ -258,7 +240,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
}
|
}
|
||||||
|
|
||||||
while (paramIterator.hasNext()) {
|
while (paramIterator.hasNext()) {
|
||||||
buffer.append(paramIterator.next().toSignature());
|
buffer.append(paramIterator.next().getSignature());
|
||||||
if (paramIterator.hasNext()) {
|
if (paramIterator.hasNext()) {
|
||||||
buffer.append(',');
|
buffer.append(',');
|
||||||
if (format) {
|
if (format) {
|
||||||
|
@ -270,26 +252,19 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
|
|
||||||
buffer.append(')');
|
buffer.append(')');
|
||||||
buffer.append(storageClass == null ? "" : " " + storageClass);
|
buffer.append(storageClass == null ? "" : " " + storageClass);
|
||||||
// }
|
|
||||||
|
|
||||||
if (returnType instanceof DemangledFunctionPointer) {
|
if (returnType instanceof DemangledFunctionPointer) {
|
||||||
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) returnType;
|
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) returnType;
|
||||||
String partialSig = funcPtr.toSignature(buffer.toString());
|
String partialSig = funcPtr.toSignature(buffer.toString());
|
||||||
buffer = new StringBuffer();
|
buffer = new StringBuilder();
|
||||||
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
||||||
buffer.append(
|
buffer.append(
|
||||||
visibility == null || "global".equals(visibility) ? "" : visibility + " ");
|
visibility == null || "global".equals(visibility) ? "" : visibility + " ");
|
||||||
//if (virtual || super.isVirtual) {
|
|
||||||
if (isVirtual) {
|
if (isVirtual) {
|
||||||
buffer.append("virtual ");
|
buffer.append("virtual ");
|
||||||
}
|
}
|
||||||
buffer.append(partialSig);
|
buffer.append(partialSig);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (specialSuffix != null) {
|
|
||||||
buffer.append(specialSuffix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTrailingConst()) {
|
if (isTrailingConst()) {
|
||||||
if (buffer.length() > 2) {
|
if (buffer.length() > 2) {
|
||||||
|
@ -332,7 +307,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceName() {
|
public String getNamespaceName() {
|
||||||
return getName() + getParameterString();
|
return getName() + getParameterString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +316,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
buffer.append('(');
|
buffer.append('(');
|
||||||
Iterator<DemangledDataType> dditer = parameters.iterator();
|
Iterator<DemangledDataType> dditer = parameters.iterator();
|
||||||
while (dditer.hasNext()) {
|
while (dditer.hasNext()) {
|
||||||
buffer.append(dditer.next().toSignature());
|
buffer.append(dditer.next().getSignature());
|
||||||
if (dditer.hasNext()) {
|
if (dditer.hasNext()) {
|
||||||
buffer.append(',');
|
buffer.append(',');
|
||||||
}
|
}
|
||||||
|
@ -452,13 +427,13 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
for (int i = 0; i < args.size(); i++) {
|
for (int i = 0; i < args.size(); i++) {
|
||||||
if (args.get(i).getLength() > pointerSize) {
|
if (args.get(i).getLength() > pointerSize) {
|
||||||
bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler",
|
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");
|
"large to fit in a parameter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler",
|
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");
|
") in a function in a namespace");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +463,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.
|
// If something is returned as a Union, Structure, or Class return.
|
||||||
// It appears that is passed as an additional parameter. Essentially, it accesses
|
// It appears that is passed as an additional parameter. Essentially, it accesses
|
||||||
// the stack assuming there is reserved space.
|
// the stack assuming there is reserved space.
|
||||||
|
@ -497,7 +473,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
}
|
}
|
||||||
|
|
||||||
// If returnType is null check for constructor or destructor names
|
// 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();
|
String n = getName();
|
||||||
if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) {
|
if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) {
|
||||||
// constructor && destructor
|
// constructor && destructor
|
||||||
|
@ -507,47 +483,50 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Structure maybeUpdateCallingConventionAndCreateClass(Program program, Function func) {
|
private Structure maybeUpdateCallingConventionAndCreateClass(Program program,
|
||||||
try {
|
Function function) {
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isThisCall(func)) {
|
String convention = validateCallingConvention(program, function);
|
||||||
func.setCallingConvention(THIS_CALL);
|
if (convention == null) {
|
||||||
return createClassStructure(program, func);
|
if (!isThisCall(function)) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
// Leave the calling convention to someone else to figure out
|
convention = THIS_CALL;
|
||||||
// else {
|
}
|
||||||
// String defaultConvention = getDefaultCallingConvention(program);
|
|
||||||
// if (defaultConvention != null) {
|
try {
|
||||||
// func.setCallingConvention(defaultConvention);
|
function.setCallingConvention(convention);
|
||||||
// }
|
return maybeCreateClassStructure(program, function, convention);
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
catch (InvalidInputException e) {
|
catch (InvalidInputException e) {
|
||||||
e.printStackTrace();
|
Msg.error(this, "Unexpected exception setting calling convention", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
private List<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
||||||
|
|
||||||
List<ParameterDefinitionImpl> args = new ArrayList<>();
|
List<ParameterDefinitionImpl> args = new ArrayList<>();
|
||||||
|
@ -661,7 +640,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the function name is the same name as it's namespace
|
// 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())) {
|
if (n.startsWith(namespace.getName())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -686,7 +665,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
return true;
|
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!
|
// But is also could be a static member function!
|
||||||
// The only way to really tell is compare the number of detected parameters
|
// 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
|
// to the number of parameters we have, OR, to detect the calling convention
|
||||||
|
@ -707,13 +686,58 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
||||||
if (ns == null) {
|
if (ns == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ns.getName().toLowerCase().equals(STD_NAMESPACE)) {
|
if (ns.getName().equalsIgnoreCase(STD_NAMESPACE)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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) {
|
TaskMonitor monitor) {
|
||||||
Listing listing = prog.getListing();
|
Listing listing = prog.getListing();
|
||||||
Function func = listing.getFunctionAt(addr);
|
Function func = listing.getFunctionAt(addr);
|
||||||
|
|
|
@ -27,7 +27,7 @@ import ghidra.program.model.data.*;
|
||||||
* is still an indirect definition (not a regular function definition). The
|
* is still an indirect definition (not a regular function definition). The
|
||||||
* function indirect is prevalent in the Microsoft model, if not other models.
|
* function indirect is prevalent in the Microsoft model, if not other models.
|
||||||
*/
|
*/
|
||||||
public class DemangledFunctionIndirect extends DemangledDataType implements ParameterReceiver {
|
public class DemangledFunctionIndirect extends DemangledDataType {
|
||||||
|
|
||||||
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
||||||
private static final String NAMESPACE_DELIMITER = "::";
|
private static final String NAMESPACE_DELIMITER = "::";
|
||||||
|
@ -58,23 +58,6 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
return ID++;
|
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<GenericDemangledDataType> genericParameters = generic.getParameters();
|
|
||||||
// for (GenericDemangledDataType parameter : genericParameters) {
|
|
||||||
// parameters.add((DemangledDataType) DemangledObjectFactory.convert(parameter));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the return type.
|
* Returns the return type.
|
||||||
* @return the return type
|
* @return the return type
|
||||||
|
@ -152,20 +135,17 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameters to the end of the parameter list for
|
* Adds a parameters to the end of the parameter list for this demangled function
|
||||||
* this demangled function.
|
|
||||||
* @param parameter the new parameter to add
|
* @param parameter the new parameter to add
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledDataType parameter) {
|
||||||
parameters.add(parameter);
|
parameters.add(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of the parameters for this demangled functions.
|
* Returns a list of the parameters for this demangled functions
|
||||||
* @return a list of the parameters for this demangled functions
|
* @return a list of the parameters for this demangled functions
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public List<DemangledDataType> getParameters() {
|
public List<DemangledDataType> getParameters() {
|
||||||
return new ArrayList<>(parameters);
|
return new ArrayList<>(parameters);
|
||||||
}
|
}
|
||||||
|
@ -195,13 +175,13 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String getSignature() {
|
||||||
return toSignature(null);
|
return toSignature(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSignature(String name) {
|
public String toSignature(String name) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuilder buffer = new StringBuilder();
|
||||||
StringBuffer buffer1 = new StringBuffer();
|
StringBuilder buffer1 = new StringBuilder();
|
||||||
String s = getConventionPointerNameString(name);
|
String s = getConventionPointerNameString(name);
|
||||||
if (s.contains(" ") || s.isEmpty()) {
|
if (s.contains(" ") || s.isEmpty()) {
|
||||||
// spaces--add parens
|
// spaces--add parens
|
||||||
|
@ -213,7 +193,7 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
|
|
||||||
buffer1.append('(');
|
buffer1.append('(');
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
buffer1.append(parameters.get(i).toSignature());
|
buffer1.append(parameters.get(i).getSignature());
|
||||||
if (i < parameters.size() - 1) {
|
if (i < parameters.size() - 1) {
|
||||||
buffer1.append(',');
|
buffer1.append(',');
|
||||||
}
|
}
|
||||||
|
@ -222,21 +202,24 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
|
|
||||||
if (returnType instanceof DemangledFunctionPointer) {
|
if (returnType instanceof DemangledFunctionPointer) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionReference) {
|
else if (returnType instanceof DemangledFunctionReference) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buffer.append(returnType.toSignature()).append(SPACE);
|
buffer.append(returnType.getSignature()).append(SPACE);
|
||||||
buffer.append(buffer1);
|
buffer.append(buffer1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +261,7 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFunctionPointerParens(StringBuffer buffer, String s) {
|
private void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||||
if (!displayFunctionPointerParens) {
|
if (!displayFunctionPointerParens) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -322,9 +305,6 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
// if (buffer.length() > 2) {
|
|
||||||
// buffer.append(SPACE);
|
|
||||||
// }
|
|
||||||
if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) {
|
if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) {
|
||||||
buffer.append(SPACE);
|
buffer.append(SPACE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import ghidra.program.model.data.*;
|
||||||
/**
|
/**
|
||||||
* 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 DemangledDataType {
|
||||||
|
|
||||||
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
||||||
private static final Object NAMESPACE_DELIMITER = "::";
|
private static final Object NAMESPACE_DELIMITER = "::";
|
||||||
|
@ -131,11 +131,9 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameters to the end of the parameter list for
|
* Adds a parameters to the end of the parameter list for this demangled function
|
||||||
* this demangled function.
|
|
||||||
* @param parameter the new parameter to add
|
* @param parameter the new parameter to add
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledDataType parameter) {
|
||||||
parameters.add(parameter);
|
parameters.add(parameter);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +142,6 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||||
* Returns a list of the parameters for this demangled functions.
|
* Returns a list of the parameters for this demangled functions.
|
||||||
* @return a list of the parameters for this demangled functions
|
* @return a list of the parameters for this demangled functions
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public List<DemangledDataType> getParameters() {
|
public List<DemangledDataType> getParameters() {
|
||||||
return new ArrayList<>(parameters);
|
return new ArrayList<>(parameters);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +171,7 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String getSignature() {
|
||||||
return toSignature(null);
|
return toSignature(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +189,7 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||||
|
|
||||||
buffer1.append('(');
|
buffer1.append('(');
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
buffer1.append(parameters.get(i).toSignature());
|
buffer1.append(parameters.get(i).getSignature());
|
||||||
if (i < parameters.size() - 1) {
|
if (i < parameters.size() - 1) {
|
||||||
buffer1.append(',');
|
buffer1.append(',');
|
||||||
}
|
}
|
||||||
|
@ -200,25 +197,19 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
||||||
buffer1.append(')');
|
buffer1.append(')');
|
||||||
|
|
||||||
if (returnType instanceof DemangledFunctionPointer) {
|
if (returnType instanceof DemangledFunctionPointer) {
|
||||||
buffer.append(
|
DemangledFunctionPointer dfp = (DemangledFunctionPointer) returnType;
|
||||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
buffer.append(dfp.toSignature(buffer1.toString())).append(SPACE);
|
||||||
.append(
|
|
||||||
SPACE);
|
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionReference) {
|
else if (returnType instanceof DemangledFunctionReference) {
|
||||||
buffer.append(
|
DemangledFunctionReference dfr = (DemangledFunctionReference) returnType;
|
||||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
buffer.append(dfr.toSignature(buffer1.toString())).append(SPACE);
|
||||||
.append(
|
|
||||||
SPACE);
|
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||||
buffer.append(
|
DemangledFunctionIndirect dfi = (DemangledFunctionIndirect) returnType;
|
||||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
buffer.append(dfi.toSignature(buffer1.toString())).append(SPACE);
|
||||||
.append(
|
|
||||||
SPACE);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buffer.append(returnType.toSignature()).append(SPACE);
|
buffer.append(returnType.getSignature()).append(SPACE);
|
||||||
buffer.append(buffer1);
|
buffer.append(buffer1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ 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 DemangledDataType {
|
||||||
|
|
||||||
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
||||||
private static final Object NAMESPACE_DELIMITER = "::";
|
private static final Object NAMESPACE_DELIMITER = "::";
|
||||||
|
@ -131,11 +131,9 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameters to the end of the parameter list for
|
* Adds a parameters to the end of the parameter list for this demangled function
|
||||||
* this demangled function.
|
|
||||||
* @param parameter the new parameter to add
|
* @param parameter the new parameter to add
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledDataType parameter) {
|
||||||
parameters.add(parameter);
|
parameters.add(parameter);
|
||||||
}
|
}
|
||||||
|
@ -144,7 +142,6 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
||||||
* Returns a list of the parameters for this demangled functions.
|
* Returns a list of the parameters for this demangled functions.
|
||||||
* @return a list of the parameters for this demangled functions
|
* @return a list of the parameters for this demangled functions
|
||||||
*/
|
*/
|
||||||
@Override
|
|
||||||
public List<DemangledDataType> getParameters() {
|
public List<DemangledDataType> getParameters() {
|
||||||
return new ArrayList<>(parameters);
|
return new ArrayList<>(parameters);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +171,7 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toSignature() {
|
public String getSignature() {
|
||||||
return toSignature(null);
|
return toSignature(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +189,7 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
||||||
|
|
||||||
buffer1.append('(');
|
buffer1.append('(');
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
buffer1.append(parameters.get(i).toSignature());
|
buffer1.append(parameters.get(i).getSignature());
|
||||||
if (i < parameters.size() - 1) {
|
if (i < parameters.size() - 1) {
|
||||||
buffer1.append(',');
|
buffer1.append(',');
|
||||||
}
|
}
|
||||||
|
@ -201,21 +198,24 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
||||||
|
|
||||||
if (returnType instanceof DemangledFunctionPointer) {
|
if (returnType instanceof DemangledFunctionPointer) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionReference) {
|
else if (returnType instanceof DemangledFunctionReference) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||||
buffer.append(
|
buffer.append(
|
||||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append(
|
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||||
SPACE);
|
.append(
|
||||||
|
SPACE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
buffer.append(returnType.toSignature()).append(SPACE);
|
buffer.append(returnType.getSignature()).append(SPACE);
|
||||||
buffer.append(buffer1);
|
buffer.append(buffer1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,34 +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;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.demangler;
|
package ghidra.app.util.demangler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a demangled lambda function
|
||||||
|
*/
|
||||||
public class DemangledLambda extends DemangledFunction {
|
public class DemangledLambda extends DemangledFunction {
|
||||||
|
|
||||||
public DemangledLambda(String name) {
|
public DemangledLambda(String name) {
|
||||||
|
@ -22,7 +25,7 @@ public class DemangledLambda extends DemangledFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceName() {
|
public String getNamespaceName() {
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,12 @@ import java.util.regex.Pattern;
|
||||||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||||
import ghidra.app.util.NamespaceUtils;
|
import ghidra.app.util.NamespaceUtils;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.listing.CodeUnit;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.symbol.*;
|
import ghidra.program.model.symbol.*;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.*;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
import ghidra.util.exception.InvalidInputException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,10 +42,8 @@ public abstract class DemangledObject implements Demangled {
|
||||||
protected static final String EMPTY_STRING = "";
|
protected static final String EMPTY_STRING = "";
|
||||||
|
|
||||||
protected String mangled; // original mangled string
|
protected String mangled; // original mangled string
|
||||||
protected String utilDemangled;
|
protected String originalDemangled;
|
||||||
protected String specialPrefix;
|
protected String specialPrefix;
|
||||||
protected String specialMidfix;
|
|
||||||
protected String specialSuffix;
|
|
||||||
protected Demangled namespace;
|
protected Demangled namespace;
|
||||||
protected String visibility;//public, protected, etc.
|
protected String visibility;//public, protected, etc.
|
||||||
|
|
||||||
|
@ -75,23 +74,11 @@ public abstract class DemangledObject implements Demangled {
|
||||||
// default
|
// default
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 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() {
|
public String getDemangledName() {
|
||||||
return demangledName;
|
return demangledName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -181,6 +168,7 @@ public abstract class DemangledObject implements Demangled {
|
||||||
* Sets the name of the demangled object
|
* Sets the name of the demangled object
|
||||||
* @param name the new name
|
* @param name the new name
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.demangledName = name;
|
this.demangledName = name;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -202,20 +190,14 @@ public abstract class DemangledObject implements Demangled {
|
||||||
return mangled;
|
return mangled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the demangled output from a supplemental utility.
|
public void setOriginalDemangled(String originalDemangled) {
|
||||||
* @param utilDemangled the demangled string
|
this.originalDemangled = originalDemangled;
|
||||||
*/
|
|
||||||
public void setUtilDemangled(String utilDemangled) {
|
|
||||||
this.utilDemangled = utilDemangled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the demangled output from a supplemental utility.
|
public String getOriginalDemangled() {
|
||||||
* @return the demangled String created for this object.
|
return originalDemangled;
|
||||||
*/
|
|
||||||
public String getUtilDemangled() {
|
|
||||||
return utilDemangled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -252,22 +234,6 @@ public abstract class DemangledObject implements Demangled {
|
||||||
this.specialPrefix = 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.
|
* Returns a complete signature for the demangled symbol.
|
||||||
* <br>For example:
|
* <br>For example:
|
||||||
|
@ -281,12 +247,17 @@ public abstract class DemangledObject implements Demangled {
|
||||||
*/
|
*/
|
||||||
public abstract String getSignature(boolean format);
|
public abstract String getSignature(boolean format);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignature() {
|
||||||
|
return getSignature(false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a signature that contains only the name (and parameter list for functions)
|
* Returns a signature that contains only the name (and parameter list for functions)
|
||||||
* @return the signature
|
* @return the signature
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceName() {
|
public String getNamespaceName() {
|
||||||
return getSignature(false);
|
return getSignature(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,13 +276,13 @@ public abstract class DemangledObject implements Demangled {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceString() {
|
public String getNamespaceString() {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
if (namespace != null) {
|
if (namespace != null) {
|
||||||
buffer.append(namespace.toNamespaceString());
|
buffer.append(namespace.getNamespaceString());
|
||||||
buffer.append(Namespace.DELIMITER);
|
buffer.append(Namespace.DELIMITER);
|
||||||
}
|
}
|
||||||
buffer.append(toNamespaceName());
|
buffer.append(getNamespaceName());
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,8 +337,8 @@ public abstract class DemangledObject implements Demangled {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String generatePlateComment() {
|
protected String generatePlateComment() {
|
||||||
if (utilDemangled != null) {
|
if (originalDemangled != null) {
|
||||||
return utilDemangled;
|
return originalDemangled;
|
||||||
}
|
}
|
||||||
return (signature == null) ? getSignature(true) : signature;
|
return (signature == null) ? getSignature(true) : signature;
|
||||||
}
|
}
|
||||||
|
@ -446,22 +417,20 @@ public abstract class DemangledObject implements Demangled {
|
||||||
* @return list of namespace names
|
* @return list of namespace names
|
||||||
*/
|
*/
|
||||||
private static List<String> getNamespaceList(Demangled typeNamespace) {
|
private static List<String> getNamespaceList(Demangled typeNamespace) {
|
||||||
ArrayList<String> list = new ArrayList<>();
|
List<String> list = new ArrayList<>();
|
||||||
Demangled ns = typeNamespace;
|
Demangled ns = typeNamespace;
|
||||||
while (ns != null) {
|
while (ns != null) {
|
||||||
list.add(0, ns.getName());
|
list.add(0, ns.getNamespaceName());
|
||||||
ns = ns.getNamespace();
|
ns = ns.getNamespace();
|
||||||
}
|
}
|
||||||
return list;
|
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
|
* 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
|
* namespace if errors occurred. The caller should check the returned namespace and adjust
|
||||||
* any symbol creation accordingly. Caller should use
|
* any symbol creation accordingly.
|
||||||
* <code>getResidualNamespacePath(DemangledType, Namespace)</code> to handle the case where
|
*
|
||||||
* only a partial namespace has been returned.
|
|
||||||
* @param program the program
|
* @param program the program
|
||||||
* @param typeNamespace demangled namespace
|
* @param typeNamespace demangled namespace
|
||||||
* @param parentNamespace root namespace to be used (e.g., library, global, etc.)
|
* @param parentNamespace root namespace to be used (e.g., library, global, etc.)
|
||||||
|
@ -556,37 +525,4 @@ public abstract class DemangledObject implements Demangled {
|
||||||
return buffy.toString();
|
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
|
|
||||||
Demangled 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,12 +48,9 @@ public class DemangledString extends DemangledObject {
|
||||||
public String getSignature(boolean format) {
|
public String getSignature(boolean format) {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
if (specialPrefix != null) {
|
if (specialPrefix != null) {
|
||||||
buffer.append(specialPrefix + " for ");
|
buffer.append(specialPrefix);
|
||||||
}
|
}
|
||||||
buffer.append(string);
|
buffer.append(string);
|
||||||
if (specialSuffix != null) {
|
|
||||||
buffer.append(" " + specialSuffix);
|
|
||||||
}
|
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +69,9 @@ public class DemangledString extends DemangledObject {
|
||||||
public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
||||||
TaskMonitor monitor) throws Exception {
|
TaskMonitor monitor) throws Exception {
|
||||||
|
|
||||||
String label = SymbolUtilities.replaceInvalidChars(string, false);
|
String label = buildStringLabel();
|
||||||
if (hasLabel(program, address, label)) {
|
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)) {
|
if (!super.applyTo(program, address, options, monitor)) {
|
||||||
|
@ -88,24 +85,24 @@ public class DemangledString extends DemangledObject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should we be using length ?
|
|
||||||
CreateStringCmd cmd = new CreateStringCmd(address, -1, isUnicode());
|
CreateStringCmd cmd = new CreateStringCmd(address, -1, isUnicode());
|
||||||
cmd.applyTo(program);
|
cmd.applyTo(program);
|
||||||
|
|
||||||
// unclear what demangled name should be used so apply
|
|
||||||
// fabricated string label which is more useful than mangled name
|
|
||||||
Symbol demangledSymbol =
|
Symbol demangledSymbol =
|
||||||
applyDemangledName(buildStringLabel(), address, true, false, program);
|
applyDemangledName(label, address, true, false, program);
|
||||||
return (demangledSymbol != null);
|
return (demangledSymbol != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildStringLabel() {
|
private String buildStringLabel() {
|
||||||
// build string label consistent with dynamic label formatting
|
|
||||||
if (specialPrefix != null) {
|
if (specialPrefix != null) {
|
||||||
|
// a 'special prefix' implies that the author wishes to apply the string exactly as-is
|
||||||
return getName();
|
return getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build string label consistent with dynamic label formatting
|
||||||
int len = string.length();
|
int len = string.length();
|
||||||
StringBuffer buf = new StringBuffer(len);
|
StringBuilder buf = new StringBuilder(len);
|
||||||
for (int i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
char c = string.charAt(i);
|
char c = string.charAt(i);
|
||||||
if (StringUtilities.isDisplayable(c) && (c != ' ')) {
|
if (StringUtilities.isDisplayable(c) && (c != ' ')) {
|
||||||
|
|
|
@ -19,31 +19,23 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
public class DemangledTemplate implements ParameterReceiver {
|
public class DemangledTemplate {
|
||||||
private List<DemangledDataType> parameters = new ArrayList<DemangledDataType>();
|
private List<DemangledDataType> parameters = new ArrayList<DemangledDataType>();
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addParameter(DemangledDataType parameter) {
|
public void addParameter(DemangledDataType parameter) {
|
||||||
parameters.add(parameter);
|
parameters.add(parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<DemangledDataType> getParameters() {
|
public List<DemangledDataType> getParameters() {
|
||||||
return new ArrayList<DemangledDataType>(parameters);
|
return new ArrayList<DemangledDataType>(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toTemplate() {
|
public String toTemplate() {
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuilder buffer = new StringBuilder();
|
||||||
buffer.append('<');
|
buffer.append('<');
|
||||||
for (int i = 0; i < parameters.size(); ++i) {
|
for (int i = 0; i < parameters.size(); ++i) {
|
||||||
try {
|
buffer.append(parameters.get(i).getSignature());
|
||||||
buffer.append(parameters.get(i).toSignature());
|
|
||||||
}
|
|
||||||
catch (Error e) {
|
|
||||||
Msg.error(this, "Unexpected Error: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
if (i < parameters.size() - 1) {
|
if (i < parameters.size() - 1) {
|
||||||
buffer.append(',');
|
buffer.append(',');
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,12 @@ package ghidra.app.util.demangler;
|
||||||
|
|
||||||
import ghidra.program.model.symbol.Namespace;
|
import ghidra.program.model.symbol.Namespace;
|
||||||
|
|
||||||
// TODO maybe rename this to DemangledNamespace
|
/**
|
||||||
|
* 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 {
|
public class DemangledType implements Demangled {
|
||||||
private String demangledName;
|
private String demangledName;
|
||||||
private String name;
|
private String name;
|
||||||
|
@ -26,37 +31,23 @@ public class DemangledType implements Demangled {
|
||||||
protected DemangledTemplate template;
|
protected DemangledTemplate template;
|
||||||
private boolean isConst;
|
private boolean isConst;
|
||||||
private boolean isVolatile;
|
private boolean isVolatile;
|
||||||
|
private String originalDemangled;
|
||||||
|
|
||||||
public DemangledType(String name) {
|
public DemangledType(String name) {
|
||||||
setName(name);
|
setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 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() {
|
public String getDemangledName() {
|
||||||
return demangledName;
|
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
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Sets the name of the demangled type object.
|
|
||||||
* @param name the new name
|
|
||||||
*/
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
demangledName = name;
|
demangledName = name;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -66,6 +57,16 @@ public class DemangledType implements Demangled {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setOriginalDemangled(String originalDemangled) {
|
||||||
|
this.originalDemangled = originalDemangled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOriginalDemangled() {
|
||||||
|
return originalDemangled;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMangledString(String mangled) {
|
public void setMangledString(String mangled) {
|
||||||
this.mangled = mangled;
|
this.mangled = mangled;
|
||||||
|
@ -113,19 +114,20 @@ public class DemangledType implements Demangled {
|
||||||
this.template = template;
|
this.template = template;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSignature() {
|
@Override
|
||||||
return toNamespaceString();
|
public String getSignature() {
|
||||||
|
return getNamespaceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceString() {
|
public String getNamespaceString() {
|
||||||
return getName(true);
|
return getName(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getName(boolean includeNamespace) {
|
private String getName(boolean includeNamespace) {
|
||||||
StringBuilder buffer = new StringBuilder();
|
StringBuilder buffer = new StringBuilder();
|
||||||
if (includeNamespace && namespace != null) {
|
if (includeNamespace && namespace != null) {
|
||||||
buffer.append(namespace.toNamespaceString());
|
buffer.append(namespace.getNamespaceString());
|
||||||
buffer.append(Namespace.DELIMITER);
|
buffer.append(Namespace.DELIMITER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,12 +144,12 @@ public class DemangledType implements Demangled {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceName() {
|
public String getNamespaceName() {
|
||||||
return getName(false);
|
return getName(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return toNamespaceString();
|
return getNamespaceString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,31 +33,11 @@ public class DemangledUnknown extends DemangledObject {
|
||||||
setName(name);
|
setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DemangledUnknown(GenericDemangledVariable other) {
|
|
||||||
// super(other);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
@Override
|
@Override
|
||||||
public String getSignature(boolean format) {
|
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
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
//These items likely do not have names or data types, so return the signature.
|
//These items likely do not have names or data types, so return the signature.
|
||||||
|
|
|
@ -79,7 +79,7 @@ public class DemangledVariable extends DemangledObject {
|
||||||
!(datatype instanceof DemangledFunctionReference) &&
|
!(datatype instanceof DemangledFunctionReference) &&
|
||||||
!(datatype instanceof DemangledFunctionIndirect)) {
|
!(datatype instanceof DemangledFunctionIndirect)) {
|
||||||
if (datatype != null) {
|
if (datatype != null) {
|
||||||
datatypeBuffer.append(datatype.toSignature());
|
datatypeBuffer.append(datatype.getSignature());
|
||||||
spacer = SPACE;
|
spacer = SPACE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ public class DemangledVariable extends DemangledObject {
|
||||||
datatypeBuffer.append(spacer);
|
datatypeBuffer.append(spacer);
|
||||||
spacer = EMPTY_STRING;
|
spacer = EMPTY_STRING;
|
||||||
|
|
||||||
datatypeBuffer.append(namespace.toNamespaceString());
|
datatypeBuffer.append(namespace.getNamespaceString());
|
||||||
|
|
||||||
if (hasName) {
|
if (hasName) {
|
||||||
datatypeBuffer.append(NAMESPACE_SEPARATOR);
|
datatypeBuffer.append(NAMESPACE_SEPARATOR);
|
||||||
|
@ -143,9 +143,6 @@ public class DemangledVariable extends DemangledObject {
|
||||||
datatypeBuffer.append(getName());
|
datatypeBuffer.append(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
datatypeBuffer.append(specialMidfix == null ? EMPTY_STRING : specialMidfix + SPACE);
|
|
||||||
datatypeBuffer.append(specialSuffix == null ? EMPTY_STRING : SPACE + specialSuffix);
|
|
||||||
|
|
||||||
if (datatype instanceof DemangledFunctionPointer) {
|
if (datatype instanceof DemangledFunctionPointer) {
|
||||||
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) datatype;
|
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) datatype;
|
||||||
return buffer.append(funcPtr.toSignature(datatypeBuffer.toString())).toString();
|
return buffer.append(funcPtr.toSignature(datatypeBuffer.toString())).toString();
|
||||||
|
@ -165,7 +162,7 @@ public class DemangledVariable extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toNamespaceName() {
|
public String getNamespaceName() {
|
||||||
|
|
||||||
String n = getDemangledName();
|
String n = getDemangledName();
|
||||||
if (!StringUtils.isBlank(n)) {
|
if (!StringUtils.isBlank(n)) {
|
||||||
|
@ -173,7 +170,7 @@ public class DemangledVariable extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datatype != null) {
|
if (datatype != null) {
|
||||||
return datatype.toSignature();
|
return datatype.getSignature();
|
||||||
}
|
}
|
||||||
return "<no name>"; // shouldn't happen
|
return "<no name>"; // shouldn't happen
|
||||||
}
|
}
|
||||||
|
@ -200,9 +197,6 @@ public class DemangledVariable extends DemangledObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol demangledSymbol = applyDemangledName(address, true, true, program);
|
Symbol demangledSymbol = applyDemangledName(address, true, true, program);
|
||||||
|
|
||||||
//TODO replace existing datatype?
|
|
||||||
|
|
||||||
DataType demangledDT = getProgramDataType(program);
|
DataType demangledDT = getProgramDataType(program);
|
||||||
|
|
||||||
if (address.isExternalAddress()) {
|
if (address.isExternalAddress()) {
|
||||||
|
|
|
@ -101,31 +101,6 @@ public class DemanglerUtil {
|
||||||
return ClassSearcher.getInstances(Demangler.class);
|
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<String> 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
|
* Remove superfluous function signature spaces from specified string
|
||||||
* @param str string
|
* @param str string
|
||||||
|
|
|
@ -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<DemangledDataType> getParameters();
|
|
||||||
}
|
|
|
@ -400,8 +400,7 @@ public class ColorizingPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
ActionContext context = getActionContext();
|
ActionContext context = getActionContext();
|
||||||
performAction(setColorAction, context, false);
|
performAction(setColorAction, context, false);
|
||||||
|
|
||||||
Window chooserWindow = waitForWindow(null, ColorizingServiceProvider.COLOR_CHOOSER_TITLE,
|
Window chooserWindow = waitForWindow(ColorizingServiceProvider.COLOR_CHOOSER_TITLE);
|
||||||
DEFAULT_WINDOW_TIMEOUT);
|
|
||||||
assertNotNull("Did not find Color Chooser", chooserWindow);
|
assertNotNull("Did not find Color Chooser", chooserWindow);
|
||||||
GhidraColorChooser colorChooser = findComponent(chooserWindow, GhidraColorChooser.class);
|
GhidraColorChooser colorChooser = findComponent(chooserWindow, GhidraColorChooser.class);
|
||||||
JButton okButton = findButtonByText(chooserWindow, "OK");
|
JButton okButton = findButtonByText(chooserWindow, "OK");
|
||||||
|
|
|
@ -13,12 +13,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package ghidra.app.util.demangler;
|
package ghidra.app.util.demangler.gnu;
|
||||||
|
|
||||||
// TODO delete this
|
/**
|
||||||
public class DemangledMethod extends DemangledFunction {
|
* Exception to signal a problem parsing a demangled string
|
||||||
|
*/
|
||||||
|
public class DemanglerParseException extends RuntimeException {
|
||||||
|
|
||||||
public DemangledMethod(String name) {
|
public DemanglerParseException(String message) {
|
||||||
super(name);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -209,7 +209,7 @@ public class GnuDemangler implements Demangler {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
GnuDemanglerParser parser = new GnuDemanglerParser(process);
|
GnuDemanglerParser parser = new GnuDemanglerParser();
|
||||||
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
||||||
return demangledObject;
|
return demangledObject;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -145,7 +145,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
|
|
||||||
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
|
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
|
||||||
assertNotNull(s);
|
assertNotNull(s);
|
||||||
assertEquals("typeinfo_name", s.getName());
|
assertEquals("typeinfo-name", s.getName());
|
||||||
assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true));
|
assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true));
|
||||||
|
|
||||||
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks",
|
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks",
|
||||||
|
@ -238,6 +238,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
String demanglerName = GnuDemanglerOptions.GNU_DEMANGLER_DEFAULT;
|
String demanglerName = GnuDemanglerOptions.GNU_DEMANGLER_DEFAULT;
|
||||||
String applicationArguments = "-s MrBob";
|
String applicationArguments = "-s MrBob";
|
||||||
try {
|
try {
|
||||||
|
setErrorsExpected(true);
|
||||||
GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName,
|
GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName,
|
||||||
applicationArguments);
|
applicationArguments);
|
||||||
fail("Expected an exception when passing unknown arguments to the native demangler");
|
fail("Expected an exception when passing unknown arguments to the native demangler");
|
||||||
|
@ -246,7 +247,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
||||||
// expected
|
// expected
|
||||||
Msg.error(this, "Test error", e);
|
Msg.error(this, "Test error", e);
|
||||||
}
|
}
|
||||||
|
setErrorsExpected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address addr(String address) {
|
private Address addr(String address) {
|
||||||
|
|
|
@ -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
|
|
File diff suppressed because it is too large
Load diff
|
@ -614,8 +614,8 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNamespaceDeleted(Namespace namespace2) {
|
private boolean isNamespaceDeleted(Namespace other) {
|
||||||
Symbol nsSymbol = namespace2.getSymbol();
|
Symbol nsSymbol = other.getSymbol();
|
||||||
if (nsSymbol == null) {
|
if (nsSymbol == null) {
|
||||||
return false; // global namespace.
|
return false; // global namespace.
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class MDMangGhidra extends MDMang {
|
||||||
if (objectResult != null) {
|
if (objectResult != null) {
|
||||||
objectResult.setMangledString(mangledArg);
|
objectResult.setMangledString(mangledArg);
|
||||||
// Make our version of the demangled string available (could be large).
|
// Make our version of the demangled string available (could be large).
|
||||||
objectResult.setUtilDemangled(item.toString());
|
objectResult.setOriginalDemangled(item.toString());
|
||||||
}
|
}
|
||||||
return returnedItem;
|
return returnedItem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,25 +218,9 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Window waitForWindowByTitleContaining(String text) {
|
public static Window waitForWindowByTitleContaining(String text) {
|
||||||
return waitForWindowByTitleContaining(null, text, DEFAULT_WAIT_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated
|
|
||||||
* @param parentWindow
|
|
||||||
* @param text
|
|
||||||
* @param timeoutMS
|
|
||||||
* @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
|
// try at least one time
|
||||||
Window window = getWindowByTitleContaining(parentWindow, text);
|
Window window = getWindowByTitleContaining(null, text);
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
return window;// we found it...no waiting required
|
return window;// we found it...no waiting required
|
||||||
}
|
}
|
||||||
|
@ -245,7 +229,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
int timeout = DEFAULT_WAIT_TIMEOUT;
|
int timeout = DEFAULT_WAIT_TIMEOUT;
|
||||||
while (totalTime <= timeout) {
|
while (totalTime <= timeout) {
|
||||||
|
|
||||||
window = getWindowByTitleContaining(parentWindow, text);
|
window = getWindowByTitleContaining(null, text);
|
||||||
if (window != null) {
|
if (window != null) {
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
@ -257,43 +241,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
"Timed-out waiting for window containg title '" + text + "'");
|
"Timed-out waiting for window containg title '" + text + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits for a window with the given name. If <code>parentWindow</code> is not null, then it
|
|
||||||
* will be used to find subordinate windows. If <code>parentWindow</code> 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.
|
* Waits for a window with the given name.
|
||||||
*
|
*
|
||||||
|
@ -1828,25 +1775,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
||||||
useErrorGUI = enable;
|
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
|
* Turns off the gui displays for errors. This does not change the "isUseErrorGUI()" value for
|
||||||
* other tests in the TestCase.
|
* other tests in the TestCase.
|
||||||
|
|
|
@ -248,8 +248,9 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
||||||
*/
|
*/
|
||||||
public static Set<Window> getAllWindows() {
|
public static Set<Window> getAllWindows() {
|
||||||
Set<Window> set = new HashSet<>();
|
Set<Window> set = new HashSet<>();
|
||||||
Frame sharedOwnerFrame = (Frame) AppContext.getAppContext().get(
|
Frame sharedOwnerFrame = (Frame) AppContext.getAppContext()
|
||||||
new StringBuffer("SwingUtilities.sharedOwnerFrame"));
|
.get(
|
||||||
|
new StringBuffer("SwingUtilities.sharedOwnerFrame"));
|
||||||
if (sharedOwnerFrame != null) {
|
if (sharedOwnerFrame != null) {
|
||||||
set.addAll(getAllWindows(sharedOwnerFrame));
|
set.addAll(getAllWindows(sharedOwnerFrame));
|
||||||
}
|
}
|
||||||
|
@ -1515,6 +1516,29 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
||||||
UIManager.put("TextArea.font", f);
|
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
|
* Waits for the Swing thread to process any pending events. This method
|
||||||
* also waits for any {@link SwingUpdateManager}s that have pending events
|
* also waits for any {@link SwingUpdateManager}s that have pending events
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package help.screenshot;
|
package help.screenshot;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
@ -148,7 +148,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator {
|
||||||
makeSelection(0x0406be1, 0x0406bf1);
|
makeSelection(0x0406be1, 0x0406bf1);
|
||||||
|
|
||||||
performAction("Create Table From Selection", "CodeBrowserPlugin", true);
|
performAction("Create Table From Selection", "CodeBrowserPlugin", true);
|
||||||
Window window = waitForWindowByTitleContaining(null, "Selection Table", 2000);
|
Window window = waitForWindowByTitleContaining("Selection Table");
|
||||||
Point loc = plugin.getListingPanel().getLocationOnScreen();
|
Point loc = plugin.getListingPanel().getLocationOnScreen();
|
||||||
Dimension size = window.getSize();
|
Dimension size = window.getSize();
|
||||||
window.setBounds(loc.x + 300, loc.y + 150, size.width, 300);
|
window.setBounds(loc.x + 300, loc.y + 150, size.width, 300);
|
||||||
|
|
|
@ -142,7 +142,7 @@ public class NavigationScreenShots extends GhidraScreenShotGenerator {
|
||||||
setGotoText(dialog, "LAB*");
|
setGotoText(dialog, "LAB*");
|
||||||
pressOkOnDialog();
|
pressOkOnDialog();
|
||||||
Window window =
|
Window window =
|
||||||
waitForWindowByTitleContaining(null, "Search Limit Exceeded!", DEFAULT_WINDOW_TIMEOUT);
|
waitForWindowByTitleContaining("Search Limit Exceeded!");
|
||||||
assertNotNull(window);
|
assertNotNull(window);
|
||||||
pressButtonByText(window, "OK");
|
pressButtonByText(window, "OK");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
||||||
program.endTransaction(txID, false);
|
program.endTransaction(txID, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
* 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.
|
* 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.
|
* 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));
|
assertEquals("ATL", ns.getName(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that the DemangledFunction will properly update a thunk function
|
* Test that the DemangledFunction will properly update a thunk function
|
||||||
* with its namespace, and ripple through to the underlying default thunked
|
* with its namespace, and ripple through to the underlying default thunked
|
||||||
* function. The thunk 'this' parameter should utilize the Class
|
* 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
|
* 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.
|
* functions that live inside of a class that lives inside of a namespace.
|
||||||
* This test applies a demangled name where the mangled name exists.
|
* 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));
|
assertEquals("ATL", ns.getName(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
* 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.
|
* 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.
|
* 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));
|
assertEquals("ATL", ns.getName(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
* 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.
|
* 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
|
* This test applies a demangled name where both the mangled name exists and
|
||||||
|
@ -243,7 +243,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
||||||
assertEquals("ATL", ns.getName(false));
|
assertEquals("ATL", ns.getName(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
* 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.
|
* 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
|
* This test applies a demangled name where the mangled name exists on an external
|
||||||
|
@ -339,7 +339,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
||||||
private void assertSimpleNamespaceExists(String name) {
|
private void assertSimpleNamespaceExists(String name) {
|
||||||
SymbolTable symbolTable = program.getSymbolTable();
|
SymbolTable symbolTable = program.getSymbolTable();
|
||||||
Namespace ns = symbolTable.getNamespace(name, program.getGlobalNamespace());
|
Namespace ns = symbolTable.getNamespace(name, program.getGlobalNamespace());
|
||||||
assertNotNull(ns);
|
assertNotNull("Namespace not created: " + name, ns);
|
||||||
assertEquals(SymbolType.NAMESPACE, ns.getSymbol().getSymbolType());
|
assertEquals(SymbolType.NAMESPACE, ns.getSymbol().getSymbolType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,10 +57,11 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
|
||||||
String mangled = "MyFunction__11MyNamespacePQ215$ParamNamespace9paramName";
|
String mangled = "MyFunction__11MyNamespacePQ215$ParamNamespace9paramName";
|
||||||
|
|
||||||
GnuDemangler demangler = new GnuDemangler();
|
GnuDemangler demangler = new GnuDemangler();
|
||||||
demangler.canDemangle(program);// this perform initialization
|
demangler.canDemangle(program);// this performs initialization
|
||||||
|
|
||||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||||
options.setDemangleOnlyKnownPatterns(false);
|
options.setDemangleOnlyKnownPatterns(false);
|
||||||
|
options = options.withDeprecatedDemangler();
|
||||||
DemangledObject result = demangler.demangle(mangled, options);
|
DemangledObject result = demangler.demangle(mangled, options);
|
||||||
assertNotNull(result);
|
assertNotNull(result);
|
||||||
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
|
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue