mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +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;
|
||||
|
||||
// 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 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
|
||||
* @return the string
|
||||
*/
|
||||
public String getMangledString();
|
||||
|
||||
/**
|
||||
* Sets the original mangled string
|
||||
* @param mangled the mangled string
|
||||
*/
|
||||
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(' ');
|
||||
}
|
||||
String namespaceStr = namespace.toNamespaceString();
|
||||
String namespaceStr = namespace.getNamespaceString();
|
||||
buffer.append(namespaceStr);
|
||||
if (!namespaceStr.endsWith(NAMESPACE_SEPARATOR)) {
|
||||
buffer.append(NAMESPACE_SEPARATOR);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package ghidra.app.util.demangler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -221,7 +222,7 @@ public class DemangledDataType extends DemangledType {
|
|||
dt = createPlaceHolderStructure(name, getNamespace());
|
||||
}
|
||||
}
|
||||
else if (dt == null) { // TODO: Is using whatever was found OK ??
|
||||
else if (dt == null) {
|
||||
|
||||
// I don't know what this is
|
||||
// If it isn't pointed to, or isn't a referent, then assume typedef.
|
||||
|
@ -367,41 +368,43 @@ public class DemangledDataType extends DemangledType {
|
|||
*/
|
||||
static DataType findDataType(DataTypeManager dataTypeManager, Demangled namespace,
|
||||
String dtName) {
|
||||
// TODO: Should be able to search archives somehow
|
||||
ArrayList<DataType> list = new ArrayList<>();
|
||||
|
||||
List<DataType> list = new ArrayList<>();
|
||||
dataTypeManager.findDataTypes(dtName, list);
|
||||
if (!list.isEmpty()) {
|
||||
//use the datatype that exists in the root category,
|
||||
//otherwise just pick the first one...
|
||||
DataType anyDt = null;
|
||||
DataType preferredDataType = null;
|
||||
for (DataType existingDT : list) {
|
||||
if (existingDT instanceof BuiltIn) {
|
||||
continue; // TODO: not sure if this is good - built-ins handled explicitly
|
||||
// by DemangledDataType.getDataType method
|
||||
}
|
||||
if (namespace == null) {
|
||||
if (existingDT.getCategoryPath().equals(CategoryPath.ROOT)) {
|
||||
return existingDT;
|
||||
}
|
||||
anyDt = existingDT;
|
||||
}
|
||||
if (isNamespaceCategoryMatch(existingDT, namespace)) {
|
||||
preferredDataType = existingDT;
|
||||
}
|
||||
}
|
||||
if (preferredDataType != null) {
|
||||
return preferredDataType;
|
||||
}
|
||||
return anyDt;
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
//use the datatype that exists in the root category,
|
||||
//otherwise just pick the first one...
|
||||
DataType anyDt = null;
|
||||
DataType preferredDataType = null;
|
||||
for (DataType existingDT : list) {
|
||||
if (existingDT instanceof BuiltIn) {
|
||||
// not sure if this is good - built-ins handled explicitly by getDataType()
|
||||
continue;
|
||||
}
|
||||
if (namespace == null) {
|
||||
if (existingDT.getCategoryPath().equals(CategoryPath.ROOT)) {
|
||||
return existingDT;
|
||||
}
|
||||
anyDt = existingDT;
|
||||
}
|
||||
if (isNamespaceCategoryMatch(existingDT, namespace)) {
|
||||
preferredDataType = existingDT;
|
||||
}
|
||||
}
|
||||
if (preferredDataType != null) {
|
||||
return preferredDataType;
|
||||
}
|
||||
return anyDt;
|
||||
}
|
||||
|
||||
private static boolean isNamespaceCategoryMatch(DataType dt, Demangled namespace) {
|
||||
if (namespace == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Demangled ns = namespace;
|
||||
CategoryPath categoryPath = dt.getCategoryPath();
|
||||
while (ns != null) {
|
||||
|
@ -433,7 +436,6 @@ public class DemangledDataType extends DemangledType {
|
|||
StructureDataType structDT = new StructureDataType(dtName, 0);
|
||||
structDT.setDescription("PlaceHolder Structure");
|
||||
structDT.setCategoryPath(getDemanglerCategoryPath(dtName, namespace));
|
||||
|
||||
return structDT;
|
||||
}
|
||||
|
||||
|
@ -617,10 +619,6 @@ public class DemangledDataType extends DemangledType {
|
|||
boolean isPrimitiveDT =
|
||||
!isArray() && !isClass && !isComplex && !isEnum && !isPointer() && !isPointer64 &&
|
||||
!isSigned && !isTemplate && !isUnion && !isCoclass && !isCointerface && !isVarArgs;
|
||||
// boolean isPrimitiveDT = !isArray && !isClass && !isComplex && !isEnum && !isPointer() &&
|
||||
// !isPointer64 && !isSigned && !isTemplate && !isUnion && !isVarArgs;
|
||||
// boolean isPrimitiveDT = !isArray && !isClass && !isComplex && !isEnum && !isPointer() &&
|
||||
// !isPointer64 && !isSigned && !isTemplate && !isUnion && !isVarArgs && !isVolatile;
|
||||
if (isPrimitiveDT) {
|
||||
for (String primitiveNames : PRIMITIVES) {
|
||||
if (getName().equals(primitiveNames)) {
|
||||
|
@ -631,8 +629,7 @@ public class DemangledDataType extends DemangledType {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
public String getSignature() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (isUnion) {
|
||||
|
@ -659,9 +656,6 @@ public class DemangledDataType extends DemangledType {
|
|||
if (isComplex) {
|
||||
buffer.append(COMPLEX + SPACE);
|
||||
}
|
||||
// if (isVolatile) {
|
||||
// buffer.append(VOLATILE + SPACE);
|
||||
// }
|
||||
if (isSigned) {
|
||||
buffer.append(SIGNED + SPACE);
|
||||
}
|
||||
|
@ -670,7 +664,7 @@ public class DemangledDataType extends DemangledType {
|
|||
}
|
||||
|
||||
if (getNamespace() != null) {
|
||||
buffer.append(getNamespace().toNamespaceString());
|
||||
buffer.append(getNamespace().getNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
|
||||
|
@ -684,7 +678,6 @@ public class DemangledDataType extends DemangledType {
|
|||
buffer.append(SPACE + CONST);
|
||||
}
|
||||
|
||||
// TODO: The output of volatile belongs here, not above, so I put the commented code here for now.
|
||||
if (isVolatile()) {
|
||||
buffer.append(SPACE + VOLATILE);
|
||||
}
|
||||
|
@ -709,7 +702,8 @@ public class DemangledDataType extends DemangledType {
|
|||
buffer.append(SPACE + REF_NOTATION);
|
||||
}
|
||||
|
||||
//Order of __ptr64 and __restrict can vary--with fuzzing... but what is the natural "real symbol" order?
|
||||
// the order of __ptr64 and __restrict can vary--with fuzzing...
|
||||
// but what is the natural "real symbol" order?
|
||||
if (isPointer64) {
|
||||
buffer.append(SPACE + PTR64);
|
||||
}
|
||||
|
@ -736,7 +730,7 @@ public class DemangledDataType extends DemangledType {
|
|||
|
||||
@Override
|
||||
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.function.*;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.PrototypeModel;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.program.model.util.CodeUnitInsertionException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* A class to represent a demangled function.
|
||||
*/
|
||||
public class DemangledFunction extends DemangledObject implements ParameterReceiver {
|
||||
public class DemangledFunction extends DemangledObject {
|
||||
|
||||
public static final String VOLATILE = "volatile";
|
||||
public static final String CONST = "const";
|
||||
|
@ -104,18 +106,10 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
this.isOverloadedOperator = isOverloadedOperator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.util.demangler.ParameterReceiver
|
||||
*/
|
||||
@Override
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.util.demangler.ParameterReceiver
|
||||
*/
|
||||
@Override
|
||||
public List<DemangledDataType> getParameters() {
|
||||
return new ArrayList<>(parameters);
|
||||
}
|
||||
|
@ -198,7 +192,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
|
||||
@Override
|
||||
public String getSignature(boolean format) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (!(returnType instanceof DemangledFunctionPointer)) {
|
||||
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
||||
|
@ -214,38 +208,26 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
buffer.append("static ");
|
||||
}
|
||||
if (!isTypeCast()) {
|
||||
buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
|
||||
buffer.append(returnType == null ? "" : returnType.getSignature() + " ");
|
||||
}
|
||||
// buffer.append(returnType == null ? "" : returnType.toSignature() + " ");
|
||||
}
|
||||
|
||||
buffer.append(callingConvention == null ? "" : callingConvention + " ");
|
||||
if (namespace != null) {
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(namespace.getNamespaceString());
|
||||
buffer.append(NAMESPACE_SEPARATOR);
|
||||
}
|
||||
|
||||
buffer.append(getDemangledName());
|
||||
if (isTypeCast()) {
|
||||
buffer.append(returnType == null ? "" : " " + returnType.toSignature() + " ");
|
||||
buffer.append(returnType == null ? "" : " " + returnType.getSignature() + " ");
|
||||
}
|
||||
|
||||
if (template != null) {
|
||||
buffer.append(template.toTemplate());
|
||||
}
|
||||
|
||||
if (specialMidfix != null) {
|
||||
buffer.append('[').append(specialMidfix).append(']');
|
||||
}
|
||||
|
||||
// check for special case of 'conversion operator' where we only want to display '()' and
|
||||
// not (void)
|
||||
// if (name.endsWith("()")) {
|
||||
// if (name.equals("operator")) {
|
||||
// buffer.append("()");
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
if (templatedConstructorType != null) {
|
||||
buffer.append('<').append(templatedConstructorType).append('>');
|
||||
}
|
||||
|
@ -258,7 +240,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
}
|
||||
|
||||
while (paramIterator.hasNext()) {
|
||||
buffer.append(paramIterator.next().toSignature());
|
||||
buffer.append(paramIterator.next().getSignature());
|
||||
if (paramIterator.hasNext()) {
|
||||
buffer.append(',');
|
||||
if (format) {
|
||||
|
@ -270,26 +252,19 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
|
||||
buffer.append(')');
|
||||
buffer.append(storageClass == null ? "" : " " + storageClass);
|
||||
// }
|
||||
|
||||
if (returnType instanceof DemangledFunctionPointer) {
|
||||
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) returnType;
|
||||
String partialSig = funcPtr.toSignature(buffer.toString());
|
||||
buffer = new StringBuffer();
|
||||
buffer = new StringBuilder();
|
||||
buffer.append(specialPrefix == null ? "" : specialPrefix + " ");
|
||||
buffer.append(
|
||||
visibility == null || "global".equals(visibility) ? "" : visibility + " ");
|
||||
//if (virtual || super.isVirtual) {
|
||||
if (isVirtual) {
|
||||
buffer.append("virtual ");
|
||||
}
|
||||
buffer.append(partialSig);
|
||||
}
|
||||
else {
|
||||
if (specialSuffix != null) {
|
||||
buffer.append(specialSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
if (isTrailingConst()) {
|
||||
if (buffer.length() > 2) {
|
||||
|
@ -332,7 +307,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
public String getNamespaceName() {
|
||||
return getName() + getParameterString();
|
||||
}
|
||||
|
||||
|
@ -341,7 +316,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
buffer.append('(');
|
||||
Iterator<DemangledDataType> dditer = parameters.iterator();
|
||||
while (dditer.hasNext()) {
|
||||
buffer.append(dditer.next().toSignature());
|
||||
buffer.append(dditer.next().getSignature());
|
||||
if (dditer.hasNext()) {
|
||||
buffer.append(',');
|
||||
}
|
||||
|
@ -452,13 +427,13 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
for (int i = 0; i < args.size(); i++) {
|
||||
if (args.get(i).getLength() > pointerSize) {
|
||||
bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler",
|
||||
"Couldn't Apply demangled signature - probably due to datatype that is too " +
|
||||
"Couldn't apply demangled signature - probably due to datatype that is too " +
|
||||
"large to fit in a parameter");
|
||||
}
|
||||
}
|
||||
|
||||
bookmarkManager.setBookmark(address, BookmarkType.ANALYSIS, "Demangler",
|
||||
"Couldn't Apply demangled signature - bad parameter number match (" + args.size() +
|
||||
"Couldn't apply demangled signature - bad parameter number match (" + args.size() +
|
||||
") in a function in a namespace");
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
// It appears that is passed as an additional parameter. Essentially, it accesses
|
||||
// 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 (THIS_CALL.equals(func.getCallingConventionName())) {
|
||||
if (THIS_CALL.equals(function.getCallingConventionName())) {
|
||||
String n = getName();
|
||||
if (n.equals("~" + namespace.getName()) || n.equals(namespace.getName())) {
|
||||
// constructor && destructor
|
||||
|
@ -507,47 +483,50 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
return null;
|
||||
}
|
||||
|
||||
private Structure maybeUpdateCallingConventionAndCreateClass(Program program, Function func) {
|
||||
try {
|
||||
// If the calling convention is known, should use it!
|
||||
if (callingConvention != null) {
|
||||
if (program.getCompilerSpec().getCallingConvention(callingConvention) == null) {
|
||||
// warn that calling convention not found. Datatypes are still good,
|
||||
// the real calling convention can be figured out later
|
||||
// For example X64 can have __cdecl, __fastcall, __stdcall, that are accepted but ignored
|
||||
program.getBookmarkManager()
|
||||
.setBookmark(func.getEntryPoint(),
|
||||
BookmarkType.ANALYSIS, "Demangler",
|
||||
"Warning calling convention \"" +
|
||||
callingConvention + "\" not defined in Compiler Spec (.cspec)");
|
||||
}
|
||||
else {
|
||||
func.setCallingConvention(callingConvention);
|
||||
if (THIS_CALL.equals(callingConvention)) {
|
||||
return createClassStructure(program, func);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private Structure maybeUpdateCallingConventionAndCreateClass(Program program,
|
||||
Function function) {
|
||||
|
||||
if (isThisCall(func)) {
|
||||
func.setCallingConvention(THIS_CALL);
|
||||
return createClassStructure(program, func);
|
||||
String convention = validateCallingConvention(program, function);
|
||||
if (convention == null) {
|
||||
if (!isThisCall(function)) {
|
||||
return null;
|
||||
}
|
||||
// Leave the calling convention to someone else to figure out
|
||||
// else {
|
||||
// String defaultConvention = getDefaultCallingConvention(program);
|
||||
// if (defaultConvention != null) {
|
||||
// func.setCallingConvention(defaultConvention);
|
||||
// }
|
||||
// }
|
||||
convention = THIS_CALL;
|
||||
}
|
||||
|
||||
try {
|
||||
function.setCallingConvention(convention);
|
||||
return maybeCreateClassStructure(program, function, convention);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
e.printStackTrace();
|
||||
Msg.error(this, "Unexpected exception setting calling convention", e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String validateCallingConvention(Program program, Function function) {
|
||||
|
||||
if (callingConvention == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (program.getCompilerSpec().getCallingConvention(callingConvention) == null) {
|
||||
// warn that calling convention not found. Datatypes are still good,
|
||||
// the real calling convention can be figured out later
|
||||
// For example X64 can have __cdecl, __fastcall, __stdcall, that
|
||||
// are accepted but ignored
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
Address entry = function.getEntryPoint();
|
||||
bm.setBookmark(entry, BookmarkType.ANALYSIS, "Demangler",
|
||||
"Could not apply calling convention \"" + callingConvention +
|
||||
"\" not defined in Compiler Spec (.cspec)");
|
||||
return null;
|
||||
}
|
||||
|
||||
return callingConvention;
|
||||
}
|
||||
|
||||
private List<ParameterDefinitionImpl> convertMangledToParamDef(Program program) {
|
||||
|
||||
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
|
||||
// TODO: this seems too flexible - why not use equals?
|
||||
// TODO: this seems too flexible - why not use equals?
|
||||
if (n.startsWith(namespace.getName())) {
|
||||
return true;
|
||||
}
|
||||
|
@ -686,7 +665,7 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: It STILL COULD be a this call, we just don't know!
|
||||
// It STILL COULD be a this call, we just don't know!
|
||||
// But is also could be a static member function!
|
||||
// The only way to really tell is compare the number of detected parameters
|
||||
// to the number of parameters we have, OR, to detect the calling convention
|
||||
|
@ -707,13 +686,58 @@ public class DemangledFunction extends DemangledObject implements ParameterRecei
|
|||
if (ns == null) {
|
||||
return false;
|
||||
}
|
||||
if (ns.getName().toLowerCase().equals(STD_NAMESPACE)) {
|
||||
if (ns.getName().equalsIgnoreCase(STD_NAMESPACE)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Function createFunction(Program prog, Address addr, boolean doDisassembly,
|
||||
protected Structure maybeCreateClassStructure(Program program, Function function,
|
||||
String convention) {
|
||||
|
||||
if (!THIS_CALL.equals(convention)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (namespace == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String className = namespace.getName();
|
||||
Symbol parentSymbol = function.getSymbol().getParentSymbol();
|
||||
if (parentSymbol.getSymbolType() == SymbolType.NAMESPACE) {
|
||||
try {
|
||||
NamespaceUtils.convertNamespaceToClass((Namespace) parentSymbol.getObject());
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException(e); // unexpected condition
|
||||
}
|
||||
}
|
||||
|
||||
// Store class structure in parent namespace
|
||||
Demangled classNamespace = namespace.getNamespace();
|
||||
DataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType existingType =
|
||||
DemangledDataType.findDataType(dataTypeManager, classNamespace, className);
|
||||
if (existingType != null && !(existingType instanceof Structure)) {
|
||||
BookmarkManager bm = program.getBookmarkManager();
|
||||
Address entry = function.getEntryPoint();
|
||||
bm.setBookmark(entry, BookmarkType.ANALYSIS, "Demangler",
|
||||
"Could not create class structure, data type already exists: " + existingType);
|
||||
return null;
|
||||
}
|
||||
|
||||
Structure structure = (Structure) existingType;
|
||||
if (structure == null) {
|
||||
structure = DemangledDataType.createPlaceHolderStructure(className,
|
||||
classNamespace);
|
||||
}
|
||||
structure = (Structure) dataTypeManager.resolve(structure,
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
return structure;
|
||||
}
|
||||
|
||||
protected Function createFunction(Program prog, Address addr, boolean doDisassembly,
|
||||
TaskMonitor monitor) {
|
||||
Listing listing = prog.getListing();
|
||||
Function func = listing.getFunctionAt(addr);
|
||||
|
|
|
@ -27,7 +27,7 @@ import ghidra.program.model.data.*;
|
|||
* is still an indirect definition (not a regular function definition). The
|
||||
* function indirect is prevalent in the Microsoft model, if not other models.
|
||||
*/
|
||||
public class DemangledFunctionIndirect extends DemangledDataType implements ParameterReceiver {
|
||||
public class DemangledFunctionIndirect extends DemangledDataType {
|
||||
|
||||
private static final String DEFAULT_NAME_PREFIX = "FuncDef";
|
||||
private static final String NAMESPACE_DELIMITER = "::";
|
||||
|
@ -58,23 +58,6 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
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.
|
||||
* @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
|
||||
* this demangled function.
|
||||
* Adds a parameters to the end of the parameter list for this demangled function
|
||||
* @param parameter the new parameter to add
|
||||
*/
|
||||
@Override
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the parameters for this demangled functions.
|
||||
* Returns a list of the parameters for this demangled functions
|
||||
* @return a list of the parameters for this demangled functions
|
||||
*/
|
||||
@Override
|
||||
public List<DemangledDataType> getParameters() {
|
||||
return new ArrayList<>(parameters);
|
||||
}
|
||||
|
@ -195,13 +175,13 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
public String getSignature() {
|
||||
return toSignature(null);
|
||||
}
|
||||
|
||||
public String toSignature(String name) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuffer buffer1 = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
StringBuilder buffer1 = new StringBuilder();
|
||||
String s = getConventionPointerNameString(name);
|
||||
if (s.contains(" ") || s.isEmpty()) {
|
||||
// spaces--add parens
|
||||
|
@ -213,7 +193,7 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
|
||||
buffer1.append('(');
|
||||
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) {
|
||||
buffer1.append(',');
|
||||
}
|
||||
|
@ -222,21 +202,24 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
|
||||
if (returnType instanceof DemangledFunctionPointer) {
|
||||
buffer.append(
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionReference) {
|
||||
buffer.append(
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||
buffer.append(
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else {
|
||||
buffer.append(returnType.toSignature()).append(SPACE);
|
||||
buffer.append(returnType.getSignature()).append(SPACE);
|
||||
buffer.append(buffer1);
|
||||
}
|
||||
|
||||
|
@ -278,7 +261,7 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void addFunctionPointerParens(StringBuffer buffer, String s) {
|
||||
private void addFunctionPointerParens(StringBuilder buffer, String s) {
|
||||
if (!displayFunctionPointerParens) {
|
||||
return;
|
||||
}
|
||||
|
@ -322,9 +305,6 @@ public class DemangledFunctionIndirect extends DemangledDataType implements Para
|
|||
}
|
||||
|
||||
if (name != null) {
|
||||
// if (buffer.length() > 2) {
|
||||
// buffer.append(SPACE);
|
||||
// }
|
||||
if ((buffer.length() > 2) && (buffer.charAt(buffer.length() - 1) != SPACE)) {
|
||||
buffer.append(SPACE);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import ghidra.program.model.data.*;
|
|||
/**
|
||||
* 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 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
|
||||
* this demangled function.
|
||||
* Adds a parameters to the end of the parameter list for this demangled function
|
||||
* @param parameter the new parameter to add
|
||||
*/
|
||||
@Override
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
@ -144,7 +142,6 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
|||
* Returns a list of the parameters for this demangled functions.
|
||||
* @return a list of the parameters for this demangled functions
|
||||
*/
|
||||
@Override
|
||||
public List<DemangledDataType> getParameters() {
|
||||
return new ArrayList<>(parameters);
|
||||
}
|
||||
|
@ -174,7 +171,7 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
public String getSignature() {
|
||||
return toSignature(null);
|
||||
}
|
||||
|
||||
|
@ -192,7 +189,7 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
|||
|
||||
buffer1.append('(');
|
||||
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) {
|
||||
buffer1.append(',');
|
||||
}
|
||||
|
@ -200,25 +197,19 @@ public class DemangledFunctionPointer extends DemangledDataType implements Param
|
|||
buffer1.append(')');
|
||||
|
||||
if (returnType instanceof DemangledFunctionPointer) {
|
||||
buffer.append(
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
DemangledFunctionPointer dfp = (DemangledFunctionPointer) returnType;
|
||||
buffer.append(dfp.toSignature(buffer1.toString())).append(SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionReference) {
|
||||
buffer.append(
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
DemangledFunctionReference dfr = (DemangledFunctionReference) returnType;
|
||||
buffer.append(dfr.toSignature(buffer1.toString())).append(SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||
buffer.append(
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
DemangledFunctionIndirect dfi = (DemangledFunctionIndirect) returnType;
|
||||
buffer.append(dfi.toSignature(buffer1.toString())).append(SPACE);
|
||||
}
|
||||
else {
|
||||
buffer.append(returnType.toSignature()).append(SPACE);
|
||||
buffer.append(returnType.getSignature()).append(SPACE);
|
||||
buffer.append(buffer1);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import ghidra.program.model.data.*;
|
|||
/**
|
||||
* 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 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
|
||||
* this demangled function.
|
||||
* Adds a parameters to the end of the parameter list for this demangled function
|
||||
* @param parameter the new parameter to add
|
||||
*/
|
||||
@Override
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
@ -144,7 +142,6 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
|||
* Returns a list of the parameters for this demangled functions.
|
||||
* @return a list of the parameters for this demangled functions
|
||||
*/
|
||||
@Override
|
||||
public List<DemangledDataType> getParameters() {
|
||||
return new ArrayList<>(parameters);
|
||||
}
|
||||
|
@ -174,7 +171,7 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toSignature() {
|
||||
public String getSignature() {
|
||||
return toSignature(null);
|
||||
}
|
||||
|
||||
|
@ -192,7 +189,7 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
|||
|
||||
buffer1.append('(');
|
||||
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) {
|
||||
buffer1.append(',');
|
||||
}
|
||||
|
@ -201,21 +198,24 @@ public class DemangledFunctionReference extends DemangledDataType implements Par
|
|||
|
||||
if (returnType instanceof DemangledFunctionPointer) {
|
||||
buffer.append(
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionPointer) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionReference) {
|
||||
buffer.append(
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionReference) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else if (returnType instanceof DemangledFunctionIndirect) {
|
||||
buffer.append(
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString())).append(
|
||||
SPACE);
|
||||
((DemangledFunctionIndirect) returnType).toSignature(buffer1.toString()))
|
||||
.append(
|
||||
SPACE);
|
||||
}
|
||||
else {
|
||||
buffer.append(returnType.toSignature()).append(SPACE);
|
||||
buffer.append(returnType.getSignature()).append(SPACE);
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents a demangled lambda function
|
||||
*/
|
||||
public class DemangledLambda extends DemangledFunction {
|
||||
|
||||
public DemangledLambda(String name) {
|
||||
|
@ -22,7 +25,7 @@ public class DemangledLambda extends DemangledFunction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
public String getNamespaceName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,12 @@ import java.util.regex.Pattern;
|
|||
import ghidra.app.cmd.label.SetLabelPrimaryCmd;
|
||||
import ghidra.app.util.NamespaceUtils;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.*;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
|
@ -41,10 +42,8 @@ public abstract class DemangledObject implements Demangled {
|
|||
protected static final String EMPTY_STRING = "";
|
||||
|
||||
protected String mangled; // original mangled string
|
||||
protected String utilDemangled;
|
||||
protected String originalDemangled;
|
||||
protected String specialPrefix;
|
||||
protected String specialMidfix;
|
||||
protected String specialSuffix;
|
||||
protected Demangled namespace;
|
||||
protected String visibility;//public, protected, etc.
|
||||
|
||||
|
@ -75,23 +74,11 @@ public abstract class DemangledObject implements Demangled {
|
|||
// default
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unmodified demangled name of this object.
|
||||
* This name may contain whitespace and other characters not
|
||||
* supported for symbol or data type creation. See {@link #getName()}
|
||||
* for the same name modified for use within Ghidra.
|
||||
* @return name of this DemangledObject
|
||||
*/
|
||||
@Override
|
||||
public String getDemangledName() {
|
||||
return demangledName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the demangled name of this object.
|
||||
* NOTE: unsupported symbol characters, like whitespace, will be
|
||||
* converted to an underscore.
|
||||
* @return name of this DemangledObject with unsupported characters converted to underscore
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
@ -181,6 +168,7 @@ public abstract class DemangledObject implements Demangled {
|
|||
* Sets the name of the demangled object
|
||||
* @param name the new name
|
||||
*/
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.demangledName = name;
|
||||
this.name = name;
|
||||
|
@ -202,20 +190,14 @@ public abstract class DemangledObject implements Demangled {
|
|||
return mangled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the demangled output from a supplemental utility.
|
||||
* @param utilDemangled the demangled string
|
||||
*/
|
||||
public void setUtilDemangled(String utilDemangled) {
|
||||
this.utilDemangled = utilDemangled;
|
||||
@Override
|
||||
public void setOriginalDemangled(String originalDemangled) {
|
||||
this.originalDemangled = originalDemangled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the demangled output from a supplemental utility.
|
||||
* @return the demangled String created for this object.
|
||||
*/
|
||||
public String getUtilDemangled() {
|
||||
return utilDemangled;
|
||||
@Override
|
||||
public String getOriginalDemangled() {
|
||||
return originalDemangled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -252,22 +234,6 @@ public abstract class DemangledObject implements Demangled {
|
|||
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.
|
||||
* <br>For example:
|
||||
|
@ -281,12 +247,17 @@ public abstract class DemangledObject implements Demangled {
|
|||
*/
|
||||
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)
|
||||
* @return the signature
|
||||
*/
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
public String getNamespaceName() {
|
||||
return getSignature(false);
|
||||
}
|
||||
|
||||
|
@ -305,13 +276,13 @@ public abstract class DemangledObject implements Demangled {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceString() {
|
||||
public String getNamespaceString() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (namespace != null) {
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(namespace.getNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
buffer.append(toNamespaceName());
|
||||
buffer.append(getNamespaceName());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
@ -366,8 +337,8 @@ public abstract class DemangledObject implements Demangled {
|
|||
}
|
||||
|
||||
protected String generatePlateComment() {
|
||||
if (utilDemangled != null) {
|
||||
return utilDemangled;
|
||||
if (originalDemangled != null) {
|
||||
return originalDemangled;
|
||||
}
|
||||
return (signature == null) ? getSignature(true) : signature;
|
||||
}
|
||||
|
@ -446,22 +417,20 @@ public abstract class DemangledObject implements Demangled {
|
|||
* @return list of namespace names
|
||||
*/
|
||||
private static List<String> getNamespaceList(Demangled typeNamespace) {
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
List<String> list = new ArrayList<>();
|
||||
Demangled ns = typeNamespace;
|
||||
while (ns != null) {
|
||||
list.add(0, ns.getName());
|
||||
list.add(0, ns.getNamespaceName());
|
||||
ns = ns.getNamespace();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// TODO needs updating. Couldn't determine what getResigualNamespacePath was changed to.
|
||||
/**
|
||||
* Get or create the specified typeNamespace. The returned namespace may only be a partial
|
||||
* namespace if errors occurred. The caller should check the returned namespace and adjust
|
||||
* any symbol creation accordingly. Caller should use
|
||||
* <code>getResidualNamespacePath(DemangledType, Namespace)</code> to handle the case where
|
||||
* only a partial namespace has been returned.
|
||||
* any symbol creation accordingly.
|
||||
*
|
||||
* @param program the program
|
||||
* @param typeNamespace demangled namespace
|
||||
* @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();
|
||||
}
|
||||
|
||||
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) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
if (specialPrefix != null) {
|
||||
buffer.append(specialPrefix + " for ");
|
||||
buffer.append(specialPrefix);
|
||||
}
|
||||
buffer.append(string);
|
||||
if (specialSuffix != null) {
|
||||
buffer.append(" " + specialSuffix);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
@ -72,9 +69,9 @@ public class DemangledString extends DemangledObject {
|
|||
public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
||||
TaskMonitor monitor) throws Exception {
|
||||
|
||||
String label = SymbolUtilities.replaceInvalidChars(string, false);
|
||||
String label = buildStringLabel();
|
||||
if (hasLabel(program, address, label)) {
|
||||
return true; // Desired symbol already exists here.
|
||||
return true; // This string has already been applied
|
||||
}
|
||||
|
||||
if (!super.applyTo(program, address, options, monitor)) {
|
||||
|
@ -88,24 +85,24 @@ public class DemangledString extends DemangledObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
// TODO: should we be using length ?
|
||||
CreateStringCmd cmd = new CreateStringCmd(address, -1, isUnicode());
|
||||
cmd.applyTo(program);
|
||||
|
||||
// unclear what demangled name should be used so apply
|
||||
// fabricated string label which is more useful than mangled name
|
||||
Symbol demangledSymbol =
|
||||
applyDemangledName(buildStringLabel(), address, true, false, program);
|
||||
applyDemangledName(label, address, true, false, program);
|
||||
return (demangledSymbol != null);
|
||||
}
|
||||
|
||||
private String buildStringLabel() {
|
||||
// build string label consistent with dynamic label formatting
|
||||
|
||||
if (specialPrefix != null) {
|
||||
// a 'special prefix' implies that the author wishes to apply the string exactly as-is
|
||||
return getName();
|
||||
}
|
||||
|
||||
// build string label consistent with dynamic label formatting
|
||||
int len = string.length();
|
||||
StringBuffer buf = new StringBuffer(len);
|
||||
StringBuilder buf = new StringBuilder(len);
|
||||
for (int i = 0; i < len; ++i) {
|
||||
char c = string.charAt(i);
|
||||
if (StringUtilities.isDisplayable(c) && (c != ' ')) {
|
||||
|
|
|
@ -19,31 +19,23 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
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>();
|
||||
|
||||
@Override
|
||||
public void addParameter(DemangledDataType parameter) {
|
||||
parameters.add(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DemangledDataType> getParameters() {
|
||||
return new ArrayList<DemangledDataType>(parameters);
|
||||
}
|
||||
|
||||
public String toTemplate() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append('<');
|
||||
for (int i = 0; i < parameters.size(); ++i) {
|
||||
try {
|
||||
buffer.append(parameters.get(i).toSignature());
|
||||
}
|
||||
catch (Error e) {
|
||||
Msg.error(this, "Unexpected Error: " + e.getMessage(), e);
|
||||
}
|
||||
buffer.append(parameters.get(i).getSignature());
|
||||
if (i < parameters.size() - 1) {
|
||||
buffer.append(',');
|
||||
}
|
||||
|
|
|
@ -17,7 +17,12 @@ package ghidra.app.util.demangler;
|
|||
|
||||
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 {
|
||||
private String demangledName;
|
||||
private String name;
|
||||
|
@ -26,37 +31,23 @@ public class DemangledType implements Demangled {
|
|||
protected DemangledTemplate template;
|
||||
private boolean isConst;
|
||||
private boolean isVolatile;
|
||||
private String originalDemangled;
|
||||
|
||||
public DemangledType(String name) {
|
||||
setName(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
|
||||
*/
|
||||
@Override
|
||||
public String getDemangledName() {
|
||||
return demangledName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of this type.
|
||||
* NOTE: unsupported symbol characters, like whitespace, will be
|
||||
* converted to an underscore.
|
||||
* @return name of this DemangledType suitable for namespace creation.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the demangled type object.
|
||||
* @param name the new name
|
||||
*/
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
demangledName = name;
|
||||
this.name = name;
|
||||
|
@ -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
|
||||
public void setMangledString(String mangled) {
|
||||
this.mangled = mangled;
|
||||
|
@ -113,19 +114,20 @@ public class DemangledType implements Demangled {
|
|||
this.template = template;
|
||||
}
|
||||
|
||||
public String toSignature() {
|
||||
return toNamespaceString();
|
||||
@Override
|
||||
public String getSignature() {
|
||||
return getNamespaceName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceString() {
|
||||
public String getNamespaceString() {
|
||||
return getName(true);
|
||||
}
|
||||
|
||||
private String getName(boolean includeNamespace) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
if (includeNamespace && namespace != null) {
|
||||
buffer.append(namespace.toNamespaceString());
|
||||
buffer.append(namespace.getNamespaceString());
|
||||
buffer.append(Namespace.DELIMITER);
|
||||
}
|
||||
|
||||
|
@ -142,12 +144,12 @@ public class DemangledType implements Demangled {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
public String getNamespaceName() {
|
||||
return getName(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toNamespaceString();
|
||||
return getNamespaceString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,31 +33,11 @@ public class DemangledUnknown extends DemangledObject {
|
|||
setName(name);
|
||||
}
|
||||
|
||||
// DemangledUnknown(GenericDemangledVariable other) {
|
||||
// super(other);
|
||||
// }
|
||||
//
|
||||
@Override
|
||||
public String getSignature(boolean format) {
|
||||
return utilDemangled;
|
||||
return originalDemangled;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// protected boolean isAlreadyDemangled(Program program, Address address) {
|
||||
// return !utilDemangled.isEmpty();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean applyTo(Program program, Address address, DemanglerOptions options,
|
||||
// TaskMonitor monitor) throws Exception {
|
||||
//
|
||||
// if (isAlreadyDemangled(program, address)) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// return super.applyTo(program, address, options, monitor);
|
||||
// }
|
||||
//
|
||||
@Override
|
||||
public String getName() {
|
||||
//These items likely do not have names or data types, so return the signature.
|
||||
|
|
|
@ -79,7 +79,7 @@ public class DemangledVariable extends DemangledObject {
|
|||
!(datatype instanceof DemangledFunctionReference) &&
|
||||
!(datatype instanceof DemangledFunctionIndirect)) {
|
||||
if (datatype != null) {
|
||||
datatypeBuffer.append(datatype.toSignature());
|
||||
datatypeBuffer.append(datatype.getSignature());
|
||||
spacer = SPACE;
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public class DemangledVariable extends DemangledObject {
|
|||
datatypeBuffer.append(spacer);
|
||||
spacer = EMPTY_STRING;
|
||||
|
||||
datatypeBuffer.append(namespace.toNamespaceString());
|
||||
datatypeBuffer.append(namespace.getNamespaceString());
|
||||
|
||||
if (hasName) {
|
||||
datatypeBuffer.append(NAMESPACE_SEPARATOR);
|
||||
|
@ -143,9 +143,6 @@ public class DemangledVariable extends DemangledObject {
|
|||
datatypeBuffer.append(getName());
|
||||
}
|
||||
|
||||
datatypeBuffer.append(specialMidfix == null ? EMPTY_STRING : specialMidfix + SPACE);
|
||||
datatypeBuffer.append(specialSuffix == null ? EMPTY_STRING : SPACE + specialSuffix);
|
||||
|
||||
if (datatype instanceof DemangledFunctionPointer) {
|
||||
DemangledFunctionPointer funcPtr = (DemangledFunctionPointer) datatype;
|
||||
return buffer.append(funcPtr.toSignature(datatypeBuffer.toString())).toString();
|
||||
|
@ -165,7 +162,7 @@ public class DemangledVariable extends DemangledObject {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String toNamespaceName() {
|
||||
public String getNamespaceName() {
|
||||
|
||||
String n = getDemangledName();
|
||||
if (!StringUtils.isBlank(n)) {
|
||||
|
@ -173,7 +170,7 @@ public class DemangledVariable extends DemangledObject {
|
|||
}
|
||||
|
||||
if (datatype != null) {
|
||||
return datatype.toSignature();
|
||||
return datatype.getSignature();
|
||||
}
|
||||
return "<no name>"; // shouldn't happen
|
||||
}
|
||||
|
@ -200,9 +197,6 @@ public class DemangledVariable extends DemangledObject {
|
|||
}
|
||||
|
||||
Symbol demangledSymbol = applyDemangledName(address, true, true, program);
|
||||
|
||||
//TODO replace existing datatype?
|
||||
|
||||
DataType demangledDT = getProgramDataType(program);
|
||||
|
||||
if (address.isExternalAddress()) {
|
||||
|
|
|
@ -101,31 +101,6 @@ public class DemanglerUtil {
|
|||
return ClassSearcher.getInstances(Demangler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the list of names into a namespace demangled type.
|
||||
* Given names = { "A", "B", "C" }, which represents "A::B::C".
|
||||
* The following will be created {@literal "Namespace{A}->Namespace{B}->Namespace{C}"}
|
||||
* and Namespace{C} will be returned.
|
||||
*
|
||||
* NOTE: the list will be empty after the call.
|
||||
* @param names the names to convert
|
||||
* @return the newly created type
|
||||
*/
|
||||
public static DemangledType convertToNamespaces(List<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
|
||||
* @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();
|
||||
performAction(setColorAction, context, false);
|
||||
|
||||
Window chooserWindow = waitForWindow(null, ColorizingServiceProvider.COLOR_CHOOSER_TITLE,
|
||||
DEFAULT_WINDOW_TIMEOUT);
|
||||
Window chooserWindow = waitForWindow(ColorizingServiceProvider.COLOR_CHOOSER_TITLE);
|
||||
assertNotNull("Did not find Color Chooser", chooserWindow);
|
||||
GhidraColorChooser colorChooser = findComponent(chooserWindow, GhidraColorChooser.class);
|
||||
JButton okButton = findButtonByText(chooserWindow, "OK");
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* 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) {
|
||||
super(name);
|
||||
public DemanglerParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -209,7 +209,7 @@ public class GnuDemangler implements Demangler {
|
|||
return null;
|
||||
}
|
||||
|
||||
GnuDemanglerParser parser = new GnuDemanglerParser(process);
|
||||
GnuDemanglerParser parser = new GnuDemanglerParser();
|
||||
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
||||
return demangledObject;
|
||||
}
|
||||
|
|
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"));
|
||||
assertNotNull(s);
|
||||
assertEquals("typeinfo_name", s.getName());
|
||||
assertEquals("typeinfo-name", s.getName());
|
||||
assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true));
|
||||
|
||||
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks",
|
||||
|
@ -238,6 +238,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
|||
String demanglerName = GnuDemanglerOptions.GNU_DEMANGLER_DEFAULT;
|
||||
String applicationArguments = "-s MrBob";
|
||||
try {
|
||||
setErrorsExpected(true);
|
||||
GnuDemanglerNativeProcess.getDemanglerNativeProcess(demanglerName,
|
||||
applicationArguments);
|
||||
fail("Expected an exception when passing unknown arguments to the native demangler");
|
||||
|
@ -246,7 +247,7 @@ public class GnuDemanglerTest extends AbstractGenericTest {
|
|||
// expected
|
||||
Msg.error(this, "Test error", e);
|
||||
}
|
||||
|
||||
setErrorsExpected(false);
|
||||
}
|
||||
|
||||
private Address addr(String address) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
private boolean isNamespaceDeleted(Namespace namespace2) {
|
||||
Symbol nsSymbol = namespace2.getSymbol();
|
||||
private boolean isNamespaceDeleted(Namespace other) {
|
||||
Symbol nsSymbol = other.getSymbol();
|
||||
if (nsSymbol == null) {
|
||||
return false; // global namespace.
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ public class MDMangGhidra extends MDMang {
|
|||
if (objectResult != null) {
|
||||
objectResult.setMangledString(mangledArg);
|
||||
// Make our version of the demangled string available (could be large).
|
||||
objectResult.setUtilDemangled(item.toString());
|
||||
objectResult.setOriginalDemangled(item.toString());
|
||||
}
|
||||
return returnedItem;
|
||||
}
|
||||
|
|
|
@ -218,25 +218,9 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||
}
|
||||
|
||||
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
|
||||
Window window = getWindowByTitleContaining(parentWindow, text);
|
||||
Window window = getWindowByTitleContaining(null, text);
|
||||
if (window != null) {
|
||||
return window;// we found it...no waiting required
|
||||
}
|
||||
|
@ -245,7 +229,7 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||
int timeout = DEFAULT_WAIT_TIMEOUT;
|
||||
while (totalTime <= timeout) {
|
||||
|
||||
window = getWindowByTitleContaining(parentWindow, text);
|
||||
window = getWindowByTitleContaining(null, text);
|
||||
if (window != null) {
|
||||
return window;
|
||||
}
|
||||
|
@ -257,43 +241,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||
"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.
|
||||
*
|
||||
|
@ -1828,25 +1775,6 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||
useErrorGUI = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the client expected the System Under Test (SUT) to report errors. Use this
|
||||
* when you wish to verify that errors are reported and you do not want those errors to
|
||||
* fail the test. The default value for this setting is false, which means that any
|
||||
* errors reported will fail the running test.
|
||||
*
|
||||
* @param expected true if errors are expected.
|
||||
*/
|
||||
public static void setErrorsExpected(boolean expected) {
|
||||
if (expected) {
|
||||
Msg.error(AbstractDockingTest.class, ">>>>>>>>>>>>>>>> Expected Exception");
|
||||
ConcurrentTestExceptionHandler.disable();
|
||||
}
|
||||
else {
|
||||
Msg.error(AbstractDockingTest.class, "<<<<<<<<<<<<<<<< End Expected Exception");
|
||||
ConcurrentTestExceptionHandler.enable();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off the gui displays for errors. This does not change the "isUseErrorGUI()" value for
|
||||
* other tests in the TestCase.
|
||||
|
|
|
@ -248,8 +248,9 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
|||
*/
|
||||
public static Set<Window> getAllWindows() {
|
||||
Set<Window> set = new HashSet<>();
|
||||
Frame sharedOwnerFrame = (Frame) AppContext.getAppContext().get(
|
||||
new StringBuffer("SwingUtilities.sharedOwnerFrame"));
|
||||
Frame sharedOwnerFrame = (Frame) AppContext.getAppContext()
|
||||
.get(
|
||||
new StringBuffer("SwingUtilities.sharedOwnerFrame"));
|
||||
if (sharedOwnerFrame != null) {
|
||||
set.addAll(getAllWindows(sharedOwnerFrame));
|
||||
}
|
||||
|
@ -1515,6 +1516,29 @@ public abstract class AbstractGenericTest extends AbstractGTest {
|
|||
UIManager.put("TextArea.font", f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the client expected the System Under Test (SUT) to report errors. Use this
|
||||
* when you wish to verify that errors are reported and you do not want those errors to
|
||||
* fail the test. The default value for this setting is false, which means that any
|
||||
* errors reported will fail the running test.
|
||||
*
|
||||
* @param expected true if errors are expected.
|
||||
*/
|
||||
public static void setErrorsExpected(boolean expected) {
|
||||
if (expected) {
|
||||
Msg.error(AbstractGenericTest.class, ">>>>>>>>>>>>>>>> Expected Exception");
|
||||
ConcurrentTestExceptionHandler.disable();
|
||||
}
|
||||
else {
|
||||
Msg.error(AbstractGenericTest.class, "<<<<<<<<<<<<<<<< End Expected Exception");
|
||||
ConcurrentTestExceptionHandler.enable();
|
||||
}
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
// Swing Methods
|
||||
//==================================================================================================
|
||||
|
||||
/**
|
||||
* Waits for the Swing thread to process any pending events. This method
|
||||
* also waits for any {@link SwingUpdateManager}s that have pending events
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package help.screenshot;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionListener;
|
||||
|
@ -148,7 +148,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator {
|
|||
makeSelection(0x0406be1, 0x0406bf1);
|
||||
|
||||
performAction("Create Table From Selection", "CodeBrowserPlugin", true);
|
||||
Window window = waitForWindowByTitleContaining(null, "Selection Table", 2000);
|
||||
Window window = waitForWindowByTitleContaining("Selection Table");
|
||||
Point loc = plugin.getListingPanel().getLocationOnScreen();
|
||||
Dimension size = window.getSize();
|
||||
window.setBounds(loc.x + 300, loc.y + 150, size.width, 300);
|
||||
|
|
|
@ -142,7 +142,7 @@ public class NavigationScreenShots extends GhidraScreenShotGenerator {
|
|||
setGotoText(dialog, "LAB*");
|
||||
pressOkOnDialog();
|
||||
Window window =
|
||||
waitForWindowByTitleContaining(null, "Search Limit Exceeded!", DEFAULT_WINDOW_TIMEOUT);
|
||||
waitForWindowByTitleContaining("Search Limit Exceeded!");
|
||||
assertNotNull(window);
|
||||
pressButtonByText(window, "OK");
|
||||
waitForSwing();
|
||||
|
|
|
@ -51,7 +51,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
program.endTransaction(txID, false);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
||||
* functions that live inside of a class that lives inside of a namespace.
|
||||
* This test applies a demangled name where the mangled name does NOT exist.
|
||||
|
@ -83,7 +83,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
assertEquals("ATL", ns.getName(false));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly update a thunk function
|
||||
* with its namespace, and ripple through to the underlying default thunked
|
||||
* function. The thunk 'this' parameter should utilize the Class
|
||||
|
@ -132,7 +132,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
||||
* functions that live inside of a class that lives inside of a namespace.
|
||||
* This test applies a demangled name where the mangled name exists.
|
||||
|
@ -168,7 +168,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
assertEquals("ATL", ns.getName(false));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
||||
* functions that live inside of a class that lives inside of a namespace.
|
||||
* This test applies a demangled name where the mangled name exists with address suffix.
|
||||
|
@ -205,7 +205,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
assertEquals("ATL", ns.getName(false));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
||||
* functions that live inside of a class that lives inside of a namespace.
|
||||
* This test applies a demangled name where both the mangled name exists and
|
||||
|
@ -243,7 +243,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
assertEquals("ATL", ns.getName(false));
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* Test that the DemangledFunction will properly create a cascade of namespaces for
|
||||
* functions that live inside of a class that lives inside of a namespace.
|
||||
* This test applies a demangled name where the mangled name exists on an external
|
||||
|
@ -339,7 +339,7 @@ public class DemangledFunctionTest extends AbstractGhidraHeadlessIntegrationTest
|
|||
private void assertSimpleNamespaceExists(String name) {
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
Namespace ns = symbolTable.getNamespace(name, program.getGlobalNamespace());
|
||||
assertNotNull(ns);
|
||||
assertNotNull("Namespace not created: " + name, ns);
|
||||
assertEquals(SymbolType.NAMESPACE, ns.getSymbol().getSymbolType());
|
||||
}
|
||||
|
||||
|
|
|
@ -57,10 +57,11 @@ public class GnuDemanglerIntegrationTest extends AbstractGhidraHeadlessIntegrati
|
|||
String mangled = "MyFunction__11MyNamespacePQ215$ParamNamespace9paramName";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
demangler.canDemangle(program);// this performs initialization
|
||||
|
||||
GnuDemanglerOptions options = new GnuDemanglerOptions();
|
||||
options.setDemangleOnlyKnownPatterns(false);
|
||||
options = options.withDeprecatedDemangler();
|
||||
DemangledObject result = demangler.demangle(mangled, options);
|
||||
assertNotNull(result);
|
||||
assertEquals("undefined MyNamespace::MyFunction($ParamNamespace::paramName *)",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue