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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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