mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 02:09:44 +02:00
BitFields - corrected bitfield transitions between different data
organizations and packing for unions.
This commit is contained in:
parent
486ce82586
commit
f54f68c66e
22 changed files with 352 additions and 315 deletions
|
@ -34,7 +34,7 @@ class BitFieldDBDataType extends BitFieldDataType {
|
|||
// BB - Encoded base type (8-bits, consists of the following bit fields: xttsbbbb)
|
||||
// x - 1-bit, unused
|
||||
// t - 2-bit, =0: base type only, =1:TypeDef used, =2: enum used, =3: abstract-int
|
||||
// s - 1-bit, storage +1
|
||||
// s - 1-bit, storage +1 (NOT-USED! - may be re-purposed by future schema change)
|
||||
// xxxx - 4-bits, unused
|
||||
// OO - bit offset (i.e., right-shift factor, relative to packing base type)
|
||||
// SS - bit field size in bits
|
||||
|
@ -47,10 +47,21 @@ class BitFieldDBDataType extends BitFieldDataType {
|
|||
|
||||
private static final long ID_TO_INDEX_MASK = ~-(1L << DataTypeManagerDB.DATA_TYPE_KIND_SHIFT);
|
||||
|
||||
BitFieldDBDataType(DataType baseDataType, int bitSize, int bitOffset, int storageSize,
|
||||
DataTypeManager dtm) throws InvalidDataTypeException {
|
||||
// avoid clone of baseDataType during construction
|
||||
super(baseDataType, bitSize, bitOffset, storageSize);
|
||||
/**
|
||||
* Construct DB resident bitfield. Minimal storage size and effective bit size will
|
||||
* be computed based upon specified parameters.
|
||||
* @param baseDataType base data type (integer/enum type or typedef to same). This
|
||||
* bitfield will adopt the same datatype manager as this base type.
|
||||
* @param bitSize size of bit-field expressed as number of bits (0..255). The effective
|
||||
* bit size may be reduced based upon the specified base datatype size.
|
||||
* @param bitOffset right shift factor within storage unit when viewed as a big-endian dd
|
||||
* scalar value. Based upon minimal storage bitOffset should be in the range 0 to 7.
|
||||
* @throws InvalidDataTypeException
|
||||
*/
|
||||
BitFieldDBDataType(DataType baseDataType, int bitSize, int bitOffset)
|
||||
throws InvalidDataTypeException {
|
||||
// must avoid cloning of baseDataType during construction!
|
||||
super(baseDataType, bitSize, bitOffset);
|
||||
}
|
||||
|
||||
private static enum BaseDatatypeKind {
|
||||
|
@ -137,14 +148,14 @@ class BitFieldDBDataType extends BitFieldDataType {
|
|||
* @param dtm data type manager
|
||||
* @return bit-field data type
|
||||
*/
|
||||
static final BitFieldDataType getBitFieldDataType(long id, DataTypeManager dtm) {
|
||||
static final BitFieldDataType getBitFieldDataType(long id, DataTypeManagerDB dtm) {
|
||||
|
||||
int bitSize = (int) (id & 0xff); // 8-bits
|
||||
int bitOffset = (int) ((id >> BIT_OFFSET_SHIFT) & 0xff); // 8-bits
|
||||
int baseTypeInfo = (int) ((id >> BASE_TYPE_SHIFT) & 0xff); // 8-bit encoded field
|
||||
|
||||
BaseDatatypeKind baseDataTypeKind = BaseDatatypeKind.getKind((baseTypeInfo >> 5) & 3);
|
||||
boolean extraStorageUsed = (baseTypeInfo & 0x10) != 0;
|
||||
// boolean extraStorageUsed = (baseTypeInfo & 0x10) != 0;
|
||||
|
||||
DataType baseDataType = null;
|
||||
long dataTypeIndex = (id >> DATATYPE_INDEX_SHIFT) & MAX_DATATYPE_INDEX; // 32-bits
|
||||
|
@ -164,12 +175,12 @@ class BitFieldDBDataType extends BitFieldDataType {
|
|||
// use integer datatype on failure
|
||||
baseDataType = IntegerDataType.dataType.clone(dtm);
|
||||
}
|
||||
int effectiveBitSize = getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
int storageSize = getMinimumStorageSize(effectiveBitSize);
|
||||
if (extraStorageUsed) {
|
||||
++storageSize;
|
||||
}
|
||||
return new BitFieldDBDataType(baseDataType, bitSize, bitOffset, storageSize, dtm);
|
||||
// int effectiveBitSize = getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
// int storageSize = getMinimumStorageSize(effectiveBitSize);
|
||||
// if (extraStorageUsed) {
|
||||
// ++storageSize;
|
||||
// }
|
||||
return new BitFieldDBDataType(baseDataType, bitSize, bitOffset);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
return null;
|
||||
|
|
|
@ -104,13 +104,6 @@ abstract class CompositeDB extends DataTypeDB implements Composite {
|
|||
return record.getLongValue(CompositeDBAdapter.COMPOSITE_CAT_COL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0, 0, dataMgr);
|
||||
return add(bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle replacement of datatype which may impact bitfield datatype.
|
||||
* @param bitfieldComponent bitfield component
|
||||
|
@ -140,9 +133,8 @@ abstract class CompositeDB extends DataTypeDB implements Composite {
|
|||
}
|
||||
|
||||
try {
|
||||
BitFieldDBDataType newBitfieldDt =
|
||||
new BitFieldDBDataType(newDt, bitfieldDt.getDeclaredBitSize(),
|
||||
bitfieldDt.getBitOffset(), bitfieldDt.getStorageSize(), dataMgr);
|
||||
BitFieldDBDataType newBitfieldDt = new BitFieldDBDataType(newDt,
|
||||
bitfieldDt.getDeclaredBitSize(), bitfieldDt.getBitOffset());
|
||||
bitfieldComponent.setDataType(newBitfieldDt);
|
||||
oldDt.removeParent(this);
|
||||
newDt.addParent(this);
|
||||
|
|
|
@ -790,7 +790,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
|||
storageSize = baseLength;
|
||||
}
|
||||
try {
|
||||
return new BitFieldDBDataType(resolvedBaseDt, bitSize, bitOffset, storageSize, this);
|
||||
return new BitFieldDBDataType(resolvedBaseDt, bitSize, bitOffset);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
throw new AssertException("unexpected", e);
|
||||
|
|
|
@ -276,6 +276,17 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
|
||||
BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0);
|
||||
return add(bitFieldDt, componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
|
@ -298,8 +309,7 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
}
|
||||
|
||||
// handle aligned bitfield insertion
|
||||
BitFieldDataType bitFieldDt =
|
||||
new BitFieldDBDataType(baseDataType, bitSize, 0, 0, dataMgr);
|
||||
BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0);
|
||||
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
finally {
|
||||
|
@ -315,7 +325,7 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
try {
|
||||
checkDeleted();
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
if (byteOffset < 0 || bitSize < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -405,11 +415,8 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
structLength = requiredLength;
|
||||
}
|
||||
|
||||
// use minimal storage
|
||||
// adjust for minimal storage use
|
||||
int storageBitOffset = bitOffset % 8;
|
||||
int storageSize =
|
||||
BitFieldDataType.getMinimumStorageSize(effectiveBitSize + storageBitOffset);
|
||||
|
||||
int revisedOffset;
|
||||
if (bigEndian) {
|
||||
revisedOffset = byteOffset + byteWidth - ((effectiveBitSize + bitOffset + 7) / 8);
|
||||
|
@ -418,11 +425,11 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
revisedOffset = byteOffset + (bitOffset / 8);
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt = new BitFieldDBDataType(baseDataType, bitSize,
|
||||
storageBitOffset, storageSize, getDataTypeManager());
|
||||
BitFieldDataType bitfieldDt =
|
||||
new BitFieldDBDataType(baseDataType, bitSize, storageBitOffset);
|
||||
|
||||
Record rec = componentAdapter.createRecord(dataMgr.getResolvedID(bitfieldDt), key,
|
||||
storageSize, ordinal, revisedOffset, componentName, comment);
|
||||
bitfieldDt.getStorageSize(), ordinal, revisedOffset, componentName, comment);
|
||||
DataTypeComponentDB dtc = new DataTypeComponentDB(dataMgr, componentAdapter, this, rec);
|
||||
bitfieldDt.addParent(this); // has no affect
|
||||
components.add(startIndex, dtc);
|
||||
|
@ -1513,13 +1520,13 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
try {
|
||||
validateDataType(replacementDt);
|
||||
if (!(replacementDt instanceof DataTypeDB) ||
|
||||
(replacementDt.getDataTypeManager() != getDataTypeManager())) {
|
||||
(replacementDt.getDataTypeManager() != dataMgr)) {
|
||||
replacementDt = resolve(replacementDt);
|
||||
}
|
||||
checkAncestry(replacementDt);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO: should we use Undefined instead to avoid cases where
|
||||
// TODO: should we use Undefined1 instead to avoid cases where
|
||||
// DEFAULT datatype can not be used (flex array, bitfield, aligned structure)
|
||||
// TODO: failing silently is rather hidden
|
||||
replacementDt = DataType.DEFAULT;
|
||||
|
|
|
@ -121,6 +121,8 @@ class UnionDB extends CompositeDB implements Union {
|
|||
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = adjustBitField(dataType);
|
||||
|
||||
dataType = resolve(dataType);
|
||||
checkAncestry(dataType);
|
||||
|
||||
|
@ -165,6 +167,8 @@ class UnionDB extends CompositeDB implements Union {
|
|||
checkDeleted();
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = adjustBitField(dataType);
|
||||
|
||||
dataType = resolve(dataType);
|
||||
checkAncestry(dataType);
|
||||
|
||||
|
@ -185,53 +189,22 @@ class UnionDB extends CompositeDB implements Union {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
return insertBitField(components.size(), baseDataType, bitSize, componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize,
|
||||
String componentName, String comment)
|
||||
throws InvalidDataTypeException, ArrayIndexOutOfBoundsException {
|
||||
|
||||
if (ordinal < 0 || ordinal > components.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException(ordinal);
|
||||
}
|
||||
|
||||
if (isInternallyAligned()) {
|
||||
BitFieldDataType bitFieldDt =
|
||||
new BitFieldDBDataType(baseDataType, bitSize, 0, 0, dataMgr);
|
||||
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
if (byteWidth <= 0) {
|
||||
throw new IllegalArgumentException("Invalid byteWidth");
|
||||
}
|
||||
|
||||
// handle unaligned case - use minimal storage
|
||||
// bitfield value will be forced based upon byteWidth, bitSize and endianess
|
||||
boolean bigEndian = getDataOrganization().isBigEndian();
|
||||
int effectiveBitSize =
|
||||
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(effectiveBitSize);
|
||||
if (byteWidth < storageSize) {
|
||||
throw new IllegalArgumentException(
|
||||
"Bitfield does not fit within specified constraints");
|
||||
}
|
||||
int storageBitOffset = 0;
|
||||
if (bigEndian) {
|
||||
storageBitOffset = (8 * storageSize) - effectiveBitSize;
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt = new BitFieldDBDataType(baseDataType, bitSize,
|
||||
storageBitOffset, storageSize, getDataTypeManager());
|
||||
|
||||
DataTypeComponentDB dtc = createComponent(dataMgr.getResolvedID(bitfieldDt), storageSize,
|
||||
ordinal, 0, componentName, comment);
|
||||
|
||||
bitfieldDt.addParent(this); // currently has no affect
|
||||
|
||||
shiftOrdinals(ordinal, 1);
|
||||
components.add(ordinal, dtc);
|
||||
|
||||
adjustLength(true, true);
|
||||
|
||||
return dtc;
|
||||
BitFieldDataType bitFieldDt = new BitFieldDBDataType(baseDataType, bitSize, 0);
|
||||
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -434,6 +407,51 @@ class UnionDB extends CompositeDB implements Union {
|
|||
adjustInternalAlignment(true);
|
||||
}
|
||||
|
||||
private DataType adjustBitField(DataType dataType) {
|
||||
|
||||
if (!(dataType instanceof BitFieldDataType)) {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt = (BitFieldDataType) dataType;
|
||||
|
||||
DataType baseDataType = bitfieldDt.getBaseDataType();
|
||||
baseDataType = resolve(baseDataType);
|
||||
|
||||
// Both aligned and unaligned bitfields use same adjustment
|
||||
// unaligned must force bitfield placement at byte offset 0
|
||||
int bitSize = bitfieldDt.getDeclaredBitSize();
|
||||
int effectiveBitSize =
|
||||
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
|
||||
// little-endian always uses bit offset of 0 while
|
||||
// big-endian offset must be computed
|
||||
boolean bigEndian = getDataOrganization().isBigEndian();
|
||||
int storageBitOffset = 0;
|
||||
if (bigEndian) {
|
||||
if (bitSize == 0) {
|
||||
storageBitOffset = 7;
|
||||
}
|
||||
else {
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(effectiveBitSize);
|
||||
storageBitOffset = (8 * storageSize) - effectiveBitSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (effectiveBitSize != bitfieldDt.getBitSize() ||
|
||||
storageBitOffset != bitfieldDt.getBitOffset()) {
|
||||
try {
|
||||
bitfieldDt =
|
||||
new BitFieldDBDataType(baseDataType, effectiveBitSize, storageBitOffset);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
// unexpected since deriving from existing bitfield,
|
||||
// ignore and use existing bitfield
|
||||
}
|
||||
}
|
||||
return bitfieldDt;
|
||||
}
|
||||
|
||||
private void adjustLength(boolean notify, boolean setLastChangeTime) {
|
||||
lock.acquire();
|
||||
try {
|
||||
|
|
|
@ -202,7 +202,7 @@ public class AlignedStructurePacker {
|
|||
zeroBitFieldDt.getStorageSize() != 1) {
|
||||
try {
|
||||
BitFieldDataType packedBitFieldDt = new BitFieldDataType(
|
||||
zeroBitFieldDt.getBaseDataType(), 0, zeroBitOffset, 1);
|
||||
zeroBitFieldDt.getBaseDataType(), 0, zeroBitOffset);
|
||||
dataTypeComponent.setDataType(packedBitFieldDt);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
|
@ -451,12 +451,11 @@ public class AlignedStructurePacker {
|
|||
bitOffset = bitsConsumed;
|
||||
}
|
||||
|
||||
if (bitOffset != currentBitFieldDt.getBitOffset() ||
|
||||
byteSize != currentBitFieldDt.getStorageSize()) {
|
||||
if (bitOffset != currentBitFieldDt.getBitOffset()) {
|
||||
try {
|
||||
BitFieldDataType packedBitFieldDt =
|
||||
new BitFieldDataType(currentBitFieldDt.getBaseDataType(),
|
||||
currentBitFieldDt.getDeclaredBitSize(), bitOffset, byteSize);
|
||||
currentBitFieldDt.getDeclaredBitSize(), bitOffset);
|
||||
dataTypeComponent.setDataType(packedBitFieldDt);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
|
|
|
@ -44,24 +44,23 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
// The bitOffset is established during packing and reflects the right-shift amount within the
|
||||
// normalized big-endian view of the allocated byte storage as defined by the corresponding
|
||||
// composite DataTypeComponent.
|
||||
private final int bitOffset; // indicates right-shift within big-endian view of component storage
|
||||
private final int storageSize; // component storage size to which bitOffset applies
|
||||
private final int bitOffset; // indicates right-shift within big-endian view of component storage (range: 0..7)
|
||||
private final int storageSize; // minimal component storage size to which bitOffset applies
|
||||
|
||||
protected Settings defaultSettings;
|
||||
|
||||
/**
|
||||
* Construct a bit-field type based upon a specified base type. The baseDataType will
|
||||
* take precedence if specified. Either baseType or baseDatatype must be specified.
|
||||
* @param baseDataType base data type (integer/enum type or typedef to same)
|
||||
* @param bitSize size of bit-field expressed as number of bits
|
||||
* @param baseDataType base data type (integer/enum type or typedef to same). This
|
||||
* bitfield will adopt the same datatype manager as this base type.
|
||||
* @param bitSize size of bit-field expressed as number of bits (0..255). The effective
|
||||
* bit size may be reduced based upon the specified base datatype size.
|
||||
* @param bitOffset right shift factor within storage unit when viewed as a big-endian dd
|
||||
* scalar value. Based upon minimal storage bitOffset should be in the range 0 to 7.
|
||||
* @param storageSize minimal storage allocation to which bitOffset is applied or 0 to use
|
||||
* minimum storage size.
|
||||
* @throws InvalidDataTypeException
|
||||
*/
|
||||
// FIXME: Remove storage parameter (compute based upon bitSize and bitOffset)
|
||||
protected BitFieldDataType(DataType baseDataType, int bitSize, int bitOffset, int storageSize)
|
||||
protected BitFieldDataType(DataType baseDataType, int bitSize, int bitOffset)
|
||||
throws InvalidDataTypeException {
|
||||
super(CategoryPath.ROOT, baseDataType.getName() + ":" + bitSize,
|
||||
baseDataType.getDataTypeManager());
|
||||
|
@ -76,14 +75,7 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
this.bitSize = bitSize;
|
||||
this.bitOffset = bitOffset;
|
||||
effectiveBitSize = getEffectiveBitSize(bitSize, this.baseDataType.getLength());
|
||||
if (storageSize == 0) {
|
||||
storageSize = getMinimumStorageSize(effectiveBitSize, bitOffset);
|
||||
}
|
||||
this.storageSize = storageSize;
|
||||
checkStorage();
|
||||
if (bitOffset < 0 || bitOffset > ((8 * storageSize) - effectiveBitSize)) {
|
||||
throw new InvalidDataTypeException("invalid bit offset: " + bitOffset);
|
||||
}
|
||||
storageSize = getMinimumStorageSize(effectiveBitSize, bitOffset);
|
||||
this.defaultSettings = this.baseDataType.getDefaultSettings();
|
||||
}
|
||||
|
||||
|
@ -95,14 +87,7 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
* @throws InvalidDataTypeException if specified baseDataType is not permitted
|
||||
*/
|
||||
protected BitFieldDataType(DataType baseDataType, int bitSize) throws InvalidDataTypeException {
|
||||
this(baseDataType, bitSize, 0, 0);
|
||||
}
|
||||
|
||||
private void checkStorage() throws IllegalArgumentException {
|
||||
int minimumStorageSize = getMinimumStorageSize(effectiveBitSize);
|
||||
if (storageSize != minimumStorageSize && storageSize != ++minimumStorageSize) {
|
||||
throw new IllegalArgumentException("minimal storage size required");
|
||||
}
|
||||
this(baseDataType, bitSize, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,6 +182,7 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
/**
|
||||
* Get the packing storage size in bytes associated with this bit-field which may be
|
||||
* larger than the base type associated with the fields original definition.
|
||||
* Returned value is the same as {@link #getLength()}.
|
||||
* @return packing storage size in bytes
|
||||
*/
|
||||
public int getStorageSize() {
|
||||
|
@ -320,13 +306,20 @@ public class BitFieldDataType extends AbstractDataType {
|
|||
return clone(dtm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this bitfield to a new datatype manager. This may change the effective bit
|
||||
* size and storage size of the resulting datatype based upon the data organization
|
||||
* of the specified dtm.
|
||||
* @param dtm target datatype manager
|
||||
* @return new instance or same instance of dtm is unchanged.
|
||||
*/
|
||||
@Override
|
||||
public BitFieldDataType clone(DataTypeManager dtm) {
|
||||
if (dtm == dataMgr) {
|
||||
return this;
|
||||
}
|
||||
try {
|
||||
return new BitFieldDataType(baseDataType.clone(dtm), bitSize, bitOffset, storageSize);
|
||||
return new BitFieldDataType(baseDataType.clone(dtm), bitSize, bitOffset);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
throw new AssertException("unexpected", e);
|
||||
|
|
|
@ -201,44 +201,6 @@ public interface Composite extends DataType {
|
|||
*/
|
||||
public DataTypeComponent insert(int ordinal, DataType dataType, int length);
|
||||
|
||||
/**
|
||||
* Inserts a new bitfield at the specified ordinal position in this composite.
|
||||
* Within aligned composites and unions the specified byteWidth and bitOffset will be
|
||||
* ignored.
|
||||
* The component length will be computed based upon the specified parameters and will
|
||||
* be reduced from byteWidth to its minimal size for the new component.
|
||||
* <p>
|
||||
* For unaligned structures, a component shift will only occur if the bitfield placement
|
||||
* conflicts with another component. If no conflict occurs, the bitfield will be placed
|
||||
* at the specified location consuming any DEFAULT components as needed. When a conflict
|
||||
* does occur a shift will be performed at the ordinal position based upon the specified
|
||||
* byteWidth. When located onto existing bitfields they will be packed together
|
||||
* provided they do not conflict, otherwise the conflict rule above applies.
|
||||
* <p>
|
||||
* Supported packing for little-endian fills lsb first, whereas big-endian fills msb first.
|
||||
* Insertion behavior may not work as expected if packing rules differ from this.
|
||||
* @param ordinal the ordinal where the new datatype is to be inserted.
|
||||
* @param byteWidth the storage unit width which contains the bitfield. Must be large
|
||||
* enough to contain the specified bitSize and corresponding bitOffset. The actual
|
||||
* component size used will be recomputed during insertion.
|
||||
* @param bitOffset corresponds to the bitfield left-shift amount with the storage
|
||||
* unit when viewed as big-endian. The final offset may be reduced based upon
|
||||
* the minimal storage size determined during insertion.
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the bitfield size in bits
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the componentDataType created whose associated data type will
|
||||
* be BitFieldDataType.
|
||||
* @throws InvalidDataTypeException if the specified data type is
|
||||
* not a valid base type for bitfields.
|
||||
* @throws ArrayIndexOutOfBoundsException if ordinal is less than 0 or greater than the
|
||||
* current number of components.
|
||||
*/
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
throws InvalidDataTypeException, ArrayIndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Inserts a new datatype at the specified ordinal position in this composite.
|
||||
* <BR>Note: For an aligned structure the ordinal position will get adjusted
|
||||
|
|
|
@ -17,34 +17,6 @@ package ghidra.program.model.data;
|
|||
|
||||
public class CompositeAlignmentHelper {
|
||||
|
||||
private static int getImpartedAlignment(DataOrganization dataOrganization, int packingAlignment,
|
||||
DataTypeComponent dataTypeComponent) {
|
||||
|
||||
// FIXME: try to eliminate this method.
|
||||
|
||||
// DataType componentDt = dataTypeComponent.getDataType();
|
||||
//
|
||||
// if (componentDt instanceof BitFieldDataType) {
|
||||
// BitFieldPacking bitFieldPacking = dataOrganization.getBitFieldPacking();
|
||||
// if (!bitFieldPacking.isTypeAlignmentEnabled() ||
|
||||
// isBitFieldPackingEnabled(dataOrganization, packingAlignment)) {
|
||||
// return 0;
|
||||
// }
|
||||
// BitFieldDataType bitFieldDt = (BitFieldDataType) componentDt;
|
||||
// // zero-length bitfield assumed not to influence composite alignment, only component alignment
|
||||
// if (!bitFieldPacking.zeroLengthAffectsContainerAlignment() &&
|
||||
// bitFieldDt.getBitSize() == 0) {
|
||||
// return 0;
|
||||
// }
|
||||
// // largest bit-field base-type will provide composite alignment constraint
|
||||
// return getPackedAlignment(dataOrganization, packingAlignment,
|
||||
// bitFieldDt.getBaseDataType(), bitFieldDt.getBaseTypeSize());
|
||||
// }
|
||||
|
||||
return CompositeAlignmentHelper.getPackedAlignment(dataOrganization, packingAlignment,
|
||||
dataTypeComponent);
|
||||
}
|
||||
|
||||
private static int getCompositeAlignmentMultiple(DataOrganization dataOrganization,
|
||||
Composite composite) {
|
||||
int allComponentsLCM = 1;
|
||||
|
@ -140,4 +112,5 @@ public class CompositeAlignmentHelper {
|
|||
return ((absoluteMaxAlignment == 0) || (lcm < absoluteMaxAlignment)) ? lcm
|
||||
: absoluteMaxAlignment;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -141,17 +141,6 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
|
||||
BitFieldDataType bitFieldDt = new BitFieldDataType(baseDataType, bitSize);
|
||||
return add(bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle replacement of datatype which may impact bitfield datatype.
|
||||
* @param bitfieldComponent bitfield component
|
||||
|
@ -180,9 +169,8 @@ public abstract class CompositeDataTypeImpl extends GenericDataType implements C
|
|||
}
|
||||
|
||||
try {
|
||||
BitFieldDataType newBitfieldDt =
|
||||
new BitFieldDataType(newDt, bitfieldDt.getDeclaredBitSize(),
|
||||
bitfieldDt.getBitOffset(), bitfieldDt.getStorageSize());
|
||||
BitFieldDataType newBitfieldDt = new BitFieldDataType(newDt,
|
||||
bitfieldDt.getDeclaredBitSize(), bitfieldDt.getBitOffset());
|
||||
bitfieldComponent.setDataType(newBitfieldDt);
|
||||
oldDt.removeParent(this);
|
||||
newDt.addParent(this);
|
||||
|
|
|
@ -66,6 +66,46 @@ public interface Structure extends Composite {
|
|||
*/
|
||||
public abstract DataTypeComponent getDataTypeAt(int offset);
|
||||
|
||||
/**
|
||||
* Inserts a new bitfield at the specified ordinal position in this structure.
|
||||
* Within aligned structures the specified byteWidth and bitOffset will be
|
||||
* ignored since packing will occur at the specified ordinal position.
|
||||
* The resulting component length and bitfield details will reflect the use
|
||||
* of minimal storage sizing.
|
||||
* <p>
|
||||
* For unaligned structures, a component shift will only occur if the bitfield placement
|
||||
* conflicts with another component. If no conflict occurs, the bitfield will be placed
|
||||
* at the specified location consuming any DEFAULT components as needed. When a conflict
|
||||
* does occur a shift will be performed at the ordinal position based upon the specified
|
||||
* byteWidth. When located onto existing bitfields they will be packed together
|
||||
* provided they do not conflict, otherwise the conflict rule above applies.
|
||||
* <p>
|
||||
* Supported aligned packing starts with bit-0 (lsb) of the first byte for little-endian, and
|
||||
* with bit-7 (msb) of the first byte for big-endian. This is the default behavior for most
|
||||
* compilers. Insertion behavior may not work as expected if packing rules differ from this.
|
||||
* @param ordinal the ordinal where the new datatype is to be inserted.
|
||||
* @param byteWidth the storage allocation unit width which contains the bitfield. Must be large
|
||||
* enough to contain the "effective bit size" and corresponding bitOffset. The actual
|
||||
* component size used will be recomputed during insertion.
|
||||
* @param bitOffset corresponds to the bitfield left-shift amount with the storage
|
||||
* unit when viewed as big-endian. The final offset may be reduced based upon
|
||||
* the minimal storage size determined during insertion.
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the declared bitfield size in bits. The effective bit size may be
|
||||
* adjusted based upon the specified baseDataType.
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the bitfield component created whose associated data type will
|
||||
* be BitFieldDataType.
|
||||
* @throws InvalidDataTypeException if the specified baseDataType is
|
||||
* not a valid base type for bitfields.
|
||||
* @throws ArrayIndexOutOfBoundsException if ordinal is less than 0 or greater than the
|
||||
* current number of components.
|
||||
*/
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
throws InvalidDataTypeException, ArrayIndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Inserts a new bitfield at the specified location in this composite.
|
||||
* This method is intended to be used with unaligned structures where
|
||||
|
|
|
@ -297,7 +297,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
}
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
if ((offset > structLength) && !isInternallyAligned()) {
|
||||
|
@ -369,7 +369,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
DataTypeComponentImpl dtc;
|
||||
|
@ -437,7 +437,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
}
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
int idx;
|
||||
|
@ -481,6 +481,17 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
return dtc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
BitFieldDataType bitFieldDt = new BitFieldDataType(baseDataType, bitSize);
|
||||
return add(bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
|
@ -491,7 +502,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
}
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
if (!isInternallyAligned()) {
|
||||
int offset = structLength;
|
||||
|
@ -521,7 +532,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
}
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
int effectiveBitSize =
|
||||
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
|
@ -602,11 +613,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
structLength = requiredLength;
|
||||
}
|
||||
|
||||
// use minimal storage
|
||||
// adjust for minimal storage use
|
||||
int storageBitOffset = bitOffset % 8;
|
||||
int storageSize =
|
||||
BitFieldDataType.getMinimumStorageSize(effectiveBitSize + storageBitOffset);
|
||||
|
||||
int revisedOffset;
|
||||
if (bigEndian) {
|
||||
revisedOffset = byteOffset + byteWidth - ((effectiveBitSize + bitOffset + 7) / 8);
|
||||
|
@ -615,11 +623,10 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
revisedOffset = byteOffset + (bitOffset / 8);
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt =
|
||||
new BitFieldDataType(baseDataType, bitSize, storageBitOffset, storageSize);
|
||||
BitFieldDataType bitfieldDt = new BitFieldDataType(baseDataType, bitSize, storageBitOffset);
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(bitfieldDt, this, storageSize,
|
||||
ordinal, revisedOffset, componentName, comment);
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(bitfieldDt, this,
|
||||
bitfieldDt.getStorageSize(), ordinal, revisedOffset, componentName, comment);
|
||||
bitfieldDt.addParent(this); // currently has no affect
|
||||
|
||||
components.add(startIndex, dtc);
|
||||
|
@ -845,7 +852,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
if (getDataTypeManager() == dtm) {
|
||||
if (dataMgr == dtm) {
|
||||
return this;
|
||||
}
|
||||
StructureDataType struct =
|
||||
|
@ -991,13 +998,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
DataType newDt = replacementDt;
|
||||
try {
|
||||
validateDataType(replacementDt);
|
||||
if (replacementDt.getDataTypeManager() != getDataTypeManager()) {
|
||||
if (replacementDt.getDataTypeManager() != dataMgr) {
|
||||
replacementDt = replacementDt.clone(dataMgr);
|
||||
}
|
||||
checkAncestry(replacementDt);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// TODO: should we use Undefined instead to avoid cases where
|
||||
// TODO: should we use Undefined1 instead to avoid cases where
|
||||
// DEFAULT datatype can not be used (flex array, bitfield, aligned structure)
|
||||
// TODO: failing silently is rather hidden
|
||||
replacementDt = DataType.DEFAULT;
|
||||
|
@ -1130,7 +1137,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
return getComponent(index);
|
||||
}
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
@ -1173,7 +1180,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
return getComponent(ordinal);
|
||||
}
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
|
|
@ -20,4 +20,26 @@ package ghidra.program.model.data;
|
|||
*/
|
||||
public interface Union extends Composite {
|
||||
|
||||
/**
|
||||
* Inserts a new bitfield at the specified ordinal position in this union.
|
||||
* For both aligned and unaligned unions the bitfield starts with bit-0 (lsb) of the first byte
|
||||
* for little-endian, and with bit-7 (msb) of the first byte for big-endian. This is the
|
||||
* default behavior for most compilers. Insertion behavior may not work as expected if
|
||||
* packing rules differ from this.
|
||||
* @param ordinal the ordinal where the new datatype is to be inserted.
|
||||
* @param baseDataType the bitfield base datatype (certain restrictions apply).
|
||||
* @param bitSize the declared bitfield size in bits. The effective bit size may be
|
||||
* adjusted based upon the specified baseDataType.
|
||||
* @param componentName the field name to associate with this component.
|
||||
* @param comment the comment to associate with this component.
|
||||
* @return the bitfield component created whose associated data type will
|
||||
* be BitFieldDataType.
|
||||
* @throws InvalidDataTypeException if the specified baseDataType is
|
||||
* not a valid base type for bitfields.
|
||||
* @throws ArrayIndexOutOfBoundsException if ordinal is less than 0 or greater than the
|
||||
* current number of components.
|
||||
*/
|
||||
public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize,
|
||||
String componentName, String comment)
|
||||
throws InvalidDataTypeException, ArrayIndexOutOfBoundsException;
|
||||
}
|
||||
|
|
|
@ -129,7 +129,9 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = adjustBitField(dataType);
|
||||
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
@ -148,7 +150,9 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(getDataTypeManager());
|
||||
dataType = adjustBitField(dataType);
|
||||
|
||||
dataType = dataType.clone(dataMgr);
|
||||
checkAncestry(dataType);
|
||||
|
||||
length = getPreferredComponentLength(dataType, length);
|
||||
|
@ -164,8 +168,14 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
public DataTypeComponent addBitField(DataType baseDataType, int bitSize, String componentName,
|
||||
String comment) throws InvalidDataTypeException {
|
||||
return insertBitField(components.size(), baseDataType, bitSize, componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitField(int ordinal, DataType baseDataType, int bitSize,
|
||||
String componentName, String comment)
|
||||
throws InvalidDataTypeException, ArrayIndexOutOfBoundsException {
|
||||
|
||||
if (ordinal < 0 || ordinal > components.size()) {
|
||||
|
@ -173,48 +183,10 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
}
|
||||
|
||||
BitFieldDataType.checkBaseDataType(baseDataType);
|
||||
baseDataType = baseDataType.clone(getDataTypeManager());
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
if (isInternallyAligned()) {
|
||||
BitFieldDataType bitFieldDt = new BitFieldDataType(baseDataType, bitSize);
|
||||
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
if (byteWidth <= 0) {
|
||||
throw new IllegalArgumentException("Invalid byteWidth");
|
||||
}
|
||||
|
||||
// TODO: How should zero-length bitfields be handled ?
|
||||
|
||||
// handle unaligned case - use minimal storage
|
||||
// bitfield value will be forced based upon byteWidth, bitSize and endianess
|
||||
boolean bigEndian = getDataOrganization().isBigEndian();
|
||||
int effectiveBitSize =
|
||||
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(effectiveBitSize);
|
||||
if (byteWidth < storageSize) {
|
||||
throw new IllegalArgumentException(
|
||||
"Bitfield does not fit within specified constraints");
|
||||
}
|
||||
int storageBitOffset = 0;
|
||||
if (bigEndian) {
|
||||
storageBitOffset = (8 * storageSize) - effectiveBitSize;
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt =
|
||||
new BitFieldDataType(baseDataType, bitSize, storageBitOffset, storageSize);
|
||||
|
||||
DataTypeComponentImpl dtc = new DataTypeComponentImpl(bitfieldDt, this, storageSize,
|
||||
ordinal, 0, componentName, comment);
|
||||
|
||||
bitfieldDt.addParent(this); // currently has no affect
|
||||
|
||||
shiftOrdinals(ordinal, 1);
|
||||
components.add(ordinal, dtc);
|
||||
|
||||
adjustLength(true);
|
||||
|
||||
return dtc;
|
||||
BitFieldDataType bitFieldDt = new BitFieldDataType(baseDataType, bitSize);
|
||||
return insert(ordinal, bitFieldDt, bitFieldDt.getStorageSize(), componentName, comment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -227,7 +199,7 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
if (getDataTypeManager() == dtm) {
|
||||
if (dataMgr == dtm) {
|
||||
return this;
|
||||
}
|
||||
UnionDataType union = new UnionDataType(getCategoryPath(), getName(), getUniversalID(),
|
||||
|
@ -260,6 +232,50 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
}
|
||||
}
|
||||
|
||||
private DataType adjustBitField(DataType dataType) {
|
||||
|
||||
if (!(dataType instanceof BitFieldDataType)) {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
BitFieldDataType bitfieldDt = (BitFieldDataType) dataType;
|
||||
|
||||
DataType baseDataType = bitfieldDt.getBaseDataType();
|
||||
baseDataType = baseDataType.clone(dataMgr);
|
||||
|
||||
// Both aligned and unaligned bitfields use same adjustment
|
||||
// unaligned must force bitfield placement at byte offset 0
|
||||
int bitSize = bitfieldDt.getDeclaredBitSize();
|
||||
int effectiveBitSize =
|
||||
BitFieldDataType.getEffectiveBitSize(bitSize, baseDataType.getLength());
|
||||
|
||||
// little-endian always uses bit offset of 0 while
|
||||
// big-endian offset must be computed
|
||||
boolean bigEndian = getDataOrganization().isBigEndian();
|
||||
int storageBitOffset = 0;
|
||||
if (bigEndian) {
|
||||
if (bitSize == 0) {
|
||||
storageBitOffset = 7;
|
||||
}
|
||||
else {
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(effectiveBitSize);
|
||||
storageBitOffset = (8 * storageSize) - effectiveBitSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (effectiveBitSize != bitfieldDt.getBitSize() ||
|
||||
storageBitOffset != bitfieldDt.getBitOffset()) {
|
||||
try {
|
||||
bitfieldDt = new BitFieldDataType(baseDataType, effectiveBitSize, storageBitOffset);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
// unexpected since deriving from existing bitfield,
|
||||
// ignore and use existing bitfield
|
||||
}
|
||||
}
|
||||
return bitfieldDt;
|
||||
}
|
||||
|
||||
private void adjustLength(boolean notify) {
|
||||
int oldLength = unionLength;
|
||||
unionLength = 0;
|
||||
|
@ -496,4 +512,5 @@ public class UnionDataType extends CompositeDataTypeImpl implements Union {
|
|||
public void adjustInternalAlignment() {
|
||||
adjustLength(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import ghidra.program.model.data.*;
|
|||
|
||||
public class BitFieldDBDataTypeTest extends AbstractGTest {
|
||||
|
||||
private DataTypeManager dataMgr;
|
||||
private DataTypeManagerDB dataMgr;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
|
@ -36,29 +36,29 @@ public class BitFieldDBDataTypeTest extends AbstractGTest {
|
|||
@Test
|
||||
public void testGetIdAndGetDataTypeFromId() throws Exception {
|
||||
|
||||
testRoundTrip(new BitFieldDBDataType(CharDataType.dataType, 1, 4, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(CharDataType.dataType, 2, 6, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(ShortDataType.dataType, 3, 2, 2, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedShortDataType.dataType, 4, 4, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(IntegerDataType.dataType, 5, 7, 2, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedIntegerDataType.dataType, 14, 2, 3, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(LongDataType.dataType, 27, 2, 5, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedLongDataType.dataType, 6, 0, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(LongLongDataType.dataType, 6, 2, 2, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedLongLongDataType.dataType, 6, 2, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(CharDataType.dataType, 1, 4));
|
||||
testRoundTrip(new BitFieldDBDataType(CharDataType.dataType, 2, 6));
|
||||
testRoundTrip(new BitFieldDBDataType(ShortDataType.dataType, 3, 2));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedShortDataType.dataType, 4, 4));
|
||||
testRoundTrip(new BitFieldDBDataType(IntegerDataType.dataType, 5, 7));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedIntegerDataType.dataType, 14, 2));
|
||||
testRoundTrip(new BitFieldDBDataType(LongDataType.dataType, 27, 2));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedLongDataType.dataType, 6, 0));
|
||||
testRoundTrip(new BitFieldDBDataType(LongLongDataType.dataType, 6, 2));
|
||||
testRoundTrip(new BitFieldDBDataType(UnsignedLongLongDataType.dataType, 6, 2));
|
||||
|
||||
// non-standard integer base types
|
||||
testRoundTrip(new BitFieldDBDataType(ByteDataType.dataType, 6, 2, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(QWordDataType.dataType, 6, 2, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(ByteDataType.dataType, 6, 2));
|
||||
testRoundTrip(new BitFieldDBDataType(QWordDataType.dataType, 6, 2));
|
||||
|
||||
// TypeDef base types
|
||||
TypeDef foo = new TypedefDataType("foo", IntegerDataType.dataType);
|
||||
testRoundTrip(new BitFieldDBDataType(foo, 6, 3, 2, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(foo, 6, 3));
|
||||
|
||||
// Enum base types
|
||||
EnumDataType fum = new EnumDataType("fum", 4);
|
||||
fum.add("A", 1);
|
||||
testRoundTrip(new BitFieldDBDataType(fum, 6, 2, 1, dataMgr));
|
||||
testRoundTrip(new BitFieldDBDataType(fum, 6, 2));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ public class UnionDBTest extends AbstractGTest {
|
|||
union.delete(0);
|
||||
}
|
||||
// NOTE: bitOffset ignored for union
|
||||
union.insertBitField(0, 4, 12, IntegerDataType.dataType, 2, "bf1", "bf1Comment");
|
||||
union.insertBitField(0, IntegerDataType.dataType, 2, "bf1", "bf1Comment");
|
||||
union.insert(0, ShortDataType.dataType);
|
||||
|
||||
//@formatter:off
|
||||
|
@ -185,7 +185,7 @@ public class UnionDBTest extends AbstractGTest {
|
|||
for (int i = 0; i < cnt; i++) {
|
||||
union.delete(0);
|
||||
}
|
||||
union.insertBitField(0, 4, 12, IntegerDataType.dataType, 2, "bf1", "bf1Comment");
|
||||
union.insertBitField(0, IntegerDataType.dataType, 2, "bf1", "bf1Comment");
|
||||
union.insert(0, ShortDataType.dataType);
|
||||
union.setInternallyAligned(true);
|
||||
|
||||
|
@ -203,8 +203,8 @@ public class UnionDBTest extends AbstractGTest {
|
|||
@Test
|
||||
public void testInsertBitFieldLittleEndian() throws Exception {
|
||||
|
||||
union.insertBitField(2, 4, 0, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
union.insertBitField(2, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
|
@ -226,8 +226,8 @@ public class UnionDBTest extends AbstractGTest {
|
|||
|
||||
transitionToBigEndian();
|
||||
|
||||
union.insertBitField(2, 4, 0, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
union.insertBitField(2, IntegerDataType.dataType, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, ByteDataType.dataType, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
|
@ -250,8 +250,8 @@ public class UnionDBTest extends AbstractGTest {
|
|||
TypeDef td = new TypedefDataType("Foo", IntegerDataType.dataType);
|
||||
td = (TypeDef) dataMgr.resolve(td, null);
|
||||
|
||||
union.insertBitField(2, 4, 0, td, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, td, 4, "bf2", "bf2Comment");
|
||||
union.insertBitField(2, td, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, td, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
|
@ -289,8 +289,8 @@ public class UnionDBTest extends AbstractGTest {
|
|||
TypeDef td = new TypedefDataType("Foo", IntegerDataType.dataType);
|
||||
td = (TypeDef) dataMgr.resolve(td, null);
|
||||
|
||||
union.insertBitField(2, 4, 0, td, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, 1, 0, td, 4, "bf2", "bf2Comment");
|
||||
union.insertBitField(2, td, 4, "bf1", "bf1Comment");
|
||||
union.insertBitField(3, td, 4, "bf2", "bf2Comment");
|
||||
|
||||
//@formatter:off
|
||||
CompositeTestUtils.assertExpectedComposite(this, "/TestUnion\n" +
|
||||
|
|
|
@ -177,13 +177,11 @@ public class BitFieldDataTypeTest extends AbstractGTest {
|
|||
}
|
||||
|
||||
private BitFieldDataType bitField(int size, int offset) throws Exception {
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(size);
|
||||
return new BitFieldDataType(IntegerDataType.dataType, size, offset, storageSize);
|
||||
return new BitFieldDataType(IntegerDataType.dataType, size, offset);
|
||||
}
|
||||
|
||||
private BitFieldDataType unsignedBitField(int size, int offset) throws Exception {
|
||||
int storageSize = BitFieldDataType.getMinimumStorageSize(size);
|
||||
return new BitFieldDataType(UnsignedIntegerDataType.dataType, size, offset, storageSize);
|
||||
return new BitFieldDataType(UnsignedIntegerDataType.dataType, size, offset);
|
||||
}
|
||||
|
||||
private MemBuffer membuf(int... bytes) throws Exception {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue