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

View file

@ -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);
}

View file

@ -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;
}
/**

View file

@ -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) {

View file

@ -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();

View file

@ -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;
}
/**

View file

@ -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) {

View file

@ -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);

View file

@ -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) {