GP-4340 Improved datatype conflict name handling

This commit is contained in:
ghidra1 2024-02-23 16:24:22 -05:00
parent 7f58541ba0
commit 5dc7347eee
22 changed files with 493 additions and 371 deletions

View file

@ -29,6 +29,7 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.stream.JsonWriter;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.database.data.ProgramDataTypeManager;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFormatException;
@ -96,7 +97,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
* @param baseWriter the writer to use when writing data types
* @throws IOException if there is an exception writing the output
*/
public IsfDataTypeWriter(DataTypeManager dtm, List<DataType> target, Writer baseWriter) throws IOException {
public IsfDataTypeWriter(DataTypeManager dtm, List<DataType> target, Writer baseWriter)
throws IOException {
super(baseWriter);
this.baseWriter = baseWriter;
this.dtm = dtm;
@ -117,6 +119,7 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
STRICT = true;
}
@Override
public JsonObject getRootObject(TaskMonitor monitor) throws CancelledException, IOException {
genRoot(monitor);
return data;
@ -160,7 +163,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
oskey = metaData.get("Compiler ID");
if (metaData.containsKey("PDB Loaded")) {
os = gson.toJsonTree(new IsfWinOS(metaData));
} else if (metaData.containsKey("Executable Format")) {
}
else if (metaData.containsKey("Executable Format")) {
if (metaData.get("Executable Format").contains("ELF")) {
oskey = "linux";
os = gson.toJsonTree(new IsfLinuxOS(gson, metaData));
@ -201,15 +205,18 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
Symbol symbol = iterator.next();
symbolToJson(imageBase, symbolTable, linkages, map, symbol);
}
} else {
}
else {
for (Address addr : requestedAddresses) {
Symbol[] symsFromAddr = symbolTable.getSymbols(addr.add(imageBase.getOffset()));
Symbol[] symsFromAddr =
symbolTable.getSymbols(addr.add(imageBase.getOffset()));
for (Symbol symbol : symsFromAddr) {
symbolToJson(imageBase, symbolTable, linkages, map, symbol);
}
}
}
} else {
}
else {
for (String key : requestedSymbols) {
SymbolIterator iter = symbolTable.getSymbols(key);
while (iter.hasNext()) {
@ -263,7 +270,7 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
monitor.setMaximum(keylist.size());
for (String key : keylist) {
DataType dataType = map.get(key);
if (key.contains(".conflict")) {
if (DataTypeUtilities.isConflictDataType(dataType)) {
continue;
}
obj = getObjectForDataType(dataType, monitor);
@ -273,28 +280,34 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
if (dataType instanceof FunctionDefinition) {
// Would be nice to support this in the future, but Volatility does not
add(functions, dataType.getPathName(), obj);
} else if (IsfUtilities.isBaseDataType(dataType)) {
}
else if (IsfUtilities.isBaseDataType(dataType)) {
add(baseTypes, dataType.getPathName(), obj);
} else if (dataType instanceof TypeDef) {
}
else if (dataType instanceof TypeDef) {
DataType baseDataType = ((TypeDef) dataType).getBaseDataType();
if (IsfUtilities.isBaseDataType(baseDataType)) {
add(baseTypes, dataType.getPathName(), obj);
} else if (baseDataType instanceof Enum) {
}
else if (baseDataType instanceof Enum) {
add(enums, dataType.getPathName(), obj);
} else {
}
else {
add(userTypes, dataType.getPathName(), obj);
}
} else if (dataType instanceof Enum) {
}
else if (dataType instanceof Enum) {
add(enums, dataType.getPathName(), obj);
} else if (dataType instanceof Composite) {
}
else if (dataType instanceof Composite) {
add(userTypes, dataType.getPathName(), obj);
}
monitor.increment();
}
}
private void symbolToJson(Address imageBase, SymbolTable symbolTable, Map<String, Symbol> linkages,
Map<String, JsonObject> map, Symbol symbol) {
private void symbolToJson(Address imageBase, SymbolTable symbolTable,
Map<String, Symbol> linkages, Map<String, JsonObject> map, Symbol symbol) {
String key = symbol.getName();
Address address = symbol.getAddress();
JsonObject sym = map.containsKey(key) ? map.get(key) : new JsonObject();
@ -305,10 +318,12 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
sym.addProperty("linkage_name", linkage.getName());
sym.addProperty("address", linkage.getAddress().getOffset());
}
} else {
}
else {
if (address.getAddressSpace().equals(imageBase.getAddressSpace())) {
sym.addProperty("address", address.subtract(imageBase));
} else {
}
else {
sym.addProperty("address", address.getOffset());
}
}
@ -323,6 +338,7 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
}
}
@Override
public void write(JsonObject obj) {
gson.toJson(obj, writer);
}
@ -332,7 +348,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
add(baseTypes, "undefined", getTree(newTypedefPointer(null)));
}
protected JsonObject getObjectForDataType(DataType dt, TaskMonitor monitor) throws IOException, CancelledException {
protected JsonObject getObjectForDataType(DataType dt, TaskMonitor monitor)
throws IOException, CancelledException {
IsfObject isf = getIsfObject(dt, monitor);
if (isf != null) {
JsonObject jobj = (JsonObject) getTree(isf);
@ -351,7 +368,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
* @param monitor the task monitor
* @throws IOException if there is an exception writing the output
*/
protected IsfObject getIsfObject(DataType dt, TaskMonitor monitor) throws IOException, CancelledException {
protected IsfObject getIsfObject(DataType dt, TaskMonitor monitor)
throws IOException, CancelledException {
if (dt == null) {
throw new IOException("Null datatype passed to getIsfObject");
}
@ -377,21 +395,29 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
if (dt instanceof Dynamic dynamic) {
DataType rep = dynamic.getReplacementBaseType();
return rep == null ? null : getIsfObject(rep, monitor);
} else if (dt instanceof TypeDef typedef) {
}
else if (dt instanceof TypeDef typedef) {
return getObjectTypeDef(typedef, monitor);
} else if (dt instanceof Composite composite) {
}
else if (dt instanceof Composite composite) {
return new IsfComposite(composite, this, monitor);
} else if (dt instanceof Enum enumm) {
}
else if (dt instanceof Enum enumm) {
return new IsfEnum(enumm);
} else if (dt instanceof BuiltInDataType builtin) {
}
else if (dt instanceof BuiltInDataType builtin) {
return new IsfBuiltIn(builtin);
} else if (dt instanceof BitFieldDataType) {
}
else if (dt instanceof BitFieldDataType) {
// skip - not hit
} else if (dt instanceof FunctionDefinition) { /// FAIL
}
else if (dt instanceof FunctionDefinition) { /// FAIL
// skip - not hit
} else if (dt.equals(DataType.DEFAULT)) {
}
else if (dt.equals(DataType.DEFAULT)) {
// skip - not hit
} else {
}
else {
Msg.warn(this, "Unable to write datatype. Type unrecognized: " + dt.getClass());
}
@ -417,8 +443,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
}
}
}
Msg.warn(this,
"WARNING! conflicting data type names: " + dt.getPathName() + " - " + resolvedType.getPathName());
Msg.warn(this, "WARNING! conflicting data type names: " + dt.getPathName() + " - " +
resolvedType.getPathName());
return resolved.get(dt);
}
@ -465,8 +491,9 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
return newIsfDynamicComponent(dynamic, type, elementCnt);
}
Msg.error(this, dynamic.getClass().getSimpleName() + " returned bad replacementBaseType: "
+ replacementBaseType.getClass().getSimpleName());
Msg.error(this,
dynamic.getClass().getSimpleName() + " returned bad replacementBaseType: " +
replacementBaseType.getClass().getSimpleName());
}
}
return null;
@ -500,7 +527,7 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
IsfObject baseObject = getObjectDataType(IsfUtilities.getBaseDataType(dataType));
return new IsfDataTypeTypeDef(dataType, baseObject);
}
if (dataType.getPathName().contains(".conflict")) {
if (DataTypeUtilities.isConflictDataType(dataType)) {
if (!deferredKeys.contains(dataType.getPathName())) {
deferredKeys.add(dataType.getPathName());
}
@ -513,7 +540,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
*
* @throws CancelledException if the action is cancelled by the user
*/
protected IsfObject getObjectTypeDef(TypeDef typeDef, TaskMonitor monitor) throws CancelledException {
protected IsfObject getObjectTypeDef(TypeDef typeDef, TaskMonitor monitor)
throws CancelledException {
DataType dataType = typeDef.getDataType();
String typedefName = typeDef.getPathName();
@ -527,7 +555,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
return newTypedefUser(typeDef, isfObject);
}
return newTypedefPointer(typeDef);
} catch (Exception e) {
}
catch (Exception e) {
Msg.error(this, "TypeDef error: " + e);
}
clearResolve(typedefName, baseType);
@ -544,7 +573,8 @@ public class IsfDataTypeWriter extends AbstractIsfWriter {
return;
}
requestedAddresses.add(address);
} catch (AddressFormatException e) {
}
catch (AddressFormatException e) {
throw new IOException("Bad address format: " + key);
}
}

View file

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Search for the root cause of a datatype conflict based upon a selected datatype.
//@category Data Types
import java.util.*;
@ -55,8 +56,8 @@ public class FindDataTypeConflictCauseScript extends GhidraScript {
}
DataType selectedDt = DataTypeUtilities.getBaseDataType(selectedDatatypes.get(0));
if (selectedDt instanceof Pointer || selectedDt instanceof Array) {
popup("Selected datatype must not be a Pointer or Array");
if (selectedDt == null) {
popup("Selected datatype must not be a default Pointer");
return;
}

View file

@ -190,11 +190,13 @@ public class DataTypeSyncInfo {
if (sourceDt == null) {
return true;
}
if (!DataTypeSynchronizer.namesAreEquivalent(sourceDt, refDt)) {
return true;
}
if (!StringUtils.equals(refDt.getDescription(), sourceDt.getDescription())) {
return true;
if (!DataTypeSynchronizer.isPointerOrArray(refDt)) {
if (!DataTypeSynchronizer.namesAreEquivalent(sourceDt, refDt)) {
return true;
}
if (!StringUtils.equals(refDt.getDescription(), sourceDt.getDescription())) {
return true;
}
}
DataType dt = sourceDt.clone(refDt.getDataTypeManager());
return !dt.isEquivalent(refDt);

View file

@ -28,8 +28,7 @@ import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
import ghidra.app.util.ToolTipUtils;
import ghidra.app.util.html.HTMLDataTypeRepresentation;
import ghidra.app.util.html.MissingArchiveDataTypeHTMLRepresentation;
import ghidra.program.database.data.DataTypeManagerDB;
import ghidra.program.database.data.ProgramDataTypeManager;
import ghidra.program.database.data.*;
import ghidra.program.model.data.*;
import ghidra.util.*;
import ghidra.util.exception.AssertException;
@ -127,11 +126,13 @@ public class DataTypeSynchronizer {
// not handled by resolve.
long lastChangeTime = refDT.getLastChangeTime();
DataType sourceDT = sourceDTM.resolve(refDT, DataTypeConflictHandler.REPLACE_HANDLER);
if (!namesAreEquivalent(refDT, sourceDT)) {
renameDataType(sourceDTM, sourceDT, refDT);
}
if (!StringUtils.equals(refDT.getDescription(), sourceDT.getDescription())) {
sourceDT.setDescription(refDT.getDescription());
if (!isPointerOrArray(refDT)) {
if (!namesAreEquivalent(refDT, sourceDT)) {
renameDataType(sourceDTM, sourceDT, refDT);
}
if (!StringUtils.equals(refDT.getDescription(), sourceDT.getDescription())) {
sourceDT.setDescription(refDT.getDescription());
}
}
sourceDT.setLastChangeTime(lastChangeTime);
refDT.setLastChangeTimeInSourceArchive(lastChangeTime);
@ -140,11 +141,13 @@ public class DataTypeSynchronizer {
public static void updateAssumingTransactionsOpen(DataTypeManager refDTM, DataType sourceDT) {
long lastChangeTime = sourceDT.getLastChangeTime();
DataType refDT = refDTM.resolve(sourceDT, DataTypeConflictHandler.REPLACE_HANDLER);
if (!namesAreEquivalent(refDT, sourceDT)) {
renameDataType(refDTM, refDT, sourceDT);
}
if (!StringUtils.equals(sourceDT.getDescription(), refDT.getDescription())) {
refDT.setDescription(sourceDT.getDescription());
if (!isPointerOrArray(sourceDT)) {
if (!namesAreEquivalent(refDT, sourceDT)) {
renameDataType(refDTM, refDT, sourceDT);
}
if (!StringUtils.equals(sourceDT.getDescription(), refDT.getDescription())) {
refDT.setDescription(sourceDT.getDescription());
}
}
refDT.setLastChangeTimeInSourceArchive(lastChangeTime);
refDT.setLastChangeTime(lastChangeTime);
@ -252,14 +255,10 @@ public class DataTypeSynchronizer {
}
}
String name = dtToCopy.getName();
int index = name.indexOf(DataType.CONFLICT_SUFFIX);
if (index > 0) {
name = name.substring(0, index);
}
CategoryPath path = sourceDT.getCategoryPath();
if (sourceDTM.getDataType(path, name) != null) {
name = ((DataTypeManagerDB) sourceDTM).getUnusedConflictName(sourceDT.getCategoryPath(),
name);
dtToCopy);
}
try {
sourceDT.setName(name);
@ -282,27 +281,19 @@ public class DataTypeSynchronizer {
return false;
}
public static boolean namesAreEquivalent(DataType dt1, DataType dt2) {
static boolean isPointerOrArray(DataType dt) {
return (dt instanceof Pointer) || (dt instanceof Array);
}
static boolean namesAreEquivalent(DataType dt1, DataType dt2) {
if (isAutoNamedTypedef(dt1)) {
return isAutoNamedTypedef(dt2);
}
else if (isAutoNamedTypedef(dt2)) {
return false;
}
String name1 = dt1.getName();
String name2 = dt2.getName();
if (name1.equals(name2)) {
return true;
}
int index = name1.indexOf(DataType.CONFLICT_SUFFIX);
if (index > 0) {
name1 = name1.substring(0, index);
}
index = name2.indexOf(DataType.CONFLICT_SUFFIX);
if (index > 0) {
name2 = name2.substring(0, index);
}
return name1.equals(name2);
return DataTypeUtilities.getNameWithoutConflict(dt1)
.equals(DataTypeUtilities.getNameWithoutConflict(dt2));
}

View file

@ -15,6 +15,7 @@
*/
package ghidra.app.util;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionSignature;
@ -53,9 +54,9 @@ public class DataTypeNamingUtil {
}
sb.append("_");
sb.append(mangleDTName(returnType.getName()));
sb.append(mangleDTName(returnType));
for (ParameterDefinition p : parameters) {
sb.append("_").append(mangleDTName(p.getDataType().getName()));
sb.append("_").append(mangleDTName(p.getDataType()));
}
if (functionDefinition.hasVarArgs()) {
@ -72,8 +73,9 @@ public class DataTypeNamingUtil {
return name;
}
private static String mangleDTName(String s) {
return s.replaceAll(" ", "_").replaceAll("\\*", "ptr");
private static String mangleDTName(DataType dt) {
String name = DataTypeUtilities.getNameWithoutConflict(dt);
return name.replaceAll(" ", "_").replaceAll("\\*", "ptr");
}
}

View file

@ -25,14 +25,14 @@ class LibraryExportedSymbol {
private int memsize;
private int ordinal = -1;
private String symbolName;
private String fowardLibraryName;
private String fowardSymbolName;
private String forwardLibraryName;
private String forwardSymbolName;
private int purge;
private boolean noReturn;
private String comment;
LibraryExportedSymbol(String libName, int memsize, int ordinal, String symbolName,
String fowardLibraryName, String fowardSymbolName, int purge, boolean noReturn,
String forwardLibraryName, String forwardSymbolName, int purge, boolean noReturn,
String comment) {
this.libName = libName;
this.memsize = memsize;
@ -41,8 +41,8 @@ class LibraryExportedSymbol {
this.purge = purge;
this.noReturn = noReturn;
this.comment = comment;
this.fowardLibraryName = fowardLibraryName;
this.fowardSymbolName = fowardSymbolName;
this.forwardLibraryName = forwardLibraryName;
this.forwardSymbolName = forwardSymbolName;
}
/**
@ -125,12 +125,12 @@ class LibraryExportedSymbol {
private synchronized void processForwardedEntry() {
purge = -2;
LibrarySymbolTable lib = LibraryLookupTable.getSymbolTable(fowardLibraryName, memsize);
LibrarySymbolTable lib = LibraryLookupTable.getSymbolTable(forwardLibraryName, memsize);
if (lib == null) {
return;
}
LibraryExportedSymbol libSym = lib.getSymbol(fowardSymbolName);
LibraryExportedSymbol libSym = lib.getSymbol(forwardSymbolName);
if (libSym == null) {
return;
}
@ -151,24 +151,24 @@ class LibraryExportedSymbol {
}
/**
* @return true if this symbol is fowarded to another library
* @return true if this symbol is forwarded to another library
*/
boolean isFowardEntry() {
return fowardLibraryName != null;
return forwardLibraryName != null;
}
/**
* @return the fowarded library name
* @return the forwarded library name
*/
String getFowardLibraryName() {
return fowardLibraryName;
return forwardLibraryName;
}
/**
* @return the fowarded symbol name
* @return the forwarded symbol name
*/
String getFowardSymbolName() {
return fowardSymbolName;
return forwardSymbolName;
}
void setName(String name) {

View file

@ -56,8 +56,8 @@ class LibrarySymbolTable {
private String date;
private String version;
private int tempPurge;
private String fowardLibrary = null;
private String fowardSymbol = null;
private String forwardLibrary = null;
private String forwardSymbol = null;
private HashMap<String, LibraryExportedSymbol> symMap = new HashMap<>();
private ArrayList<LibraryExportedSymbol> exportList = new ArrayList<>();
private HashMap<Integer, LibraryExportedSymbol> ordMap = new HashMap<>();
@ -140,8 +140,8 @@ class LibrarySymbolTable {
}
}
fowardLibrary = null;
fowardSymbol = null;
forwardLibrary = null;
forwardSymbol = null;
tempPurge = -1;
String comment = "";
@ -160,12 +160,12 @@ class LibrarySymbolTable {
Reference[] refs = library.getReferenceManager().getReferencesFrom(symAddr);
if (refs != null && refs.length > 0 && refs[0].isExternalReference()) {
ExternalReference exRef = (ExternalReference) refs[0];
fowardLibrary = exRef.getLibraryName();
fowardSymbol = exRef.getLabel();
forwardLibrary = exRef.getLibraryName();
forwardSymbol = exRef.getLabel();
}
}
if (fowardLibrary == null || fowardLibrary.length() <= 0) {
if (forwardLibrary == null || forwardLibrary.length() <= 0) {
MemoryBlock block = library.getMemory().getBlock(symAddr);
if (block != null && block.isExecute()) {
pseudoDisassemble(library, symAddr);
@ -179,12 +179,12 @@ class LibrarySymbolTable {
noReturn = true;
}
if (fowardLibrary != null && fowardLibrary.length() > 0) {
forwards.add(fowardLibrary);
if (forwardLibrary != null && forwardLibrary.length() > 0) {
forwards.add(forwardLibrary);
}
LibraryExportedSymbol expSym = new LibraryExportedSymbol(tableName, size, ordinal,
realName, fowardLibrary, fowardSymbol, tempPurge, noReturn, comment);
realName, forwardLibrary, forwardSymbol, tempPurge, noReturn, comment);
// add to export list in order
exportList.add(expSym);
@ -225,8 +225,8 @@ class LibrarySymbolTable {
Scalar scalar = instr.getScalar(0);
if (scalar != null) {
tempPurge = (int) scalar.getSignedValue();
fowardLibrary = null;
fowardSymbol = null;
forwardLibrary = null;
forwardSymbol = null;
return false;
}
}
@ -234,15 +234,17 @@ class LibrarySymbolTable {
if (ftype.isJump() && ftype.isComputed()) {
Reference[] refs = instr.getReferencesFrom();
if (refs.length > 0) {
Data data = instr.getProgram().getListing().getDefinedDataAt(
refs[0].getToAddress());
Data data = instr.getProgram()
.getListing()
.getDefinedDataAt(refs[0].getToAddress());
if (data != null) {
refs = instr.getProgram().getReferenceManager().getReferencesFrom(
data.getMinAddress());
refs = instr.getProgram()
.getReferenceManager()
.getReferencesFrom(data.getMinAddress());
if (refs != null && refs.length > 0 && refs[0].isExternalReference()) {
ExternalReference exRef = (ExternalReference) refs[0];
fowardLibrary = exRef.getLibraryName();
fowardSymbol = exRef.getLabel();
forwardLibrary = exRef.getLibraryName();
forwardSymbol = exRef.getLabel();
}
}
}
@ -425,26 +427,24 @@ class LibrarySymbolTable {
version = root.getAttributeValue("VERSION");
List<Element> children = CollectionUtils.asList(root.getChildren(), Element.class);
Iterator<Element> iter = children.iterator();
while (iter.hasNext()) {
Element export = iter.next();
for (Element export : children) {
int ordinal = Integer.parseInt(export.getAttributeValue("ORDINAL"));
String name = export.getAttributeValue("NAME");
int purge = Integer.parseInt(export.getAttributeValue("PURGE"));
String comment = export.getAttributeValue("COMMENT");
String fowardLibName = export.getAttributeValue("FOWARDLIBRARY");
String fowardSymName = export.getAttributeValue("FOWARDSYMBOL");
String forwardLibName = export.getAttributeValue("FOWARDLIBRARY");
String forwardSymName = export.getAttributeValue("FOWARDSYMBOL");
String noReturnStr = export.getAttributeValue("NO_RETURN");
boolean noReturn = noReturnStr != null && "y".equals(noReturnStr);
if (fowardLibName != null && fowardLibName.length() > 0 &&
!fowardLibName.equals(tableName)) {
forwards.add(fowardLibName);
if (forwardLibName != null && forwardLibName.length() > 0 &&
!forwardLibName.equals(tableName)) {
forwards.add(forwardLibName);
}
LibraryExportedSymbol sym = new LibraryExportedSymbol(tableName, size, ordinal,
name, fowardLibName, fowardSymName, purge, noReturn, comment);
name, forwardLibName, forwardSymName, purge, noReturn, comment);
exportList.add(sym);
symMap.put(name, sym);
@ -494,10 +494,7 @@ class LibrarySymbolTable {
root.setAttribute("DATE", TIMESTAMP_FORMAT.format(new Date(lastModifiedSeconds)));
root.setAttribute("VERSION", lversion);
Iterator<LibraryExportedSymbol> iter = exportList.iterator();
while (iter.hasNext()) {
LibraryExportedSymbol sym = iter.next();
for (LibraryExportedSymbol sym : exportList) {
Element export = new Element("EXPORT");
export.setAttribute("ORDINAL", sym.getOrdinal() + "");

View file

@ -218,18 +218,6 @@ class CategoryDB extends DatabaseObject implements Category {
return map;
}
private String getBaseName(String dataTypeName) {
int indexOf = dataTypeName.indexOf(DataType.CONFLICT_SUFFIX);
if (indexOf <= 0) {
return dataTypeName;
}
return dataTypeName.substring(0, indexOf);
}
private boolean isConflictName(String dataTypeName) {
return dataTypeName.contains(DataType.CONFLICT_SUFFIX);
}
/**
* @see ghidra.program.model.data.Category#getCategories()
*/
@ -549,7 +537,7 @@ class CategoryDB extends DatabaseObject implements Category {
}
else { // both dataTypes remain
movedDataType.setNameAndCategory(path,
mgr.getUnusedConflictName(path, movedDataType.getName()));
mgr.getUnusedConflictName(path, movedDataType));
}
}
else {
@ -621,14 +609,14 @@ class CategoryDB extends DatabaseObject implements Category {
void dataTypeAdded(DataType dataType) {
String dtName = dataType.getName();
dataTypeMap.put(dtName, dataType);
if (isConflictName(dtName)) {
if (DataTypeUtilities.isConflictDataType(dataType)) {
conflictMap.addDataType(dataType);
}
}
void dataTypeRemoved(String dataTypeName) {
dataTypeMap.remove(dataTypeName);
if (isConflictName(dataTypeName)) {
if (DataTypeUtilities.isConflictDataTypeName(dataTypeName)) {
conflictMap.removeDataTypeName(dataTypeName);
}
}
@ -639,8 +627,9 @@ class CategoryDB extends DatabaseObject implements Category {
@Override
public List<DataType> getDataTypesByBaseName(String dataTypeName) {
List<DataType> list = new ArrayList<>();
String baseName = getBaseName(dataTypeName);
String baseName = DataTypeUtilities.getNameWithoutConflict(dataTypeName);
DataType baseType = dataTypeMap.get(baseName);
if (baseType != null) {
@ -681,8 +670,8 @@ class CategoryDB extends DatabaseObject implements Category {
Collection<DataType> values = dataTypeMap.values();
for (DataType dataType : values) {
String dataTypeName = dataType.getName();
if (isConflictName(dataTypeName)) {
String baseName = getBaseName(dataTypeName);
if (DataTypeUtilities.isConflictDataType(dataType)) {
String baseName = DataTypeUtilities.getNameWithoutConflict(dataType);
Map<String, DataType> innerMap =
map.computeIfAbsent(baseName, b -> new HashMap<>());
innerMap.put(dataTypeName, dataType);
@ -705,7 +694,7 @@ class CategoryDB extends DatabaseObject implements Category {
}
String dataTypeName = dataType.getName();
String baseName = getBaseName(dataTypeName);
String baseName = DataTypeUtilities.getNameWithoutConflict(dataType);
Map<String, DataType> innerMap = map.computeIfAbsent(baseName, b -> new HashMap<>());
innerMap.put(dataTypeName, dataType);
}
@ -721,7 +710,7 @@ class CategoryDB extends DatabaseObject implements Category {
if (map == null) {
return;
}
String baseName = getBaseName(dataTypeName);
String baseName = DataTypeUtilities.getNameWithoutConflict(dataTypeName);
Map<String, DataType> innerMap = map.get(baseName);
if (innerMap == null) {
return;

View file

@ -392,7 +392,7 @@ abstract class DataTypeDB extends DatabaseObject implements DataType {
// generate a name that would not cause a duplicate in either the current path
// or
// the new path. Use the new name if possible.
String uniqueName = dataMgr.getUniqueName(path, getCategoryPath(), name);
String uniqueName = dataMgr.getTemporaryUniqueName(path, getCategoryPath(), name);
doSetName(uniqueName);
// set the path - this is guaranteed to work since we make a name that won't

View file

@ -1091,11 +1091,6 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
}
}
ConflictResult resolveConflict(DataTypeConflictHandler handler, DataType addedDataType,
DataType existingDataType) {
return handler.resolveConflict(addedDataType, existingDataType);
}
@Override
public String getUniqueName(CategoryPath path, String baseName) {
int pos = baseName.lastIndexOf('_');
@ -1119,7 +1114,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
return name;
}
String getUniqueName(CategoryPath path1, CategoryPath path2, String baseName) {
String getTemporaryUniqueName(CategoryPath newCategoryPath, CategoryPath currentCategoryPath,
String baseName) {
int pos = baseName.lastIndexOf('_');
int oneUpNumber = 0;
String name = baseName;
@ -1134,7 +1130,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
// the number will get updated below
}
}
while (getDataType(path1, name) != null || getDataType(path2, name) != null) {
while (getDataType(newCategoryPath, name) != null ||
getDataType(currentCategoryPath, name) != null) {
++oneUpNumber;
name = baseName + "_" + oneUpNumber;
}
@ -1428,47 +1425,47 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
/**
* This method gets a ".conflict" name that is not currently used by any data
* types in the indicated category of the data type manager.
* types in the datatype's category within this data type manager. If the baseName without
* conflict suffix is not used that name will be returned.
* <br>
* NOTE: The original datatype name will be returned unchanged for pointers and arrays since
* they cannot be renamed.
*
* @param dt datatype who name is used to establish non-conflict base name
* @return the unused conflict name or original name for datatypes whose name is automatic
*/
public String getUnusedConflictName(DataType dt) {
return getUnusedConflictName(dt.getCategoryPath(), dt);
}
/**
* This method gets a ".conflict" name that is not currently used by any data
* types in the indicated category within this data type manager. If the baseName without
* conflict suffix is not used that name will be returned.
* <br>
* NOTE: The original datatype name will be returned unchanged for pointers and arrays since
* they cannot be renamed.
*
* @param path the category path of the category where the new data type live in
* the data type manager.
* @param dt datatype who name is used to establish non-conflict base name
* @return the unused conflict name
*/
public String getUnusedConflictName(CategoryPath path, DataType dt) {
String name = dt.getName();
if ((dt instanceof Array) || (dt instanceof Pointer) || (dt instanceof BuiltInDataType)) {
// name not used - anything will do
return name;
}
return getUnusedConflictName(dt.getCategoryPath(), name);
}
/**
* This method gets a ".conflict" name that is not currently used by any data
* types in the indicated category of the data type manager.
*
* @param path the category path of the category where the new data type live in
* the data type manager.
* @param name The name of the data type. This name may or may not contain
* ".conflict" as part of it. If the name contains ".conflict", only
* the part of the name that comes prior to the ".conflict" will be
* used to determine a new unused conflict name.
* @return the unused conflict name
*/
public String getUnusedConflictName(CategoryPath path, String name) {
int index = name.indexOf(DataType.CONFLICT_SUFFIX);
if (index > 0) {
name = name.substring(0, index);
}
// Name sequence: <baseName>, <baseName>.conflict, <basename>.conflict1, ...
String baseName = name + DataType.CONFLICT_SUFFIX;
String testName = name;
String baseName = DataTypeUtilities.getNameWithoutConflict(dt);
String testName = baseName;
int count = 0;
while (getDataType(path, testName) != null) {
String countSuffix = "";
if (count != 0) {
countSuffix = Integer.toString(count);
testName = baseName + DataType.CONFLICT_SUFFIX;
if (count > 0) {
testName += Integer.toString(count);
}
testName = baseName + countSuffix;
++count;
}
return testName;
@ -4394,7 +4391,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
if (dataType instanceof Pointer || dataType instanceof Array) {
dataType = DataTypeUtilities.getBaseDataType(dataType);
}
if (!contains(dataType)) {
if (dataType == null || !contains(dataType)) {
return false;
}
List<DataType> relatedByName = findDataTypesSameLocation(dataType);
@ -4508,7 +4505,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
if (dt instanceof Pointer || dt instanceof Array) {
continue;
}
boolean isConflict = dt.getName().contains(DataType.CONFLICT_SUFFIX);
boolean isConflict = DataTypeUtilities.isConflictDataType(dt);
String name = DataTypeUtilities.getNameWithoutConflict(dt, false);
if (!name.equals(lastBaseName)) {
// base name changed

View file

@ -62,8 +62,19 @@ public class DataTypeUtilities {
cPrimitiveNameMap.put("long double", LongDoubleDataType.dataType);
}
private static final Pattern DATATYPE_CONFLICT_PATTERN =
Pattern.compile(Pattern.quote(DataType.CONFLICT_SUFFIX) + "_?[0-9]*");
// TODO: Should we drop the handling of "_" use in conflict name. It's unclear
// when/if this was ever used in the generation of a conflict name.
// NOTE: It is assumed that all BuiltInDataType types (other then possibly Pointers)
// will not utilize conflict names. This includes pointers and arrays whose base
// type is a BuiltInDataType.
// NOTE: The BASE_DATATYPE_CONFLICT_PATTERN may never be applied to a pointer
// or array name as it will always fail to match. Pointer and array decorations
// must be stripped off first.
private static final Pattern BASE_DATATYPE_CONFLICT_PATTERN =
Pattern.compile(Pattern.quote(DataType.CONFLICT_SUFFIX) + "([_]{0,1}\\d+){0,1}$");
private static final Pattern DATATYPE_POINTER_ARRAY_PATTERN =
Pattern.compile("(( \\*\\d*)|(\\[\\d+\\]))+$");
public static Collection<DataType> getContainedDataTypes(DataType rootDataType) {
HashMap<String, DataType> dataTypeMap = new HashMap<>();
@ -296,81 +307,12 @@ public class DataTypeUtilities {
return dataType1.getClass().equals(dataType2.getClass());
}
/**
* Get the name of a data type with all conflict naming patterns removed.
*
* @param dataType data type
* @param includeCategoryPath if true the category path will be included with the
* returned name (e.g., /mypath/mydt)
* @return name with optional category path included
*/
public static String getNameWithoutConflict(DataType dataType, boolean includeCategoryPath) {
String name = includeCategoryPath ? dataType.getPathName() : dataType.getName();
return getNameWithoutConflict(name);
}
/**
* Get the name of a data type with all conflict naming patterns removed.
*
* @param dataTypeName data type name with optional category path included
* @return name with optional category path included
*/
public static String getNameWithoutConflict(String dataTypeName) {
return DATATYPE_CONFLICT_PATTERN.matcher(dataTypeName).replaceAll("");
}
/**
* Get the conflict value string associated with a conflict datatype name.
*
* @param dataType datatype to be checked
* @return conflict value string. Will be null if name is not a conflict name, or
* empty string if conflict has no number. Otherwise a decimal value string will be returned.
*/
public static String getConflictString(DataType dataType) {
return getConflictString(dataType.getName());
}
/**
* Get the conflict value string associated with a conflict datatype name.
*
* @param dataTypeName datatype name to be checked
* @return conflict value string. Will be one of the following:
* <ol>
* <li>A null value if not a conflict name,</li>
* <li>an empty string if conflict name without a number, or</li>
* <li>a decimal string value which corresponds to the conflict number in the name.</li>
* </ol>
*/
public static String getConflictString(String dataTypeName) {
Matcher matcher = DATATYPE_CONFLICT_PATTERN.matcher(dataTypeName);
if (matcher.find()) {
MatchResult matchResult = matcher.toMatchResult();
return dataTypeName.substring(matchResult.start() + DataType.CONFLICT_SUFFIX.length(),
matchResult.end());
}
return null;
}
/**
* Compares two data type name strings to determine if they are equivalent names, ignoring
* conflict patterns present.
*
* @param name1 the first name
* @param name2 the second name
* @return true if the names are equivalent when conflict suffixes are ignored.
*/
public static boolean equalsIgnoreConflict(String name1, String name2) {
name1 = DATATYPE_CONFLICT_PATTERN.matcher(name1).replaceAll("");
name2 = DATATYPE_CONFLICT_PATTERN.matcher(name2).replaceAll("");
return name1.equals(name2);
}
/**
* Get the base data type for the specified data type stripping away pointers and arrays only. A
* null will be returned for a default pointer.
*
* @param dt the data type whose base data type is to be determined.
* @return the base data type.
* @return the base data type (may be null for default pointer).
*/
public static DataType getBaseDataType(DataType dt) {
DataType baseDataType = dt;
@ -840,4 +782,221 @@ public class DataTypeUtilities {
}
return null;
}
//
// Conflict naming utilities
//
private static boolean canHaveConflictName(DataType dt) {
if (dt == null) {
return false; // e.g., base type for default pointer
}
return !(dt instanceof BuiltIn) || (dt instanceof Pointer);
}
private static String getPointerArrayDecorations(String dataTypeName) {
// Use of this preliminary check greatly speeds-up the check for cases
// not involving a pointer or array
if (!dataTypeName.contains("*") && !dataTypeName.contains("[")) {
return null;
}
// Return the trailing pointer and array decorations if they exist
Matcher matcher = DATATYPE_POINTER_ARRAY_PATTERN.matcher(dataTypeName);
if (matcher.find()) {
MatchResult matchResult = matcher.toMatchResult();
return dataTypeName.substring(matchResult.start());
}
return null;
}
/**
* Get the name of a data type with all conflict naming patterns removed.
*
* @param dataType data type
* @param includeCategoryPath if true, the category path will be included with the
* returned name (e.g., /mypath/mydt) and any occurance of a forward slash within individual
* path components, including the data type name, will be escaped (e.g., {@code "\/"}).
* @return name with optional category path included
*/
public static String getNameWithoutConflict(DataType dataType, boolean includeCategoryPath) {
String name = getNameWithoutConflict(dataType);
if (includeCategoryPath) {
name = dataType.getCategoryPath().getPath(name);
}
return name;
}
/**
* Get the name of a data type with all conflict naming patterns removed.
*
* @param dataTypeName data type name with optional category path included
* @return name with optional category path included
*/
public static String getNameWithoutConflict(String dataTypeName) {
String decorations = getPointerArrayDecorations(dataTypeName);
String baseDataTypeName = dataTypeName;
if (decorations != null) {
baseDataTypeName =
dataTypeName.substring(0, dataTypeName.length() - decorations.length());
}
String name = BASE_DATATYPE_CONFLICT_PATTERN.matcher(baseDataTypeName).replaceAll("");
if (decorations != null) {
name += decorations;
}
return name;
}
/**
* Get a datatype's name without conflict suffix.
*
* @param dt datatype (pointer and array permitted)
* @return datatype's name without conflict suffix
*/
public static String getNameWithoutConflict(DataType dt) {
String dtName = dt.getName();
if (!canHaveConflictName(dt)) {
return dtName; // e.g., many BuiltIn types
}
DataType baseDataType = getBaseDataType(dt);
if (baseDataType == null) {
return dtName; // e.g., default pointer
}
if (baseDataType != dt && !canHaveConflictName(baseDataType)) {
return dtName; // e.g., pointer to BuiltIn
}
if (baseDataType == dt) {
// Non-pointer/array case
return BASE_DATATYPE_CONFLICT_PATTERN.matcher(dtName).replaceAll("");
}
// Isolate pointer/array decorations
// NOTE: This is faster than using regex to isolate pointer and array decorations
String baseDtName = baseDataType.getName();
String decorations = dtName.substring(baseDtName.length());
// remove conflict suffix
return BASE_DATATYPE_CONFLICT_PATTERN.matcher(baseDtName).replaceAll("") + decorations;
}
private static int getBaseConflictValue(String baseDataTypeName) {
Matcher matcher = BASE_DATATYPE_CONFLICT_PATTERN.matcher(baseDataTypeName);
if (matcher.find()) {
MatchResult matchResult = matcher.toMatchResult();
int startIx = matchResult.start() + DataType.CONFLICT_SUFFIX.length();
if (startIx < baseDataTypeName.length() && baseDataTypeName.charAt(startIx) == '_') {
++startIx;
}
String valueStr = baseDataTypeName.substring(startIx);
if (valueStr.length() == 0) {
return 0;
}
try {
return Integer.parseInt(valueStr);
}
catch (NumberFormatException e) {
return -1;
}
}
return -1;
}
/**
* Get the conflict value string associated with a conflict datatype name.
*
* @param dataType datatype to be checked
* @return conflict value:
* <ol>
* <li>-1: when type does not have a conflict name,</li>
* <li>0: when conflict name does not have a number (i.e., {@code .conflict}), or</li>
* <li>a positive value which corresponds to the conflict number in the name
* (e.g., returns 2 for {@code .conflict2}).</li>
* </ol>
*/
public static int getConflictValue(DataType dataType) {
if (!canHaveConflictName(dataType)) {
return -1; // e.g., many BuiltIn types
}
DataType baseDataType = getBaseDataType(dataType);
if (baseDataType == null) {
return -1; // e.g., default pointer
}
if (baseDataType != dataType && !canHaveConflictName(baseDataType)) {
return -1; // e.g., pointer to BuiltIn
}
return getBaseConflictValue(baseDataType.getName());
}
/**
* Get the conflict value associated with a conflict datatype name.
*
* @param dataTypeName datatype name to be checked
* @return conflict value:
* <ol>
* <li>-1: when name is not have a conflict name,</li>
* <li>0: when conflict name does not have a number (i.e., {@code .conflict}), or</li>
* <li>a positive value which corresponds to the conflict number in the name
* (e.g., returns 2 for {@code .conflict2}).</li>
* </ol>
*/
public static int getConflictValue(String dataTypeName) {
String decorations = getPointerArrayDecorations(dataTypeName);
String baseDataTypeName = dataTypeName;
if (decorations != null) {
baseDataTypeName =
dataTypeName.substring(0, dataTypeName.length() - decorations.length());
}
return getBaseConflictValue(baseDataTypeName);
}
/**
* Determine if the specified data type name is a conflict name.
*
* @param dataTypeName datatype name
* @return true if data type name is a conflict name.
*/
public static boolean isConflictDataTypeName(String dataTypeName) {
String decorations = getPointerArrayDecorations(dataTypeName);
String baseDataTypeName = dataTypeName;
if (decorations != null) {
baseDataTypeName =
dataTypeName.substring(0, dataTypeName.length() - decorations.length());
}
Matcher matcher = BASE_DATATYPE_CONFLICT_PATTERN.matcher(baseDataTypeName);
return matcher.find();
}
/**
* Determine if the specified data type has a conflict name.
* @param dt datatype (pointer and array permitted)
* @return true if data type has a conflict name.
*/
public static boolean isConflictDataType(DataType dt) {
if (!canHaveConflictName(dt)) {
return false; // e.g., many BuiltIn types
}
DataType baseDataType = getBaseDataType(dt);
if (baseDataType == null) {
return false; // e.g., default pointer
}
if (baseDataType != dt && !canHaveConflictName(baseDataType)) {
return false; // e.g., pointer to BuiltIn
}
Matcher matcher = BASE_DATATYPE_CONFLICT_PATTERN.matcher(dt.getName());
return matcher.find();
}
/**
* Compares two data type name strings to determine if they are equivalent names, ignoring
* conflict patterns present.
*
* @param name1 the first name
* @param name2 the second name
* @return true if the names are equivalent when conflict suffixes are ignored.
*/
public static boolean equalsIgnoreConflict(String name1, String name2) {
return getNameWithoutConflict(name1).equals(getNameWithoutConflict(name2));
}
}

View file

@ -618,24 +618,22 @@ class TypedefDB extends DataTypeDB implements TypeDef {
}
private String generateTypedefName(CategoryPath path) {
String newName = TypedefDataType.generateTypedefName(this);
DataType dt = dataMgr.getDataType(path, newName);
if (dt == null || dt == this) {
return newName;
}
String baseName = newName + DataType.CONFLICT_SUFFIX;
newName = baseName;
String baseName = TypedefDataType.generateTypedefName(this);
String testName = baseName;
int count = 0;
while (true) {
dt = dataMgr.getDataType(path, newName);
if (dt == null || dt == this) {
break;
while (!isNameUnusedOrMine(path, testName)) {
testName = baseName + DataType.CONFLICT_SUFFIX;
if (count > 0) {
testName += Integer.toString(count);
}
count++;
newName = baseName + count;
++count;
}
return newName;
return testName;
}
private boolean isNameUnusedOrMine(CategoryPath path, String newName) {
DataType dt = dataMgr.getDataType(path, newName);
return dt == null || dt == this;
}
boolean updateAutoName(boolean notify) {

View file

@ -563,8 +563,8 @@ public class FunctionManagerDB implements FunctionManager {
}
@Override
public FunctionIterator getFunctions(Address start, boolean foward) {
return new FunctionIteratorDB(start, foward);
public FunctionIterator getFunctions(Address start, boolean forward) {
return new FunctionIteratorDB(start, forward);
}
@Override
@ -585,8 +585,8 @@ public class FunctionManagerDB implements FunctionManager {
}
@Override
public FunctionIterator getFunctionsNoStubs(Address start, boolean foward) {
return new FunctionFilteredIterator(new FunctionIteratorDB(start, foward));
public FunctionIterator getFunctionsNoStubs(Address start, boolean forward) {
return new FunctionFilteredIterator(new FunctionIteratorDB(start, forward));
}
@Override

View file

@ -54,11 +54,8 @@ public interface Category extends Comparable<Category> {
public abstract DataType[] getDataTypes();
/**
* Get all data types in this category whose base name matches the base name of the given name.
* The base name of a name is the first part of the string up to where the first ".conflict"
* occurs. In other words, finds all data types whose name matches the given name once
* any conflict suffixes have been removed from both the given name and the data types
* that are being scanned.
* Get all data types whose name matches the given name once any conflict suffixes have been
* removed from both the given name and the data types that are being scanned.
* <br>
* NOTE: The {@code name} provided must not contain array or pointer decorations.
*

View file

@ -19,6 +19,7 @@ import java.util.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
/**
* A category path is the full path to a particular data type
@ -228,18 +229,35 @@ public class CategoryPath implements Comparable<CategoryPath> {
/**
* Return the {@link String} representation of this category path including the category name,
* where components are delimited with a forward slash. Any component that contains a forward
* slash will be have the forward slash characters escaped.
* where components are delimited with a forward slash. Any occurance of a forward slash
* within individual path components will be escaped (e.g., {@code "\/"}).
* @return the full category path
*/
public String getPath() {
if (isRoot()) {
return DELIMITER_STRING;
}
if (parent.isRoot()) {
return DELIMITER_CHAR + escapeString(name);
return parent.getPath(name);
}
/**
* Return the {@link String} representation of the specified {@code childName} within this
* category path where all path components are delimited with a forward slash. Any occurance
* of a forward slash within individual path components, including the {@code childName}, will
* be escaped (e.g., {@code "\/"}).
* @param childName child name
* @return full path for a child within this category
*/
public String getPath(String childName) {
if (StringUtils.isBlank(childName)) {
throw new IllegalArgumentException("blank child name");
}
return parent.getPath() + DELIMITER_CHAR + escapeString(name);
String path = getPath();
if (!isRoot()) {
path += DELIMITER_STRING;
}
path += escapeString(childName);
return path;
}
@Override

View file

@ -177,8 +177,8 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
/**
* This method throws an exception if the indicated data type is an ancestor of
* this data type. In other words, the specified data type has a component or
* sub-component containing this data type.
* this data type (i.e., the specified data type has a component or
* sub-component containing this data type).
*
* @param dataType the data type
* @throws IllegalArgumentException if the data type is an ancestor of this data

View file

@ -20,6 +20,7 @@ import java.util.Collection;
import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.scalar.Scalar;
import ghidra.util.InvalidNameException;
@ -50,6 +51,12 @@ public interface DataType {
@Deprecated
public static final DataType VOID = VoidDataType.dataType;
/**
* Datatype name conflict suffix.
*
* See {@link DataTypeUtilities} for various methods related to conflict name handling.
* Direct use of this string in application/user-level code is discouraged.
*/
public final static String CONFLICT_SUFFIX = ".conflict";
public final static String TYPEDEF_ATTRIBUTE_PREFIX = "__((";

View file

@ -88,7 +88,9 @@ public interface DataTypeManager {
/**
* Returns a unique name not currently used by any other dataType or category
* with the same baseName
* with the same baseName. This does not produce a conflict name and is intended
* to be used when generating an artifical datatype name only (e.g., {@code temp_1},
* {@code temp_2}; for {@code baseName="temp"}.
*
* @param path the path of the name
* @param baseName the base name to be made unique

View file

@ -15,7 +15,7 @@
*/
package ghidra.program.model.data;
import java.util.*;
import java.util.Comparator;
import ghidra.program.database.data.DataTypeUtilities;
@ -79,8 +79,8 @@ public class DataTypeNameComparator implements Comparator<String> {
}
// Same base-name, order by conflict
int conflict1 = getConflictValue(dt1Name);
int conflict2 = getConflictValue(dt2Name);
int conflict1 = DataTypeUtilities.getConflictValue(dt1Name);
int conflict2 = DataTypeUtilities.getConflictValue(dt2Name);
if (conflict1 != conflict2) {
return conflict1 - conflict2;
}
@ -88,15 +88,4 @@ public class DataTypeNameComparator implements Comparator<String> {
return name1.compareTo(name2);
}
private int getConflictValue(String dtName) {
String conflict = DataTypeUtilities.getConflictString(dtName);
if (conflict == null) {
return -1;
}
if (conflict.length() == 0) {
return 0;
}
return Integer.parseInt(conflict);
}
}

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.program.model.data;
package ghidra.program.database.data;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@ -24,8 +24,9 @@ import org.junit.Test;
import generic.test.AbstractGTest;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*;
public class DataTypeUtilitiesTest extends AbstractGTest {
public class DataTypeUtilities2Test extends AbstractGTest {
@Test
public void testGetContainedDataTypes() {

View file

@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.datamgr;
package ghidra.program.database.data;
import static org.junit.Assert.*;
import org.junit.*;
import generic.test.AbstractGenericTest;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.database.ProgramDB;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*;
@ -32,8 +31,6 @@ import ghidra.program.model.data.*;
*/
public class DataTypeUtilitiesTest extends AbstractGenericTest {
private ProgramBuilder builder;
private ProgramDB program;
private DataTypeManager dataTypeManager;
private int txID;
@ -43,70 +40,15 @@ public class DataTypeUtilitiesTest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
builder = new ProgramBuilder("nameTest", ProgramBuilder._TOY, this);
assertNotNull(builder);
program = builder.getProgram();
assertNotNull(program);
dataTypeManager = program.getDataTypeManager();
assertNotNull(dataTypeManager);
txID = program.startTransaction("NamingUtilities test");
dataTypeManager = new StandAloneDataTypeManager("Test");
dataTypeManager.startTransaction("Test");
}
@After
public void tearDown() throws Exception {
if (txID != 0) {
program.endTransaction(txID, false);
dataTypeManager.endTransaction(txID, true);
}
if (builder != null) {
builder.dispose();
}
}
@Test
public void testIsSameKindDataType() {
assertTrue(
DataTypeUtilities.isSameKindDataType(IntegerDataType.dataType, ShortDataType.dataType));
assertFalse(
DataTypeUtilities.isSameKindDataType(FloatDataType.dataType, ShortDataType.dataType));
assertTrue(
DataTypeUtilities.isSameKindDataType(new PointerDataType(IntegerDataType.dataType),
new PointerDataType(ShortDataType.dataType)));
assertFalse(
DataTypeUtilities.isSameKindDataType(new PointerDataType(FloatDataType.dataType),
new PointerDataType(ShortDataType.dataType)));
assertTrue(
DataTypeUtilities.isSameKindDataType(new StructureDataType("X", 10),
new StructureDataType("Y", 5)));
assertTrue(
DataTypeUtilities.isSameKindDataType(new UnionDataType("X"), new UnionDataType("Y")));
assertFalse(
DataTypeUtilities.isSameKindDataType(new StructureDataType("X", 10),
new UnionDataType("Y")));
assertTrue(
DataTypeUtilities.isSameKindDataType(
new PointerDataType(new StructureDataType("X", 10)),
new PointerDataType(new StructureDataType("Y", 5))));
assertTrue(
DataTypeUtilities.isSameKindDataType(new PointerDataType(new UnionDataType("X")),
new PointerDataType(new UnionDataType("Y"))));
assertFalse(
DataTypeUtilities.isSameKindDataType(
new PointerDataType(new StructureDataType("X", 10)),
new PointerDataType(new UnionDataType("Y"))));
assertTrue(
DataTypeUtilities.isSameKindDataType(
new TypedefDataType("Foo", new PointerDataType(new StructureDataType("X", 10))),
new PointerDataType(new StructureDataType("Y", 5))));
assertFalse(
DataTypeUtilities.isSameKindDataType(
new TypedefDataType("Foo", new PointerDataType(new StructureDataType("X", 10))),
new PointerDataType(new UnionDataType("Y"))));
}
@Test
@ -393,16 +335,10 @@ public class DataTypeUtilitiesTest extends AbstractGenericTest {
same("/cat1/simpleStruct.conflict1 *32 *64", "/cat1/simpleStruct *32 *64");
same("/cat1/simpleStruct.conflict_1234 *64", "/cat1.conflict5/simpleStruct *64");
same("/cat1/simpleStruct", "/cat1/simpleStruct.conflict1");
same("/cat1/simpleStruct.conflict_1234.conflict", "/cat1/simpleStruct");
same("/cat1/simpleStruct.conflict_1234", "/cat1/simpleStruct.conflict3");
same("simpleStruct.conflict_1234_abc", "simpleStruct.conflict4_abc");
same("simpleStruct.conflict12", "simpleStruct.conflict34");
same("/cat1/simpleStruct[5]", "/cat1/simpleStruct.conflict1[5]");
@ -525,6 +461,12 @@ public class DataTypeUtilitiesTest extends AbstractGenericTest {
different("/cat1/simpleStruct[11] *32[2]", "/cat1/simpleStruct.conflict1[11] *8[2]");
different("/cat1/simpleStruct[6] *16[9]", "/cat1/simpleStruct.conflict1[6] *64[9]");
different("/cat1/simpleStruct.conflict_1234 *64", "/cat1.conflict5/simpleStruct *64");
different("/cat1/simpleStruct.conflict_1234.conflict", "/cat1/simpleStruct");
different("simpleStruct.conflict_1234_abc", "simpleStruct.conflict4_abc");
}
private void same(String name1, String name2) {

View file

@ -99,7 +99,7 @@ public class StubFunctionManager implements FunctionManager {
}
@Override
public FunctionIterator getFunctions(Address start, boolean foward) {
public FunctionIterator getFunctions(Address start, boolean forward) {
throw new UnsupportedOperationException();
}
@ -114,7 +114,7 @@ public class StubFunctionManager implements FunctionManager {
}
@Override
public FunctionIterator getFunctionsNoStubs(Address start, boolean foward) {
public FunctionIterator getFunctionsNoStubs(Address start, boolean forward) {
throw new UnsupportedOperationException();
}