diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java index fa41507f5e..8938fb089d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/app/merge/datatypes/DataTypeMerge3Test.java @@ -77,10 +77,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); - - Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); - Union union = (Union) c.getDataType("CoolUnion"); // choose MY chooseOption(DataTypeMergeManager.OPTION_MY);// DLL_Table from MY @@ -90,6 +86,11 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + + Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); + Union union = (Union) c.getDataType("CoolUnion"); + // DLL_Table should have a Word data type as the last component Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table"); DataTypeComponent dtc = s.getComponent(s.getNumComponents() - 1); @@ -154,7 +155,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); // choose DLL_Table from LATEST which means delete it chooseOption(DataTypeMergeManager.OPTION_LATEST); @@ -164,6 +164,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); @@ -226,7 +228,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// choose DLL_Table from ORIGINAL @@ -234,6 +235,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + Category c = dtm.getCategory(new CategoryPath("/Category1/Category2")); Union union = (Union) c.getDataType("CoolUnion"); @@ -298,6 +301,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { executeMerge(true); + setErrorsExpected(false); + DataTypeManager dtm = resultProgram.getDataTypeManager(); checkConflictCount(0); @@ -371,13 +376,17 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); + executeMerge(); + + chooseOption(DataTypeMergeManager.OPTION_LATEST);// LATEST CoolUnion + setErrorsExpected(true); - executeMerge(); - chooseOption(DataTypeMergeManager.OPTION_LATEST);// LATEST CoolUnion chooseOption(DataTypeMergeManager.OPTION_MY);// MY Foo waitForCompletion(); + setErrorsExpected(false); + checkConflictCount(0); DataTypeManager dtm = resultProgram.getDataTypeManager(); @@ -451,10 +460,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); - setErrorsExpected(true); - executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_MY);// MY CoolUnion @@ -462,6 +468,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -522,10 +530,12 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); + executeMerge(); + + chooseOption(DataTypeMergeManager.OPTION_LATEST);// Latest CoolUnion + setErrorsExpected(true); - executeMerge(); - chooseOption(DataTypeMergeManager.OPTION_LATEST);// Latest CoolUnion chooseOption(DataTypeMergeManager.OPTION_MY);// My Bar // @@ -533,6 +543,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { // OptionDialog errorDialog = waitForDialogComponent(null, OptionDialog.class, DEFAULT_WINDOW_TIMEOUT); + + setErrorsExpected(false); + assertNotNull(errorDialog); errorDialog.close(); window.setVisible(false); @@ -602,17 +615,20 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); - setErrorsExpected(true); - executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); - // + chooseOption(DataTypeMergeManager.OPTION_MY);// choose My Bar - chooseOption(DataTypeMergeManager.OPTION_ORIGINAL); - // choose Structure_1 from ORIGINAL + setErrorsExpected(true); + + chooseOption(DataTypeMergeManager.OPTION_ORIGINAL); // choose Structure_1 from ORIGINAL + + setErrorsExpected(false); waitForCompletion(); + + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // Bar should contain original Structure_1 Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); DataTypeComponent[] dtcs = bar.getDefinedComponents(); @@ -676,14 +692,15 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); - // - chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// choose original Bar - chooseOption(DataTypeMergeManager.OPTION_MY); - // choose Structure_1 from MY + chooseOption(DataTypeMergeManager.OPTION_ORIGINAL); // choose original Bar + + chooseOption(DataTypeMergeManager.OPTION_MY); // choose Structure_1 from MY waitForCompletion(); + + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // Bar should contain original Structure_1 Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); assertEquals(6, bar.getLength()); @@ -750,14 +767,15 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); - // + chooseOption(DataTypeMergeManager.OPTION_MY);// choose my Bar - chooseOption(DataTypeMergeManager.OPTION_LATEST);// delele Structure_1 - // choose Structure_1 from MY + chooseOption(DataTypeMergeManager.OPTION_LATEST);// delele Structure_1 (choose Structure_1 from MY) waitForCompletion(); + + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // Bar should contain undefined to replace Structure_1 Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar"); assertEquals(7, bar.getLength()); @@ -848,7 +866,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); // conflict on ArrayStruct (6) chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// use ORIGINAL ArrayStruct @@ -859,6 +876,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { // conflict on FloatStruct (2) chooseOption(DataTypeMergeManager.OPTION_LATEST);// delete FloatStruct + DataTypeManager dtm = resultProgram.getDataTypeManager(); + assertNull( dtm.getDataType(new CategoryPath("/Category1/Category2/Category5"), "FloatStruct")); @@ -940,7 +959,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { // bitfield silently transitions to int since typedef BF was removed - executeMerge(); + executeMerge(true); + DataTypeManager dtm = resultProgram.getDataTypeManager(); Structure s1 = @@ -1028,7 +1048,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { // bitfield silently transitions to BF.conflict since two different BF types were added - executeMerge(); + executeMerge(true); + DataTypeManager dtm = resultProgram.getDataTypeManager(); Structure s1 = @@ -1129,7 +1150,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// choose DLL_Table from ORIGINAL @@ -1137,6 +1157,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // DLL_Table should exist Structure dll = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table"); @@ -1218,7 +1240,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_LATEST);// delete DLL_Table @@ -1226,6 +1247,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // DLL_Table should not exist Structure dll = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table"); @@ -1308,7 +1331,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// original DLL_Table @@ -1316,6 +1338,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should not be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1395,7 +1419,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_LATEST);// delete DLL_Table @@ -1403,6 +1426,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should not be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1483,7 +1508,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_MY);// my DLL_Table @@ -1491,6 +1515,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1572,7 +1598,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// original DLL_Table @@ -1580,6 +1605,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should not be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1668,7 +1695,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// original DLL_Table @@ -1676,6 +1702,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should not be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1773,7 +1801,6 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_ORIGINAL);// original DLL_Table @@ -1781,6 +1808,8 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // CoolUnion should not be null Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); @@ -1893,12 +1922,13 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest { } }); executeMerge(); - DataTypeManager dtm = resultProgram.getDataTypeManager(); chooseOption(DataTypeMergeManager.OPTION_MY);// MY bitfields w/ enum waitForCompletion(); + DataTypeManager dtm = resultProgram.getDataTypeManager(); + // primitive type of byte used in absence of enum Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion"); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index e6fc6db105..b262485cb9 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -772,7 +772,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { private DataType resolveBitFieldDataType(BitFieldDataType bitFieldDataType, DataTypeConflictHandler handler) { - // NOTE: When a bit-field is getting adding added it will get resolved more than once. + // NOTE: When a bit-field is getting added it will get resolved more than once. // The first time we will ensure that the base data type, which may be a TypeDef, gets // resolved. If the bit-offset is too large it will be set to 0 // with the expectation that it will get corrected during subsequent packing. @@ -786,7 +786,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager { int storageSizeBits = 8 * storageSize; if ((bitOffset + bitSize) > storageSizeBits) { // should get recomputed during packing when used within aligned structure - bitOffset = getDataOrganization().isBigEndian() ? baseLengthBits - bitSize : 0; + int effectiveBitSize = Math.min(bitSize, baseLengthBits); + bitOffset = getDataOrganization().isBigEndian() ? baseLengthBits - effectiveBitSize : 0; storageSize = baseLength; } try { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java index 8b70770bf3..8f3d98148b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/StructureDB.java @@ -997,10 +997,7 @@ class StructureDB extends CompositeDB implements Structure { if (ordinal < 0 || ordinal >= numComponents) { throw new ArrayIndexOutOfBoundsException(ordinal); } - if (dataType instanceof BitFieldDataType) { - throw new IllegalArgumentException( - "Components may not be replaced with a bit-field"); - } + validateDataType(dataType); DataTypeComponent origDtc = getComponent(ordinal); @@ -1044,9 +1041,7 @@ class StructureDB extends CompositeDB implements Structure { throw new IllegalArgumentException( "Offset " + offset + " is beyond end of structure (" + structLength + ")."); } - if (dataType instanceof BitFieldDataType) { - throw new IllegalArgumentException("Components may not be replaced with a bit-field"); - } + lock.acquire(); try { checkDeleted(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java index 140a91ff3d..d05d36db2c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/StructureDataType.java @@ -1149,9 +1149,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur if (index < 0 || index >= numComponents) { throw new ArrayIndexOutOfBoundsException(index); } - if (dataType instanceof BitFieldDataType) { - throw new IllegalArgumentException("Components may not be replaced with a bit-field"); - } validateDataType(dataType); @@ -1191,9 +1188,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur throw new IllegalArgumentException( "Offset " + offset + " is beyond end of structure (" + structLength + ")."); } - if (dataType instanceof BitFieldDataType) { - throw new IllegalArgumentException("Components may not be replaced with a bit-field"); - } validateDataType(dataType);