BitFields - corrected bitfield transitions between different data

organizations and packing for unions.
This commit is contained in:
ghidra1 2019-07-10 17:06:56 -04:00
parent 486ce82586
commit f54f68c66e
22 changed files with 352 additions and 315 deletions

View file

@ -18,7 +18,6 @@ package ghidra.app.plugin.core.compositeeditor;
import java.awt.Component;
import java.awt.Window;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import docking.ActionContext;
@ -67,10 +66,7 @@ public class AddBitFieldAction extends CompositeEditorTableAction {
}
private void refreshTableAndSelection(CompEditorModel editorModel, int ordinal) {
editorModel.fireTableDataChanged();
editorModel.compositeInfoChanged();
JTable editorTable = provider.getTable();
editorTable.getSelectionModel().setSelectionInterval(ordinal, ordinal);
editorModel.notifyCompositeChanged();
}
@Override

View file

@ -20,6 +20,7 @@ import java.awt.event.*;
import java.util.Arrays;
import java.util.HashSet;
import javax.help.UnsupportedOperationException;
import javax.swing.*;
import ghidra.program.model.data.*;
@ -382,16 +383,17 @@ public class BitFieldPlacementComponent extends JPanel {
String name = (fieldName != null && fieldName.length() != 0) ? fieldName : null;
DataTypeComponent dtc;
if (composite instanceof Union) {
dtc = composite.insertBitField(ordinal, allocationByteSize,
bitFieldAllocation.bitOffset, baseDataType, bitFieldAllocation.bitSize, name,
null);
}
else {
Structure struct = (Structure) composite;
dtc = struct.insertBitFieldAt(allocationByteOffset, allocationByteSize,
bitFieldAllocation.bitOffset, baseDataType, bitFieldAllocation.bitSize, name,
null);
throw new UnsupportedOperationException(
"Union modification not currently supported");
// dtc = composite.insertBitField(ordinal, allocationByteSize,
// bitFieldAllocation.bitOffset, baseDataType, bitFieldAllocation.bitSize, name,
// null);
}
// else {
Structure struct = (Structure) composite;
dtc = struct.insertBitFieldAt(allocationByteOffset, allocationByteSize,
bitFieldAllocation.bitOffset, baseDataType, bitFieldAllocation.bitSize, name, null);
// }
if (listener != null) {
listener.componentChanged(dtc.getOrdinal());
}
@ -484,9 +486,22 @@ public class BitFieldPlacementComponent extends JPanel {
if (tip == null) {
return null;
}
String conflictMsg = "";
DataTypeComponent conflict = attrs.getConflict();
if (conflict != null) {
if (tip.length() != 0) {
conflictMsg = "<br>";
}
String conflictName = conflict.getFieldName();
String conflictTip = "'" + conflict.getDataType().getDisplayName() +
(conflictName != null ? (" " + conflictName) : "") + "' at offset " +
conflict.getOffset();
conflictMsg += "<div style=\"color: red;font-style: italic\">conflict with " +
HTMLUtilities.escapeHTML(conflictTip) + "</div>";
}
return "<HTML><div style=\"text-align:center\">" + HTMLUtilities.escapeHTML(tip) +
conflictMsg +
"<div style=\"color: gray;font-style: italic\">(Shift-wheel to zoom)</div></div></HTML>";
}
@Override
@ -1050,8 +1065,7 @@ public class BitFieldPlacementComponent extends JPanel {
return null;
}
String name = dtc.getFieldName();
return dtc.getDataType().getDisplayName() +
(name != null ? (" " + dtc.getFieldName()) : "");
return dtc.getDataType().getDisplayName() + (name != null ? (" " + name) : "");
}
DataTypeComponent getDataTypeComponent(boolean ignoreActiveComponent) {

View file

@ -147,7 +147,7 @@ public class UnionDataTypeTest 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
@ -168,7 +168,7 @@ public class UnionDataTypeTest 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);
@ -186,8 +186,8 @@ public class UnionDataTypeTest 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" +
@ -209,8 +209,8 @@ public class UnionDataTypeTest 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" +

View file

@ -42,8 +42,8 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel
CompositeTestUtils.assertExpectedComposite(this, "/U1\n" +
"Aligned\n" +
"Union U1 {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 int:2(0) 1 b \"\"\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 4 Actual Alignment = 4", struct);
//@formatter:on
@ -56,9 +56,9 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel
CompositeTestUtils.assertExpectedComposite(this, "/U1z\n" +
"Aligned\n" +
"Union U1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
" 0 int:2(0) 1 b \"\"\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 1 \"\"\n" + // has no impact
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 4 Actual Alignment = 4", struct);
//@formatter:on
@ -71,8 +71,8 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel
CompositeTestUtils.assertExpectedComposite(this, "/U1p1\n" +
"Aligned pack(1)\n" +
"Union U1p1 {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 int:2(0) 1 b \"\"\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1", struct);
//@formatter:on
@ -85,9 +85,9 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel
CompositeTestUtils.assertExpectedComposite(this, "/U1p1z\n" +
"Aligned pack(1)\n" +
"Union U1p1z {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 longlong:0(0) 1 \"\"\n" + // has no impact
" 0 int:2(0) 1 b \"\"\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 longlong:0(7) 1 \"\"\n" + // has no impact
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 1 Actual Alignment = 1", struct);
//@formatter:on
@ -100,8 +100,8 @@ public class UnionImplBigEndianBitFieldTest extends AbstractCompositeImplBitFiel
CompositeTestUtils.assertExpectedComposite(this, "/U1p2\n" +
"Aligned pack(2)\n" +
"Union U1p2 {\n" +
" 0 int:4(0) 1 a \"\"\n" +
" 0 int:2(0) 1 b \"\"\n" +
" 0 int:4(4) 1 a \"\"\n" +
" 0 int:2(6) 1 b \"\"\n" +
"}\n" +
"Size = 2 Actual Alignment = 2", struct);
//@formatter:on

View file

@ -38,7 +38,7 @@ class PdbBitField extends BitFieldDataType {
protected PdbBitField(DataType baseDataType, int bitSize, int bitOffsetWithinBaseType)
throws InvalidDataTypeException {
super(baseDataType, bitSize,
getMinimalBitOffset(baseDataType, bitSize, bitOffsetWithinBaseType), 0);
getMinimalBitOffset(baseDataType, bitSize, bitOffsetWithinBaseType));
if (bitSize < 1) {
throw new InvalidDataTypeException("invalid PDB bit size: " + bitSize);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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" +

View file

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