BitFields - improved unaligned structure edit behavior

This commit is contained in:
ghidra1 2019-06-06 18:35:34 -04:00
parent 31163bca26
commit d4ea232a4d
5 changed files with 121 additions and 43 deletions

View file

@ -255,7 +255,17 @@ public class BitFieldPlacementComponent extends JPanel {
CompositeChangeListener listener) {
HashSet<Integer> ordinalDeleteSet = new HashSet<>();
if (editOrdinal >= 0) {
int initialLength = composite.getLength();
composite.delete(editOrdinal);
int sizeChange = initialLength - composite.getLength();
if (!composite.isInternallyAligned() && editOrdinal < composite.getNumComponents()) {
// deletions cause shift which is bad - pad with defaults
for (int i = 0; i < sizeChange; i++) {
composite.insert(editOrdinal, DataType.DEFAULT);
}
}
}
if (deleteConflicts) {
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {

View file

@ -1238,4 +1238,5 @@ public abstract class CompositeEditorModel extends CompositeViewerModel implemen
protected boolean bitfieldsSupported() {
return (viewComposite instanceof Structure) || (viewComposite instanceof Union);
}
}

View file

@ -23,13 +23,12 @@ import javax.swing.KeyStroke;
import docking.ActionContext;
import docking.action.KeyBindingData;
import ghidra.program.model.data.DataType;
import ghidra.program.model.data.DataTypeInstance;
import ghidra.program.model.data.*;
import ghidra.util.exception.UsrException;
import resources.ResourceManager;
/**
* Action for use in the composite data type editor.
* Action for use in the structure data type editor.
* This action has help associated with it.
*/
public class InsertUndefinedAction extends CompositeEditorTableAction {
@ -57,8 +56,10 @@ public class InsertUndefinedAction extends CompositeEditorTableAction {
if (isContiguousSelection) {
int index = model.getMinIndexSelected();
if (index >= 0) {
DataTypeInstance dti =
DataTypeInstance.getDataTypeInstance(DataType.DEFAULT, 1);
DataType undefinedDt =
model.viewComposite.isInternallyAligned() ? Undefined1DataType.dataType
: DataType.DEFAULT;
DataTypeInstance dti = DataTypeInstance.getDataTypeInstance(undefinedDt, -1);
model.insert(index, dti.getDataType(), dti.getLength());
}
}
@ -71,13 +72,16 @@ public class InsertUndefinedAction extends CompositeEditorTableAction {
@Override
public void adjustEnablement() {
if (model.viewComposite == null) {
return;
boolean enabled = false;
if (model.viewComposite instanceof Structure) {
boolean isContiguousSelection = model.getSelection().getNumRanges() == 1;
DataType undefinedDt =
model.viewComposite.isInternallyAligned() ? Undefined1DataType.dataType
: DataType.DEFAULT;
enabled = isContiguousSelection &&
model.isInsertAllowed(model.getMinIndexSelected(), undefinedDt);
}
boolean isContiguousSelection = model.getSelection().getNumRanges() == 1;
setEnabled(isContiguousSelection && model.isShowingUndefinedBytes() &&
model.isInsertAllowed(model.getMinIndexSelected(), DataType.DEFAULT));
setEnabled(enabled);
}
}

View file

@ -229,7 +229,20 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
// TODO: could improve insertion of bitfield which does not intersect
// existing ordinal bitfield at the bit-level
idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
if (idx > 0) {
DataTypeComponentDB existingDtc = components.get(idx);
if (existingDtc.isBitFieldComponent()) {
// must shift down to eliminate possible overlap with previous component
DataTypeComponentDB previousDtc = components.get(idx - 1);
if (previousDtc.getEndOffset() == existingDtc.getOffset()) {
shiftOffsets(idx, 0, 1);
}
}
}
}
if (idx < 0) {
idx = -idx - 1;
@ -331,7 +344,7 @@ class StructureDB extends CompositeDB implements Structure {
Comparator<Object> bitOffsetComparator =
bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE;
int startIndex = Collections.binarySearch(components, new Integer(startBitOffset),
int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset),
bitOffsetComparator);
if (startIndex < 0) {
startIndex = -startIndex - 1;
@ -437,7 +450,8 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
}
if (idx >= 0) {
doDelete(idx);
@ -467,10 +481,25 @@ class StructureDB extends CompositeDB implements Structure {
if (isInternallyAligned()) {
return;
}
int shiftAmount = 0;
// Bitfields: do not remove space previously occupied
if (!dtc.isBitFieldComponent()) {
shiftAmount = dtc.getLength();
int shiftAmount = dtc.getLength();
if (dtc.isBitFieldComponent()) {
// Must handle potential overlap with adjacent components
// NOTE: existing bitfields will not overlap by more than one byte
int minOffset = dtc.getOffset();
int maxOffset = dtc.getEndOffset();
if (index > 0) {
DataTypeComponentDB previousDtc = components.get(index - 1);
if (previousDtc.getEndOffset() == dtc.getOffset()) {
++minOffset;
}
}
if (minOffset <= maxOffset && index < components.size()) {
DataTypeComponentDB nextDtc = components.get(index);
if (nextDtc.getOffset() == dtc.getOffset()) {
--maxOffset;
}
}
shiftAmount = maxOffset - minOffset + 1;
}
shiftOffsets(index, -1, -shiftAmount);
}
@ -498,7 +527,7 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal),
idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
}
if (idx >= 0) {
@ -582,7 +611,8 @@ class StructureDB extends CompositeDB implements Structure {
if (isInternallyAligned()) {
return components.get(ordinal);
}
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int idx =
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (idx >= 0) {
return components.get(idx);
}
@ -684,7 +714,8 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
}
if (idx >= 0) {
DataTypeComponentDB dtc = components.remove(idx);
@ -766,7 +797,8 @@ class StructureDB extends CompositeDB implements Structure {
if (offset >= structLength) {
return;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int offsetDelta = 0;
int ordinalDelta = 0;
@ -804,7 +836,8 @@ class StructureDB extends CompositeDB implements Structure {
if (offset >= structLength || offset < 0) {
return null;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) {
DataTypeComponent dtc = components.get(index);
if (dtc.isBitFieldComponent()) {
@ -883,7 +916,8 @@ class StructureDB extends CompositeDB implements Structure {
structLength = offset;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int additionalShift = 0;
if (index >= 0) {
@ -1418,8 +1452,8 @@ class StructureDB extends CompositeDB implements Structure {
index = ordinal;
}
else {
index =
Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
index = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
}
if (index < 0) {
index = -index - 1;
@ -1465,7 +1499,7 @@ class StructureDB extends CompositeDB implements Structure {
if (ordinal >= numComponents) {
return 0;
}
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
DataTypeComponentDB dtc = null;
if (idx < 0) {
idx = -idx - 1;

View file

@ -122,7 +122,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (offset >= structLength || offset < 0) {
return null;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) {
DataTypeComponent dtc = components.get(index);
if (dtc.isBitFieldComponent()) {
@ -173,7 +173,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
}
if (idx >= 0) {
doDelete(idx);
@ -193,10 +193,25 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (isInternallyAligned()) {
return;
}
int shiftAmount = 0;
// Bitfields: do not remove space previously occupied
if (!dtc.isBitFieldComponent()) {
shiftAmount = dtc.getLength();
int shiftAmount = dtc.getLength();
if (dtc.isBitFieldComponent()) {
// Must handle potential overlap with adjacent components
// NOTE: existing bitfields will not overlap by more than one byte
int minOffset = dtc.getOffset();
int maxOffset = dtc.getEndOffset();
if (index > 0) {
DataTypeComponentImpl previousDtc = components.get(index - 1);
if (previousDtc.getEndOffset() == dtc.getOffset()) {
++minOffset;
}
}
if (minOffset <= maxOffset && index < components.size()) {
DataTypeComponentImpl nextDtc = components.get(index);
if (nextDtc.getOffset() == dtc.getOffset()) {
--maxOffset;
}
}
shiftAmount = maxOffset - minOffset + 1;
}
shiftOffsets(index, -1, -shiftAmount);
}
@ -222,7 +237,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = ordinal;
}
else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
}
if (idx >= 0) {
doDelete(idx);
@ -259,7 +275,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index < 0 || index >= numComponents) {
throw new ArrayIndexOutOfBoundsException(index);
}
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator);
if (idx >= 0) {
return components.get(idx);
}
@ -308,7 +324,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
structLength = offset;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int additionalShift = 0;
if (index >= 0) {
@ -448,7 +464,19 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = index;
}
else {
idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
// TODO: could improve insertion of bitfield which does not intersect
// existing ordinal bitfield at the bit-level
idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator);
if (idx > 0) {
DataTypeComponentImpl existingDtc = components.get(idx);
if (existingDtc.isBitFieldComponent()) {
// must shift down to eliminate possible overlap with previous component
DataTypeComponentImpl previousDtc = components.get(idx - 1);
if (previousDtc.getEndOffset() == existingDtc.getOffset()) {
shiftOffsets(idx, 0, 1);
}
}
}
}
if (idx < 0) {
idx = -idx - 1;
@ -533,8 +561,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
Comparator<Object> bitOffsetComparator =
bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE;
int startIndex =
Collections.binarySearch(components, new Integer(startBitOffset), bitOffsetComparator);
int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset),
bitOffsetComparator);
if (startIndex < 0) {
startIndex = -startIndex - 1;
}
@ -671,7 +699,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (offset >= structLength) {
return;
}
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator);
int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int offsetDelta = 0;
int ordinalDelta = 0;
@ -850,7 +878,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index < 0 || index >= numComponents) {
throw new ArrayIndexOutOfBoundsException(index);
}
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator);
if (idx >= 0) {
DataTypeComponent dtc = components.remove(idx);
dtc.getDataType().removeParent(this);
@ -1221,7 +1249,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
}
}
}
int index = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator);
int index =
Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
if (index < 0) {
index = -index - 1;
}
@ -1256,7 +1285,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index >= numComponents) {
return 0;
}
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator);
int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator);
DataTypeComponent dtc = null;
if (idx < 0) {
idx = -idx - 1;