diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/DataTypeSettingsDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/DataTypeSettingsDialog.java index 75f11419fe..c31442561e 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/DataTypeSettingsDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/data/DataTypeSettingsDialog.java @@ -86,8 +86,8 @@ public class DataTypeSettingsDialog extends AbstractSettingsDialog { nameBuf.append("Default "); } String name = dataType.getDisplayName(); - // default array settings defer to base type if (dtc == null) { + // default array settings defer to base type name = getSettingsBaseType(dataType).getDisplayName(); } nameBuf.append(name); @@ -147,6 +147,7 @@ public class DataTypeSettingsDialog extends AbstractSettingsDialog { return null; } + @Override protected void applySettings() { DataTypeManager dtm = dataType.getDataTypeManager(); int txId = dtm.startTransaction(getTitle()); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/InstanceSettingsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/InstanceSettingsTest.java index 6dd937cccf..72141571bf 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/InstanceSettingsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/InstanceSettingsTest.java @@ -112,6 +112,50 @@ public class InstanceSettingsTest extends AbstractGhidraHeadedIntegrationTest { assertEquals(PaddingSettingsDefinition.UNPADDED_VALUE, data.getLong("padded").longValue()); } + @Test + public void testComponentInstanceSettings() throws Exception { + + Structure s = new StructureDataType("struct", 0); + s.setPackingEnabled(true); + s.add(new ArrayDataType(ByteDataType.dataType, 4, -1)); + s = (Structure) dataMgr.resolve(s, null); + + Data data = DataUtilities.createData(program, addr(10), s, -1, false, + ClearDataMode.CLEAR_ALL_CONFLICT_DATA); + + Data component = data.getComponent(new int[] { 0, 2 }); + assertNotNull(component); + + Settings defaultSettings = component.getDefaultSettings(); + FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.CHAR); + EndianSettingsDefinition.DEF.setBigEndian(defaultSettings, false); + PaddingSettingsDefinition.DEF.setPadded(defaultSettings, true); + + assertEquals(FormatSettingsDefinition.CHAR, component.getLong("format").longValue()); + FormatSettingsDefinition.DEF.setChoice(component, FormatSettingsDefinition.DECIMAL); + assertEquals(FormatSettingsDefinition.DECIMAL, component.getLong("format").longValue()); + + assertEquals(EndianSettingsDefinition.LITTLE, component.getLong("endian").longValue()); + EndianSettingsDefinition.DEF.setChoice(component, EndianSettingsDefinition.BIG); + assertEquals(EndianSettingsDefinition.BIG, component.getLong("endian").longValue()); + + assertEquals(PaddingSettingsDefinition.PADDED_VALUE, + component.getLong("padded").longValue()); + PaddingSettingsDefinition.DEF.setChoice(component, + PaddingSettingsDefinition.UNPADDED_VALUE); + assertEquals(PaddingSettingsDefinition.UNPADDED_VALUE, + component.getLong("padded").longValue()); + + FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.HEX); + EndianSettingsDefinition.DEF.clear(defaultSettings); + PaddingSettingsDefinition.DEF.clear(defaultSettings); + + assertEquals(FormatSettingsDefinition.DECIMAL, component.getLong("format").longValue()); + assertEquals(EndianSettingsDefinition.BIG, component.getLong("endian").longValue()); + assertEquals(PaddingSettingsDefinition.UNPADDED_VALUE, + component.getLong("padded").longValue()); + } + @Test public void testGetInstanceNames() throws Exception { Data data = listing.getDataAt(addr(10)); @@ -259,7 +303,6 @@ public class InstanceSettingsTest extends AbstractGhidraHeadedIntegrationTest { private void addBlock() throws Exception { Memory memory = program.getMemory(); - memory.createInitializedBlock("test", addr(0), 100, (byte) 0, - TaskMonitor.DUMMY, false); + memory.createInitializedBlock("test", addr(0), 100, (byte) 0, TaskMonitor.DUMMY, false); } } diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/SettingsTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/SettingsTest.java index 39dc6c95d7..2cc58aed91 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/SettingsTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/program/database/data/SettingsTest.java @@ -389,6 +389,41 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest { assertEquals(Array.class, array.getValueClass(defaultSettings)); } + @Test + public void testDefaultSettingsOnCharArrayComponent() throws Exception { + + DataType charDT = dataMgr.resolve(new CharDataType(), null); + SettingsDefinition[] settingsDefinitions = charDT.getSettingsDefinitions(); + + assertTrue("Expect multiple settings on char type", settingsDefinitions.length > 2); // make sure we get more than two settings + + Array array = new ArrayDataType(charDT, 5, -1); + assertArrayEquals(settingsDefinitions, array.getSettingsDefinitions()); + + array = (Array) dataMgr.resolve(array, null); + assertArrayEquals(settingsDefinitions, array.getSettingsDefinitions()); + + Structure s = new StructureDataType("struct", 0); + s.setPackingEnabled(true); + s.add(array); + s = (Structure) dataMgr.resolve(s, null); + DataTypeComponent dtc = s.getComponent(0); + + Settings defaultSettings = dtc.getDefaultSettings(); + + assertEquals(FormatSettingsDefinition.CHAR, + FormatSettingsDefinition.DEF_CHAR.getChoice(defaultSettings)); + + assertEquals(MutabilitySettingsDefinition.NORMAL, + MutabilitySettingsDefinition.DEF.getChoice(defaultSettings)); + + assertEquals(String.class, array.getValueClass(defaultSettings)); + + FormatSettingsDefinition.DEF_CHAR.setChoice(defaultSettings, FormatSettingsDefinition.HEX); + + assertEquals(Array.class, array.getValueClass(defaultSettings)); + } + @Test public void testDefaultSettingsOnTypedef() throws Exception { DataType byteDT = dataMgr.resolve(ByteDataType.dataType, null); @@ -516,7 +551,6 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest { private void addBlock() throws Exception { Memory memory = program.getMemory(); - memory.createInitializedBlock("test", addr(0), 100, (byte) 0, - TaskMonitor.DUMMY, false); + memory.createInitializedBlock("test", addr(0), 100, (byte) 0, TaskMonitor.DUMMY, false); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/DataComponent.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/DataComponent.java index b9d783126b..b59d447030 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/DataComponent.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/code/DataComponent.java @@ -287,6 +287,10 @@ class DataComponent extends DataDB { if (component != null) { return component.getDefaultSettings(); } + if (parent instanceof DataComponent) { + // Ensure we pickup default component settings for array + return parent.getDefaultSettings(); + } return super.getDefaultSettings(); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java index 1497074617..9d662f5f67 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/ProgramDataTypeManager.java @@ -177,6 +177,15 @@ public class ProgramDataTypeManager extends ProgramBasedDataTypeManagerDB implem } } + @Override + public void dataTypeSettingsChanged(DataType dt) { + super.dataTypeSettingsChanged(dt); + if (!isCreatingDataType()) { + program.dataTypeChanged(getID(dt), ProgramEvent.DATA_TYPE_SETTING_CHANGED, false, null, + dt); + } + } + @Override protected void dataTypeAdded(DataType newDt, DataType originalDataType) { super.dataTypeAdded(newDt, originalDataType); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/ProgramEvent.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/ProgramEvent.java index 295b62ea1a..8cffb56090 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/ProgramEvent.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/util/ProgramEvent.java @@ -101,7 +101,7 @@ public enum ProgramEvent implements EventType { DATA_TYPE_RENAMED, // a data type was renamed DATA_TYPE_MOVED, // a data type was moved DATA_TYPE_CHANGED, // a data type was changed - DATA_TYPE_SETTING_CHANGED, // a data type's settings changed + DATA_TYPE_SETTING_CHANGED, // a data type's settings changed (default or at specific address) DATA_TYPE_REPLACED, // a data type was replaced SOURCE_ARCHIVE_ADDED, // a new data type source archive was defined SOURCE_ARCHIVE_CHANGED, // a data type source archive was changed