From 0199d0213fa6a6bc8ee9581032f5f2f7c1758214 Mon Sep 17 00:00:00 2001 From: emteere <47253321+emteere@users.noreply.github.com> Date: Fri, 18 Mar 2022 14:28:27 -0400 Subject: [PATCH] GP-1841 User new PointerTypedef for small method_t pointers, fixed chain pointer conflict with method structures --- .../bin/format/objc2/ObjectiveC2_Method.java | 17 ++-- .../format/objc2/ObjectiveC2_MethodList.java | 27 +++-- .../format/objectiveC/ObjectiveC1_Module.java | 12 ++- .../objectiveC/ObjectiveC1_SymbolTable.java | 52 ++++++---- .../objectiveC/ObjectiveC1_Utilities.java | 15 +-- .../objectiveC/ObjectiveC_MethodList.java | 28 ++++-- ...ObjectiveC2_DecompilerMessageAnalyzer.java | 3 + .../program/model/data/DataUtilities.java | 98 +++++++++++-------- 8 files changed, 154 insertions(+), 98 deletions(-) diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java index 30519dc79d..d1bf43deb0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_Method.java @@ -36,7 +36,7 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { isSmall = isSmallList; if (isSmallList) { - int nameOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true); + int nameOffset = (int) ObjectiveC1_Utilities.readNextIndex(reader, true); long namePtr; if (state.is32bit) { namePtr = reader.readInt(_index + nameOffset); @@ -47,17 +47,17 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { name = reader.readAsciiString(namePtr); - int typesOffset = (int)ObjectiveC1_Utilities.readNextIndex(reader, true); + int typesOffset = (int) ObjectiveC1_Utilities.readNextIndex(reader, true); types = reader.readAsciiString(_index + 4 + typesOffset); } else { long nameIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit); - name = reader.readAsciiString(nameIndex); + name = reader.readAsciiString(nameIndex); long typesIndex = ObjectiveC1_Utilities.readNextIndex(reader, state.is32bit); types = reader.readAsciiString(typesIndex); } - + imp = new ObjectiveC2_Implementation(state, reader, isSmallList); } @@ -65,17 +65,20 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { public String getName() { return name; } + @Override public String getTypes() { return types; } + @Override public long getImplementation() { return imp.getImplementation(); } + @Override public DataType toDataType() throws DuplicateNameException, IOException { - Structure struct = new StructureDataType("method_t", 0); + Structure struct = new StructureDataType("method" + (isSmall ? "_small" : "") + "_t", 0); if (isSmall) { DataType sdw = SignedDWordDataType.dataType; String comment = "offset from this address"; @@ -84,9 +87,9 @@ public class ObjectiveC2_Method extends ObjectiveC_Method { struct.add(sdw, sdw.getLength(), "imp", comment); } else { - struct.add(new PointerDataType(STRING), _state.pointerSize, "name", null); + struct.add(new PointerDataType(STRING), _state.pointerSize, "name", null); struct.add(new PointerDataType(STRING), _state.pointerSize, "types", null); - struct.add(new PointerDataType(VOID), _state.pointerSize, "imp", null); + struct.add(new PointerDataType(VOID), _state.pointerSize, "imp", null); } struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH); return struct; diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_MethodList.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_MethodList.java index 32be0cdd4b..71bac5371a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_MethodList.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objc2/ObjectiveC2_MethodList.java @@ -29,7 +29,8 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList { private int entsizeAndFlags; private int count; - public ObjectiveC2_MethodList(ObjectiveC2_State state, BinaryReader reader, ObjectiveC_MethodType methodType) throws IOException { + public ObjectiveC2_MethodList(ObjectiveC2_State state, BinaryReader reader, + ObjectiveC_MethodType methodType) throws IOException { super(state, reader, NAME); if (_index == 0) { @@ -37,15 +38,19 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList { } entsizeAndFlags = reader.readNextInt(); - count = reader.readNextInt(); + count = reader.readNextInt(); - boolean isSmallList = (entsizeAndFlags & 0x80000000) != 0; + boolean isSmallList = isSmallMethods(); - for (int i = 0 ; i < count ; ++i) { - methods.add( new ObjectiveC2_Method(state, reader, methodType, isSmallList) ); + for (int i = 0; i < count; ++i) { + methods.add(new ObjectiveC2_Method(state, reader, methodType, isSmallList)); } } + protected boolean isSmallMethods() { + return (entsizeAndFlags & 0x80000000) != 0; + } + public long getEntsizeAndFlags() { return entsizeAndFlags; } @@ -57,19 +62,21 @@ public class ObjectiveC2_MethodList extends ObjectiveC_MethodList { public static DataType toGenericDataType() throws DuplicateNameException { Structure struct = new StructureDataType(NAME, 0); struct.add(DWORD, "entsizeAndFlags", null); - struct.add(DWORD, "count", null); + struct.add(DWORD, "count", null); struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH); return struct; } + @Override public DataType toDataType() throws DuplicateNameException, IOException { - Structure struct = new StructureDataType(NAME+'_'+count+'_', 0); + Structure struct = + new StructureDataType(NAME + (isSmallMethods() ? "_small" : "") + '_' + count + '_', 0); struct.add(DWORD, "entsizeAndFlags", null); - struct.add(DWORD, "count", null); + struct.add(DWORD, "count", null); - for (int i = 0 ; i < methods.size() ; ++i) { - struct.add(methods.get(i).toDataType(), "method"+i, null); + for (int i = 0; i < methods.size(); ++i) { + struct.add(methods.get(i).toDataType(), "method" + i, null); } struct.setCategoryPath(ObjectiveC2_Constants.CATEGORY_PATH); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Module.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Module.java index 8a1b101cd7..2aaa4a4d3d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Module.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Module.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -16,14 +15,16 @@ */ package ghidra.app.util.bin.format.objectiveC; +import java.io.IOException; + import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; import ghidra.program.model.address.Address; import ghidra.program.model.data.*; +import ghidra.program.model.data.DataUtilities.ClearDataMode; +import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; -import java.io.IOException; - public class ObjectiveC1_Module implements StructConverter { private ObjectiveC1_State _state; private long _index; @@ -74,9 +75,11 @@ public class ObjectiveC1_Module implements StructConverter { _state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index); DataType dt = toDataType(); try { - _state.program.getListing().createData(address, dt); + DataUtilities.createData(_state.program, address, dt, -1, false, + ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA); } catch (Exception e) { + Msg.warn(this, "Could not create " + dt.getName() + " @" + address); } if (symbolTable != null) { @@ -84,6 +87,7 @@ public class ObjectiveC1_Module implements StructConverter { } } + @Override public DataType toDataType() throws DuplicateNameException, IOException { StructureDataType struct = new StructureDataType("objc_module", 0); struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_SymbolTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_SymbolTable.java index 28a73ab7f7..755bb3ea0e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_SymbolTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_SymbolTable.java @@ -23,6 +23,8 @@ import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; import ghidra.program.model.address.Address; import ghidra.program.model.data.*; +import ghidra.program.model.data.DataUtilities.ClearDataMode; +import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; public class ObjectiveC1_SymbolTable implements StructConverter { @@ -42,12 +44,12 @@ public class ObjectiveC1_SymbolTable implements StructConverter { this._state = state; this._index = reader.getPointerIndex(); - sel_ref_cnt = reader.readNextInt(); - refs = reader.readNextInt(); - cls_def_cnt = reader.readNextShort(); - cat_def_cnt = reader.readNextShort(); + sel_ref_cnt = reader.readNextInt(); + refs = reader.readNextInt(); + cls_def_cnt = reader.readNextShort(); + cat_def_cnt = reader.readNextShort(); - for (int i = 0 ; i < cls_def_cnt ; ++i) { + for (int i = 0; i < cls_def_cnt; ++i) { long classIndex = reader.readNextInt(); long oldClassIndex = reader.getPointerIndex(); reader.setPointerIndex(classIndex); @@ -55,7 +57,7 @@ public class ObjectiveC1_SymbolTable implements StructConverter { reader.setPointerIndex(oldClassIndex); } - for (int i = 0 ; i < cat_def_cnt ; ++i) { + for (int i = 0; i < cat_def_cnt; ++i) { long categoryIndex = reader.readNextInt(); long oldCategoryIndex = reader.getPointerIndex(); reader.setPointerIndex(categoryIndex); @@ -67,12 +69,15 @@ public class ObjectiveC1_SymbolTable implements StructConverter { public int getSelectorReferenceCount() { return sel_ref_cnt; } + public int getRefs() { return refs; } + public short getClassDefinitionCount() { return cls_def_cnt; } + public short getCategoryDefinitionCount() { return cat_def_cnt; } @@ -80,6 +85,7 @@ public class ObjectiveC1_SymbolTable implements StructConverter { public List getClasses() { return classes; } + public List getCategories() { return categories; } @@ -89,23 +95,28 @@ public class ObjectiveC1_SymbolTable implements StructConverter { struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH); struct.add(DWORD, "sel_ref_cnt", null); struct.add(DWORD, "refs", null); - struct.add( WORD, "cls_def_cnt", null); - struct.add( WORD, "cat_def_cnt", null); + struct.add(WORD, "cls_def_cnt", null); + struct.add(WORD, "cat_def_cnt", null); return struct; } + @Override public DataType toDataType() throws DuplicateNameException, IOException { - StructureDataType struct = new StructureDataType(NAME+"_"+cls_def_cnt+"_"+cat_def_cnt+"_", 0); + StructureDataType struct = + new StructureDataType(NAME + "_" + cls_def_cnt + "_" + cat_def_cnt + "_", 0); struct.setCategoryPath(ObjectiveC1_Constants.CATEGORY_PATH); struct.add(DWORD, "sel_ref_cnt", null); struct.add(DWORD, "refs", null); - struct.add( WORD, "cls_def_cnt", null); - struct.add( WORD, "cat_def_cnt", null); - for (int i = 0 ; i < cls_def_cnt ; ++i) { - struct.add(PointerDataType.getPointer(classes.get(i).toDataType(), _state.pointerSize), "class"+i, null); + struct.add(WORD, "cls_def_cnt", null); + struct.add(WORD, "cat_def_cnt", null); + for (int i = 0; i < cls_def_cnt; ++i) { + struct.add(PointerDataType.getPointer(classes.get(i).toDataType(), _state.pointerSize), + "class" + i, null); } - for (int i = 0 ; i < cat_def_cnt ; ++i) { - struct.add(PointerDataType.getPointer(categories.get(i).toDataType(), _state.pointerSize), "category"+i, null); + for (int i = 0; i < cat_def_cnt; ++i) { + struct.add( + PointerDataType.getPointer(categories.get(i).toDataType(), _state.pointerSize), + "category" + i, null); } return struct; } @@ -116,11 +127,16 @@ public class ObjectiveC1_SymbolTable implements StructConverter { } _state.beenApplied.add(_index); - Address address = _state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index); + Address address = + _state.program.getAddressFactory().getDefaultAddressSpace().getAddress(_index); + DataType dt = toDataType(); try { - _state.program.getListing().createData(address, toDataType()); + DataUtilities.createData(_state.program, address, dt, -1, false, + ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA); + } + catch (Exception e) { + Msg.warn(this, "Could not create " + dt.getName() + " @" + address); } - catch (Exception e) {} _state.program.getListing().getDefinedDataAt(address); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Utilities.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Utilities.java index 44d3d1e4c8..ca227385f7 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Utilities.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC1_Utilities.java @@ -31,6 +31,7 @@ import ghidra.framework.cmd.Command; import ghidra.program.database.symbol.ClassSymbol; import ghidra.program.model.address.*; import ghidra.program.model.data.*; +import ghidra.program.model.data.DataUtilities.ClearDataMode; import ghidra.program.model.lang.Processor; import ghidra.program.model.lang.Register; import ghidra.program.model.listing.*; @@ -48,8 +49,8 @@ public final class ObjectiveC1_Utilities { * Clears the code units defined in the given memory block. */ public static void clear(ObjectiveC2_State state, MemoryBlock block) throws Exception { - state.program.getListing().clearCodeUnits(block.getStart(), block.getEnd(), false, - state.monitor); + state.program.getListing() + .clearCodeUnits(block.getStart(), block.getEnd(), false, state.monitor); } /** @@ -143,9 +144,11 @@ public final class ObjectiveC1_Utilities { if (data != null && data.getDataType().isEquivalent(dt)) { return; } - //program.getListing().clearCodeUnits(address, address.add(dt.getLength()-1)); - program.getListing().createData(address, dt); + // need to clear, as pointers could have been created on import + // from following pointer chains + DataUtilities.createData(program, address, dt, -1, false, + ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA); } /** @@ -230,8 +233,8 @@ public final class ObjectiveC1_Utilities { */ public static Symbol createSymbol(Program program, Namespace parentNamespace, String symbolName, Address symbolAddress) throws InvalidInputException { - Symbol symbol = program.getSymbolTable().createLabel(symbolAddress, symbolName, - parentNamespace, SourceType.IMPORTED); + Symbol symbol = program.getSymbolTable() + .createLabel(symbolAddress, symbolName, parentNamespace, SourceType.IMPORTED); symbol.setPrimary(); return symbol; } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC_MethodList.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC_MethodList.java index 5532c0cdb9..28f5e6965d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC_MethodList.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/objectiveC/ObjectiveC_MethodList.java @@ -1,6 +1,5 @@ /* ### * 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. @@ -16,13 +15,15 @@ */ package ghidra.app.util.bin.format.objectiveC; +import java.util.ArrayList; +import java.util.List; + import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.StructConverter; import ghidra.program.model.address.Address; +import ghidra.program.model.data.DataType; import ghidra.program.model.symbol.Namespace; - -import java.util.ArrayList; -import java.util.List; +import ghidra.util.Msg; public abstract class ObjectiveC_MethodList implements StructConverter { private String _className; @@ -31,7 +32,8 @@ public abstract class ObjectiveC_MethodList implements StructConverter { protected List methods = new ArrayList(); - protected ObjectiveC_MethodList(ObjectiveC1_State state, BinaryReader reader, String className) { + protected ObjectiveC_MethodList(ObjectiveC1_State state, BinaryReader reader, + String className) { this._state = state; this._index = reader.getPointerIndex(); this._className = className; @@ -51,17 +53,23 @@ public abstract class ObjectiveC_MethodList implements StructConverter { _state.beenApplied.add(_index); Address address = ObjectiveC1_Utilities.toAddress(_state.program, _index); + DataType dt = toDataType(); try { - ObjectiveC1_Utilities.applyData(_state.program, toDataType(), address); + ObjectiveC1_Utilities.applyData(_state.program, dt, address); + } + catch (Exception e) { + Msg.warn(this, "Could not create " + dt.getName() + " @" + address); } - catch (Exception e) {} try { //creates a symbol on the method list data structure - Namespace methodListNamespace = ObjectiveC1_Utilities.createNamespace(_state.program, ObjectiveC1_Constants.NAMESPACE, _className); - ObjectiveC1_Utilities.createSymbol(_state.program, methodListNamespace, namespace.getName(), address); + Namespace methodListNamespace = ObjectiveC1_Utilities.createNamespace(_state.program, + ObjectiveC1_Constants.NAMESPACE, _className); + ObjectiveC1_Utilities.createSymbol(_state.program, methodListNamespace, + namespace.getName(), address); + } + catch (Exception e) { } - catch (Exception e) {} for (ObjectiveC_Method method : getMethods()) { method.applyTo(namespace); diff --git a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_DecompilerMessageAnalyzer.java b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_DecompilerMessageAnalyzer.java index 14ac26aedf..9cbe37e861 100644 --- a/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_DecompilerMessageAnalyzer.java +++ b/Ghidra/Features/Decompiler/src/main/java/ghidra/app/plugin/core/analysis/ObjectiveC2_DecompilerMessageAnalyzer.java @@ -191,6 +191,9 @@ public class ObjectiveC2_DecompilerMessageAnalyzer extends AbstractAnalyzer { } setReference(objcCallAddress, program, currentClassName, currentMethodName); + if (instruction == null) { + return; + } if (instruction.getComment(CodeUnit.EOL_COMMENT) != null) { return; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java index 8d62b17349..60e229ef13 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataUtilities.java @@ -70,21 +70,57 @@ public final class DataUtilities { */ CLEAR_SINGLE_DATA, /** - * Clear all conflicting Undefined data provided data will + * Clear all conflicting Undefined Data provided new data will * fit within memory and not conflict with an * instruction or other defined data. Undefined refers to defined - * data with the Undefined data-type. - * @see Undefined#isUndefined(DataType) + * data with the Undefined data-type (see {@link Undefined#isUndefined(DataType)}). */ CLEAR_ALL_UNDEFINED_CONFLICT_DATA, /** - * Clear all conflicting data provided data will - * fit within memory and not conflict with an - * instruction. + * Clear all Default Data provided new data will fit within memory and + * not conflict with an instruction or other defined data. In this + * context Default Data refers to all defined data with either an + * Undefined data-type (see {@link Undefined#isUndefined(DataType)}) or + * is considered a default pointer which is either: + *
    + *
  1. A pointer without a referenced datatype (i.e., addr), or
  2. + *
  3. An auto-named pointer-typedef without a referenced datatype + * (e.g., pointer __((offset(0x8))).
  4. + *
+ */ + CLEAR_ALL_DEFAULT_CONFLICT_DATA, + /** + * Clear all conflicting data provided new data will fit within memory and + * not conflict with an instruction. */ CLEAR_ALL_CONFLICT_DATA } + private static boolean isDefaultData(DataType dt) { + // see ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA + if (Undefined.isUndefined(dt)) { + return true; + } + if (dt instanceof Pointer) { + Pointer p = (Pointer) dt; + dt = p.getDataType(); + return dt == null || dt == DataType.DEFAULT; + } + return false; + } + + private static boolean isDataClearingDenied(DataType dt, ClearDataMode clearMode) { + if ((clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA && + !Undefined.isUndefined(dt))) { + return true; + } + if (clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA && + !isDefaultData(dt)) { + return true; + } + return false; + } + /** * Create data where existing data may already exist. * @param program the program @@ -113,8 +149,7 @@ public final class DataUtilities { return data; } - if (!stackPointers && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA && - !Undefined.isUndefined(existingType)) { + if (!stackPointers && isDataClearingDenied(existingType, clearMode)) { throw new CodeUnitInsertionException("Could not create Data at address " + addr); } @@ -176,12 +211,12 @@ public final class DataUtilities { // null data; see if we are in a composite if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA || - clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) { + clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA || + clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA) { // allow offcut addr if CLEAR_ALL_CONFLICT_DATA data = listing.getDataContaining(addr); - if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA && - !Undefined.isUndefined(data.getDataType())) { + if (data != null && isDataClearingDenied(data.getDataType(), clearMode)) { data = null; // force error } } @@ -267,32 +302,8 @@ public final class DataUtilities { return extRef; } - private static void validateCanCreateData(Address addr, ClearDataMode clearMode, - Listing listing, Data data) throws CodeUnitInsertionException { - - if (data != null) { - return; // existing data; it us possible to create data - } - - if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA || - clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) { - - // allow offcut addr if CLEAR_ALL_CONFLICT_DATA - data = listing.getDataContaining(addr); - if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA && - !Undefined.isUndefined(data.getDataType())) { - data = null; // force error - } - } - - // null data implies that we cannot create data at this address - if (data == null) { - throw new CodeUnitInsertionException("Could not create Data at address " + addr); - } - } - private static void checkEnoughSpace(Program program, Address addr, int existingDataLen, - DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException { + DataTypeInstance dti, ClearDataMode clearMode) throws CodeUnitInsertionException { // NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA Listing listing = program.getListing(); Address end = null; @@ -318,11 +329,12 @@ public final class DataUtilities { return; } - if (mode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA && - Undefined.isUndefined(definedData.getDataType())) { - checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress()); + if ((clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA || + clearMode == ClearDataMode.CLEAR_ALL_DEFAULT_CONFLICT_DATA) && + !isDataClearingDenied(definedData.getDataType(), clearMode)) { + checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress(), clearMode); } - else if (mode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) { + else if (clearMode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) { throw new CodeUnitInsertionException("Not enough space to create DataType " + dti.getDataType().getDisplayName()); } @@ -330,9 +342,9 @@ public final class DataUtilities { } private static void checkForDefinedData(DataTypeInstance dti, Listing listing, Address address, - Address end) throws CodeUnitInsertionException { + Address end, ClearDataMode clearMode) throws CodeUnitInsertionException { - // ignore all defined data which is considered Undefined and may be cleared + // ignore all defined data which may be cleared while (end.compareTo(address) <= 0) { Data definedData = listing.getDefinedDataAfter(end); if (definedData == null || @@ -340,7 +352,7 @@ public final class DataUtilities { return; } - if (!Undefined.isUndefined(definedData.getDataType())) { + if (isDataClearingDenied(definedData.getDataType(), clearMode)) { throw new CodeUnitInsertionException("Not enough space to create DataType " + dti.getDataType().getDisplayName()); }