diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeTreeCopyMoveTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeTreeCopyMoveTask.java index de5e5da8ac..99ee1297c4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeTreeCopyMoveTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/util/DataTypeTreeCopyMoveTask.java @@ -338,6 +338,12 @@ public class DataTypeTreeCopyMoveTask extends Task { DataTypeManager nodeDtm = dataType.getDataTypeManager(); boolean sameManager = (dtm == nodeDtm); DataType newDt = !sameManager ? dataType.clone(nodeDtm) : dataType.copy(nodeDtm); + + if (!sameManager && toCategory.isRoot()) { + // preserve use of source category when copy to root + toCategory = dtm.createCategory(dataType.getCategoryPath()); + } + if (sameManager && newDt.getCategoryPath().equals(toCategory.getCategoryPath())) { renameAsCopy(toCategory, newDt); } diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java index e24c3ef1d8..aa7f1118da 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java @@ -138,7 +138,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { try { Address spareDataAddress = getSpareDataAddress(); - if (spareDataAddress != null && spareDataAddress.getOffset() != 0L && + if (spareDataAddress != null && spareDataAddress.getOffset() != 0 && !loadedAndInitializedSet.contains(spareDataAddress)) { throw new InvalidDataTypeException(getName() + " data type at " + getAddress() + " doesn't point to a spare data address in a loaded and initialized memory block."); @@ -360,8 +360,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { Address vfTableAddress; // component 0 is either vf table pointer or hash value. vfTableAddress = EHDataTypeUtilities.getAddress(getDataType(), VF_TABLE_OR_HASH_ORDINAL, getMemBuffer()); - - return vfTableAddress.getOffset() != 0 ? vfTableAddress : null; + return (vfTableAddress != null && vfTableAddress.getOffset() != 0) ? vfTableAddress : null; } /** @@ -393,7 +392,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { // component 1 is the spare data. Address spareAddress = EHDataTypeUtilities.getAddress(getDataType(), SPARE_ORDINAL, getMemBuffer()); - return spareAddress.getOffset() != 0 ? spareAddress : null; + return (spareAddress != null && spareAddress.getOffset() != 0) ? spareAddress : null; } /** diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/Rtti1Model.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/Rtti1Model.java index ee5261e991..17b0c1f8da 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/Rtti1Model.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/Rtti1Model.java @@ -122,7 +122,7 @@ public class Rtti1Model extends AbstractCreateRttiDataModel { // First component is either a direct reference or an image base offset. Address rtti0Address = getReferencedAddress(program, startAddress); if (rtti0Address == null) { - invalid(); // throws Exception + invalid("Invalid TypeDescriptor reference (pTypeDescriptor)."); // throws Exception } rtti0Model = new TypeDescriptorModel(program, rtti0Address, validationOptions); if (validateReferredToData) { diff --git a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/settings/SettingsImpl.java b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/settings/SettingsImpl.java index 98c077d538..2f36664245 100644 --- a/Ghidra/Framework/Docking/src/main/java/ghidra/docking/settings/SettingsImpl.java +++ b/Ghidra/Framework/Docking/src/main/java/ghidra/docking/settings/SettingsImpl.java @@ -241,6 +241,9 @@ public class SettingsImpl implements Settings, Serializable { @Override public void clearAllSettings() { + if (map.isEmpty()) { + return; + } if (checkSetting(null, null)) { map.clear(); changed(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/PointerTypedefInspector.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/PointerTypedefInspector.java index a605019334..576cc939c2 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/PointerTypedefInspector.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/PointerTypedefInspector.java @@ -15,8 +15,8 @@ */ package ghidra.program.database.data; -import ghidra.program.model.address.AddressFactory; -import ghidra.program.model.address.AddressSpace; +import ghidra.docking.settings.Settings; +import ghidra.program.model.address.*; import ghidra.program.model.data.*; /** @@ -60,12 +60,21 @@ public class PointerTypedefInspector { if (!pointerTypeDef.isPointer()) { return null; } + Settings settings = pointerTypeDef.getDefaultSettings(); String spaceName = - AddressSpaceSettingsDefinition.DEF.getValue(pointerTypeDef.getDefaultSettings()); + AddressSpaceSettingsDefinition.DEF.getValue(settings); if (spaceName == null) { return null; } - return addrFactory.getAddressSpace(spaceName); + AddressSpace addressSpace = addrFactory.getAddressSpace(spaceName); + if (addressSpace instanceof SegmentedAddressSpace) { + // Other settings do not apply when SegmentedAddressSpace is used + // see PointerDataType.getAddressValue(MemBuffer, int, Settings) + return addressSpace; + } + // Address space setting ignored if Pointer Type has been specified + PointerType choice = PointerTypeSettingsDefinition.DEF.getType(settings); + return choice == PointerType.DEFAULT ? addressSpace : null; } /** diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeMnemonicSettingsDefinition.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeMnemonicSettingsDefinition.java index 0b57bfd833..4f5024f659 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeMnemonicSettingsDefinition.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/DataTypeMnemonicSettingsDefinition.java @@ -41,7 +41,9 @@ public class DataTypeMnemonicSettingsDefinition implements EnumSettingsDefinitio /** * Returns the format based on the specified settings * @param settings the instance settings. - * @return the format value (HEX, DECIMAL, BINARY, OCTAL, CHAR) + * @return the mnemonic style (DEFAULT, ASSEMBLY, CSPEC). + * The ASSEMBLY style is returned if no setting has been made. + * The DEFAULT style corresponds to the use of {@link DataType#getName()}. */ public int getMnemonicStyle(Settings settings) { if (settings == null) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerDataType.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerDataType.java index b102e2fea7..408ed7bb0f 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerDataType.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerDataType.java @@ -368,6 +368,7 @@ public class PointerDataType extends BuiltIn implements Pointer { Program program = mem.getProgram(); String spaceName = AddressSpaceSettingsDefinition.DEF.getValue(settings); if (spaceName != null) { + // this space may be ignored if pointer type specified targetSpace = program.getAddressFactory().getAddressSpace(spaceName); } } @@ -377,12 +378,13 @@ public class PointerDataType extends BuiltIn implements Pointer { } if (targetSpace instanceof SegmentedAddressSpace) { - // ignore other settings + // ignore other settings with SegmentedAddressSpace use return getAddressValue(buf, size, targetSpace); } Long offset = getStoredOffset(buf, size); if (offset == null) { + // Insufficient bytes return null; } @@ -403,7 +405,13 @@ public class PointerDataType extends BuiltIn implements Pointer { try { PointerType choice = PointerTypeSettingsDefinition.DEF.getType(settings); + // Address space setting ignored if Pointer Type has been specified if (choice == PointerType.IMAGE_BASE_RELATIVE && mem != null) { + if (addrOffset == 0) { + // Done for consistency with old ImageBaseOffsetDataType. + // A 0 relative offset is considerd invalid (NaP) + return null; + } // must ignore AddressSpaceSettingsDefinition Address imageBase = mem.getProgram().getImageBase(); targetSpace = imageBase.getAddressSpace(); @@ -464,10 +472,16 @@ public class PointerDataType extends BuiltIn implements Pointer { return null; } + Long offset = getStoredOffset(buf, size); + if (offset == null) { + // Insufficient bytes + return null; + } + if (targetSpace instanceof SegmentedAddressSpace) { try { // NOTE: conversion assumes a little-endian space - return getSegmentedAddressValue(buf, size); + return getSegmentedAddressValue(buf, size, offset); } catch (AddressOutOfBoundsException e) { // offset too large @@ -482,14 +496,13 @@ public class PointerDataType extends BuiltIn implements Pointer { return null; } - Long offset = getStoredOffset(buf, size); - if (offset != null) { - try { - return targetSpace.getAddress(offset, true); - } - catch (AddressOutOfBoundsException e) { - // offset too large - } + + + try { + return targetSpace.getAddress(offset, true); + } + catch (AddressOutOfBoundsException e) { + // offset too large } return null; } @@ -503,27 +516,20 @@ public class PointerDataType extends BuiltIn implements Pointer { * @return address value returned as segmented Address object or null for * unsupported pointer length or meory access error occurs. */ - private static Address getSegmentedAddressValue(MemBuffer buf, int dataLen) { + private static Address getSegmentedAddressValue(MemBuffer buf, int dataLen, long storedOffset) { SegmentedAddress a = (SegmentedAddress) buf.getAddress(); int segment = a.getSegment(); - int offset = 0; - try { - switch (dataLen) { - case 2: // near pointer - offset = buf.getUnsignedShort(0); - break; - case 4: // far pointer - long value = buf.getUnsignedInt(0); - segment = (int) (value >> 16); - offset = (int) (value & 0xffff); - break; - default: - return null; - } - - } - catch (MemoryAccessException e) { - return null; + int offset; + switch (dataLen) { + case 2: // near pointer + offset = (int) (storedOffset & 0xffff); + break; + case 4: // far pointer + segment = (int) ((storedOffset >> 16) & 0xffff); + offset = (int) (storedOffset & 0xffff); + break; + default: + return null; } SegmentedAddressSpace space = (SegmentedAddressSpace) a.getAddressSpace(); SegmentedAddress addr = space.getAddress(segment, offset); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerTypeSettingsDefinition.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerTypeSettingsDefinition.java index 5b74e32447..89e91675ea 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerTypeSettingsDefinition.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/data/PointerTypeSettingsDefinition.java @@ -43,7 +43,8 @@ public class PointerTypeSettingsDefinition /** * Returns the format based on the specified settings * @param settings the instance settings or null for default value. - * @return the format value (HEX, DECIMAL, BINARY, OCTAL, CHAR) + * @return the {@link PointerType}. {@link PointerType#DEFAULT} will be returned + * if no setting has been made. */ public PointerType getType(Settings settings) { if (settings == null) {