GT-3545 - GNU Demangler - Fix Parsing Issues - Ready for Review

This commit is contained in:
dragonmacher 2020-03-02 14:22:23 -05:00
parent ed80be21c3
commit 11619169b4
33 changed files with 1359 additions and 3934 deletions

View file

@ -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();
} }

View file

@ -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);

View file

@ -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();
} }
} }

View file

@ -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);

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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);
} }

View file

@ -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;
}
}

View file

@ -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();
} }

View file

@ -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;
}
} }

View file

@ -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 != ' ')) {

View file

@ -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(',');
} }

View file

@ -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();
} }
} }

View file

@ -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.

View file

@ -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()) {

View file

@ -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

View file

@ -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();
}

View file

@ -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");

View file

@ -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);
} }
} }

View file

@ -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;
} }

View file

@ -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) {

View file

@ -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

View file

@ -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.
} }

View file

@ -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;
} }

View file

@ -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.

View file

@ -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

View file

@ -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);
@ -240,7 +240,7 @@ public class CodeBrowserPluginScreenShots extends GhidraScreenShotGenerator {
JWindow popup = (JWindow) waitForWindowByName("ListingHoverProvider"); JWindow popup = (JWindow) waitForWindowByName("ListingHoverProvider");
paintFix(popup); paintFix(popup);
captureProvider(CodeViewerProvider.class); captureProvider(CodeViewerProvider.class);
CodeViewerProvider provider = getProvider(CodeViewerProvider.class); CodeViewerProvider provider = getProvider(CodeViewerProvider.class);
captureProviderWithScreenShot(provider); captureProviderWithScreenShot(provider);
} }

View file

@ -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();

View file

@ -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());
} }

View file

@ -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 *)",