GP-1036 Improved RTTI handling of null pointer values. Changed IBO

pointers to return null for 0 value to retain backward compatibility.
Improved datatype drag onto root to preserve source category path.
This commit is contained in:
ghidra1
2022-03-15 10:59:16 -04:00
parent a02efe9c4c
commit 3acd14c48a
8 changed files with 66 additions and 40 deletions
@@ -338,6 +338,12 @@ public class DataTypeTreeCopyMoveTask extends Task {
DataTypeManager nodeDtm = dataType.getDataTypeManager(); DataTypeManager nodeDtm = dataType.getDataTypeManager();
boolean sameManager = (dtm == nodeDtm); boolean sameManager = (dtm == nodeDtm);
DataType newDt = !sameManager ? dataType.clone(nodeDtm) : dataType.copy(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())) { if (sameManager && newDt.getCategoryPath().equals(toCategory.getCategoryPath())) {
renameAsCopy(toCategory, newDt); renameAsCopy(toCategory, newDt);
} }
@@ -138,7 +138,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
try { try {
Address spareDataAddress = getSpareDataAddress(); Address spareDataAddress = getSpareDataAddress();
if (spareDataAddress != null && spareDataAddress.getOffset() != 0L && if (spareDataAddress != null && spareDataAddress.getOffset() != 0 &&
!loadedAndInitializedSet.contains(spareDataAddress)) { !loadedAndInitializedSet.contains(spareDataAddress)) {
throw new InvalidDataTypeException(getName() + " data type at " + getAddress() + throw new InvalidDataTypeException(getName() + " data type at " + getAddress() +
" doesn't point to a spare data address in a loaded and initialized memory block."); " 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; Address vfTableAddress;
// component 0 is either vf table pointer or hash value. // component 0 is either vf table pointer or hash value.
vfTableAddress = EHDataTypeUtilities.getAddress(getDataType(), VF_TABLE_OR_HASH_ORDINAL, getMemBuffer()); vfTableAddress = EHDataTypeUtilities.getAddress(getDataType(), VF_TABLE_OR_HASH_ORDINAL, getMemBuffer());
return (vfTableAddress != null && vfTableAddress.getOffset() != 0) ? vfTableAddress : null;
return vfTableAddress.getOffset() != 0 ? vfTableAddress : null;
} }
/** /**
@@ -393,7 +392,7 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel {
// component 1 is the spare data. // component 1 is the spare data.
Address spareAddress = Address spareAddress =
EHDataTypeUtilities.getAddress(getDataType(), SPARE_ORDINAL, getMemBuffer()); EHDataTypeUtilities.getAddress(getDataType(), SPARE_ORDINAL, getMemBuffer());
return spareAddress.getOffset() != 0 ? spareAddress : null; return (spareAddress != null && spareAddress.getOffset() != 0) ? spareAddress : null;
} }
/** /**
@@ -122,7 +122,7 @@ public class Rtti1Model extends AbstractCreateRttiDataModel {
// First component is either a direct reference or an image base offset. // First component is either a direct reference or an image base offset.
Address rtti0Address = getReferencedAddress(program, startAddress); Address rtti0Address = getReferencedAddress(program, startAddress);
if (rtti0Address == null) { if (rtti0Address == null) {
invalid(); // throws Exception invalid("Invalid TypeDescriptor reference (pTypeDescriptor)."); // throws Exception
} }
rtti0Model = new TypeDescriptorModel(program, rtti0Address, validationOptions); rtti0Model = new TypeDescriptorModel(program, rtti0Address, validationOptions);
if (validateReferredToData) { if (validateReferredToData) {
@@ -241,6 +241,9 @@ public class SettingsImpl implements Settings, Serializable {
@Override @Override
public void clearAllSettings() { public void clearAllSettings() {
if (map.isEmpty()) {
return;
}
if (checkSetting(null, null)) { if (checkSetting(null, null)) {
map.clear(); map.clear();
changed(); changed();
@@ -15,8 +15,8 @@
*/ */
package ghidra.program.database.data; package ghidra.program.database.data;
import ghidra.program.model.address.AddressFactory; import ghidra.docking.settings.Settings;
import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.*;
import ghidra.program.model.data.*; import ghidra.program.model.data.*;
/** /**
@@ -60,12 +60,21 @@ public class PointerTypedefInspector {
if (!pointerTypeDef.isPointer()) { if (!pointerTypeDef.isPointer()) {
return null; return null;
} }
Settings settings = pointerTypeDef.getDefaultSettings();
String spaceName = String spaceName =
AddressSpaceSettingsDefinition.DEF.getValue(pointerTypeDef.getDefaultSettings()); AddressSpaceSettingsDefinition.DEF.getValue(settings);
if (spaceName == null) { if (spaceName == null) {
return 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;
} }
/** /**
@@ -41,7 +41,9 @@ public class DataTypeMnemonicSettingsDefinition implements EnumSettingsDefinitio
/** /**
* Returns the format based on the specified settings * Returns the format based on the specified settings
* @param settings the instance 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) { public int getMnemonicStyle(Settings settings) {
if (settings == null) { if (settings == null) {
@@ -368,6 +368,7 @@ public class PointerDataType extends BuiltIn implements Pointer {
Program program = mem.getProgram(); Program program = mem.getProgram();
String spaceName = AddressSpaceSettingsDefinition.DEF.getValue(settings); String spaceName = AddressSpaceSettingsDefinition.DEF.getValue(settings);
if (spaceName != null) { if (spaceName != null) {
// this space may be ignored if pointer type specified
targetSpace = program.getAddressFactory().getAddressSpace(spaceName); targetSpace = program.getAddressFactory().getAddressSpace(spaceName);
} }
} }
@@ -377,12 +378,13 @@ public class PointerDataType extends BuiltIn implements Pointer {
} }
if (targetSpace instanceof SegmentedAddressSpace) { if (targetSpace instanceof SegmentedAddressSpace) {
// ignore other settings // ignore other settings with SegmentedAddressSpace use
return getAddressValue(buf, size, targetSpace); return getAddressValue(buf, size, targetSpace);
} }
Long offset = getStoredOffset(buf, size); Long offset = getStoredOffset(buf, size);
if (offset == null) { if (offset == null) {
// Insufficient bytes
return null; return null;
} }
@@ -403,7 +405,13 @@ public class PointerDataType extends BuiltIn implements Pointer {
try { try {
PointerType choice = PointerTypeSettingsDefinition.DEF.getType(settings); 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 (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 // must ignore AddressSpaceSettingsDefinition
Address imageBase = mem.getProgram().getImageBase(); Address imageBase = mem.getProgram().getImageBase();
targetSpace = imageBase.getAddressSpace(); targetSpace = imageBase.getAddressSpace();
@@ -464,10 +472,16 @@ public class PointerDataType extends BuiltIn implements Pointer {
return null; return null;
} }
Long offset = getStoredOffset(buf, size);
if (offset == null) {
// Insufficient bytes
return null;
}
if (targetSpace instanceof SegmentedAddressSpace) { if (targetSpace instanceof SegmentedAddressSpace) {
try { try {
// NOTE: conversion assumes a little-endian space // NOTE: conversion assumes a little-endian space
return getSegmentedAddressValue(buf, size); return getSegmentedAddressValue(buf, size, offset);
} }
catch (AddressOutOfBoundsException e) { catch (AddressOutOfBoundsException e) {
// offset too large // offset too large
@@ -482,15 +496,14 @@ public class PointerDataType extends BuiltIn implements Pointer {
return null; return null;
} }
Long offset = getStoredOffset(buf, size);
if (offset != null) {
try { try {
return targetSpace.getAddress(offset, true); return targetSpace.getAddress(offset, true);
} }
catch (AddressOutOfBoundsException e) { catch (AddressOutOfBoundsException e) {
// offset too large // offset too large
} }
}
return null; return null;
} }
@@ -503,28 +516,21 @@ public class PointerDataType extends BuiltIn implements Pointer {
* @return address value returned as segmented Address object or null for * @return address value returned as segmented Address object or null for
* unsupported pointer length or meory access error occurs. * 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(); SegmentedAddress a = (SegmentedAddress) buf.getAddress();
int segment = a.getSegment(); int segment = a.getSegment();
int offset = 0; int offset;
try {
switch (dataLen) { switch (dataLen) {
case 2: // near pointer case 2: // near pointer
offset = buf.getUnsignedShort(0); offset = (int) (storedOffset & 0xffff);
break; break;
case 4: // far pointer case 4: // far pointer
long value = buf.getUnsignedInt(0); segment = (int) ((storedOffset >> 16) & 0xffff);
segment = (int) (value >> 16); offset = (int) (storedOffset & 0xffff);
offset = (int) (value & 0xffff);
break; break;
default: default:
return null; return null;
} }
}
catch (MemoryAccessException e) {
return null;
}
SegmentedAddressSpace space = (SegmentedAddressSpace) a.getAddressSpace(); SegmentedAddressSpace space = (SegmentedAddressSpace) a.getAddressSpace();
SegmentedAddress addr = space.getAddress(segment, offset); SegmentedAddress addr = space.getAddress(segment, offset);
return normalize(addr, buf.getMemory()); return normalize(addr, buf.getMemory());
@@ -43,7 +43,8 @@ public class PointerTypeSettingsDefinition
/** /**
* Returns the format based on the specified settings * Returns the format based on the specified settings
* @param settings the instance settings or null for default value. * @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) { public PointerType getType(Settings settings) {
if (settings == null) { if (settings == null) {