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) { CompositeChangeListener listener) {
HashSet<Integer> ordinalDeleteSet = new HashSet<>(); HashSet<Integer> ordinalDeleteSet = new HashSet<>();
if (editOrdinal >= 0) { if (editOrdinal >= 0) {
int initialLength = composite.getLength();
composite.delete(editOrdinal); 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) { if (deleteConflicts) {
for (BitAttributes attrs : bitFieldAllocation.bitAttributes) { for (BitAttributes attrs : bitFieldAllocation.bitAttributes) {

View file

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

View file

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

View file

@ -229,7 +229,20 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal; idx = ordinal;
} }
else { 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) { if (idx < 0) {
idx = -idx - 1; idx = -idx - 1;
@ -331,7 +344,7 @@ class StructureDB extends CompositeDB implements Structure {
Comparator<Object> bitOffsetComparator = Comparator<Object> bitOffsetComparator =
bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE; bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE;
int startIndex = Collections.binarySearch(components, new Integer(startBitOffset), int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset),
bitOffsetComparator); bitOffsetComparator);
if (startIndex < 0) { if (startIndex < 0) {
startIndex = -startIndex - 1; startIndex = -startIndex - 1;
@ -437,7 +450,8 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal; idx = ordinal;
} }
else { else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
} }
if (idx >= 0) { if (idx >= 0) {
doDelete(idx); doDelete(idx);
@ -467,10 +481,25 @@ class StructureDB extends CompositeDB implements Structure {
if (isInternallyAligned()) { if (isInternallyAligned()) {
return; return;
} }
int shiftAmount = 0; int shiftAmount = dtc.getLength();
// Bitfields: do not remove space previously occupied if (dtc.isBitFieldComponent()) {
if (!dtc.isBitFieldComponent()) { // Must handle potential overlap with adjacent components
shiftAmount = dtc.getLength(); // 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); shiftOffsets(index, -1, -shiftAmount);
} }
@ -498,7 +527,7 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal; idx = ordinal;
} }
else { else {
idx = Collections.binarySearch(components, new Integer(ordinal), idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator); ordinalComparator);
} }
if (idx >= 0) { if (idx >= 0) {
@ -582,7 +611,8 @@ class StructureDB extends CompositeDB implements Structure {
if (isInternallyAligned()) { if (isInternallyAligned()) {
return components.get(ordinal); 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) { if (idx >= 0) {
return components.get(idx); return components.get(idx);
} }
@ -684,7 +714,8 @@ class StructureDB extends CompositeDB implements Structure {
idx = ordinal; idx = ordinal;
} }
else { else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
} }
if (idx >= 0) { if (idx >= 0) {
DataTypeComponentDB dtc = components.remove(idx); DataTypeComponentDB dtc = components.remove(idx);
@ -766,7 +797,8 @@ class StructureDB extends CompositeDB implements Structure {
if (offset >= structLength) { if (offset >= structLength) {
return; return;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int offsetDelta = 0; int offsetDelta = 0;
int ordinalDelta = 0; int ordinalDelta = 0;
@ -804,7 +836,8 @@ class StructureDB extends CompositeDB implements Structure {
if (offset >= structLength || offset < 0) { if (offset >= structLength || offset < 0) {
return null; return null;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) { if (index >= 0) {
DataTypeComponent dtc = components.get(index); DataTypeComponent dtc = components.get(index);
if (dtc.isBitFieldComponent()) { if (dtc.isBitFieldComponent()) {
@ -883,7 +916,8 @@ class StructureDB extends CompositeDB implements Structure {
structLength = offset; structLength = offset;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index =
Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int additionalShift = 0; int additionalShift = 0;
if (index >= 0) { if (index >= 0) {
@ -1418,8 +1452,8 @@ class StructureDB extends CompositeDB implements Structure {
index = ordinal; index = ordinal;
} }
else { else {
index = index = Collections.binarySearch(components, Integer.valueOf(ordinal),
Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); ordinalComparator);
} }
if (index < 0) { if (index < 0) {
index = -index - 1; index = -index - 1;
@ -1465,7 +1499,7 @@ class StructureDB extends CompositeDB implements Structure {
if (ordinal >= numComponents) { if (ordinal >= numComponents) {
return 0; return 0;
} }
int idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); int idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
DataTypeComponentDB dtc = null; DataTypeComponentDB dtc = null;
if (idx < 0) { if (idx < 0) {
idx = -idx - 1; idx = -idx - 1;

View file

@ -122,7 +122,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (offset >= structLength || offset < 0) { if (offset >= structLength || offset < 0) {
return null; return null;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
if (index >= 0) { if (index >= 0) {
DataTypeComponent dtc = components.get(index); DataTypeComponent dtc = components.get(index);
if (dtc.isBitFieldComponent()) { if (dtc.isBitFieldComponent()) {
@ -173,7 +173,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = ordinal; idx = ordinal;
} }
else { else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); idx = Collections.binarySearch(components, Integer.valueOf(ordinal), ordinalComparator);
} }
if (idx >= 0) { if (idx >= 0) {
doDelete(idx); doDelete(idx);
@ -193,10 +193,25 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (isInternallyAligned()) { if (isInternallyAligned()) {
return; return;
} }
int shiftAmount = 0; int shiftAmount = dtc.getLength();
// Bitfields: do not remove space previously occupied if (dtc.isBitFieldComponent()) {
if (!dtc.isBitFieldComponent()) { // Must handle potential overlap with adjacent components
shiftAmount = dtc.getLength(); // 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); shiftOffsets(index, -1, -shiftAmount);
} }
@ -222,7 +237,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = ordinal; idx = ordinal;
} }
else { else {
idx = Collections.binarySearch(components, new Integer(ordinal), ordinalComparator); idx = Collections.binarySearch(components, Integer.valueOf(ordinal),
ordinalComparator);
} }
if (idx >= 0) { if (idx >= 0) {
doDelete(idx); doDelete(idx);
@ -259,7 +275,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index < 0 || index >= numComponents) { if (index < 0 || index >= numComponents) {
throw new ArrayIndexOutOfBoundsException(index); 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) { if (idx >= 0) {
return components.get(idx); return components.get(idx);
} }
@ -308,7 +324,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
structLength = offset; structLength = offset;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int additionalShift = 0; int additionalShift = 0;
if (index >= 0) { if (index >= 0) {
@ -448,7 +464,19 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
idx = index; idx = index;
} }
else { 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) { if (idx < 0) {
idx = -idx - 1; idx = -idx - 1;
@ -533,8 +561,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
Comparator<Object> bitOffsetComparator = Comparator<Object> bitOffsetComparator =
bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE; bigEndian ? bitOffsetComparatorBE : bitOffsetComparatorLE;
int startIndex = int startIndex = Collections.binarySearch(components, Integer.valueOf(startBitOffset),
Collections.binarySearch(components, new Integer(startBitOffset), bitOffsetComparator); bitOffsetComparator);
if (startIndex < 0) { if (startIndex < 0) {
startIndex = -startIndex - 1; startIndex = -startIndex - 1;
} }
@ -671,7 +699,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (offset >= structLength) { if (offset >= structLength) {
return; return;
} }
int index = Collections.binarySearch(components, new Integer(offset), offsetComparator); int index = Collections.binarySearch(components, Integer.valueOf(offset), offsetComparator);
int offsetDelta = 0; int offsetDelta = 0;
int ordinalDelta = 0; int ordinalDelta = 0;
@ -850,7 +878,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index < 0 || index >= numComponents) { if (index < 0 || index >= numComponents) {
throw new ArrayIndexOutOfBoundsException(index); 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) { if (idx >= 0) {
DataTypeComponent dtc = components.remove(idx); DataTypeComponent dtc = components.remove(idx);
dtc.getDataType().removeParent(this); 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) { if (index < 0) {
index = -index - 1; index = -index - 1;
} }
@ -1256,7 +1285,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index >= numComponents) { if (index >= numComponents) {
return 0; return 0;
} }
int idx = Collections.binarySearch(components, new Integer(index), ordinalComparator); int idx = Collections.binarySearch(components, Integer.valueOf(index), ordinalComparator);
DataTypeComponent dtc = null; DataTypeComponent dtc = null;
if (idx < 0) { if (idx < 0) {
idx = -idx - 1; idx = -idx - 1;