mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
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:
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();
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue