mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-10-06 04:59:23 +08:00
Merge remote-tracking branch 'origin/Ghidra_12.2'
This commit is contained in:
+92
-59
File diff suppressed because it is too large
Load Diff
+6
@@ -1098,6 +1098,12 @@ class StackFrameDataType implements Structure {
|
||||
return dtc != null ? new StackComponentWrapper(dtc) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent getDefinedComponent(int index) throws IndexOutOfBoundsException {
|
||||
DataTypeComponent dtc = wrappedStruct.getDefinedComponent(index);
|
||||
return new StackComponentWrapper(dtc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackComponentWrapper getComponent(int ordinal) throws IndexOutOfBoundsException {
|
||||
DataTypeComponent dtc = wrappedStruct.getComponent(ordinal);
|
||||
|
||||
+66
@@ -1169,6 +1169,72 @@ public class DataTypeMerge4Test extends AbstractDataTypeMergeTest {
|
||||
checkConflictCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiEdits14() throws Exception {
|
||||
|
||||
mtf.initialize("notepad2", new ProgramModifierListener() {
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar");
|
||||
|
||||
// Create a conflict while retaining Bar's original six-byte length.
|
||||
assertEquals(6, bar.getLength());
|
||||
bar.getComponent(0).setComment("Latest Bar component");
|
||||
|
||||
int junk = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
CategoryPath path = new CategoryPath("/MISC");
|
||||
Structure bar = (Structure) dtm.getDataType(path, "Bar");
|
||||
bar.delete(1); // Remove the pointer, shrinking Bar from six bytes to two.
|
||||
assertEquals(2, bar.getLength());
|
||||
|
||||
// Allocate the container before its target so that the merge records a fixup
|
||||
// for the as-yet-unresolved target when processing the added container.
|
||||
Structure container = (Structure) dtm.addDataType(
|
||||
new StructureDataType(path, "FixupContainer", 0),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
Structure target = new StructureDataType(path, "FixupTarget", 0);
|
||||
target.add(ByteDataType.dataType);
|
||||
target = (Structure) dtm.addDataType(target, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
|
||||
container.add(bar, "bar", null);
|
||||
container.growStructure(4);
|
||||
container.add(target, "target", null);
|
||||
assertFalse(container.isPackingEnabled());
|
||||
assertEquals(6, container.getComponent(5).getOffset());
|
||||
|
||||
int junk = 0;
|
||||
}
|
||||
});
|
||||
|
||||
executeMerge();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
|
||||
// The added container initially uses Latest's six-byte Bar, so the placeholder
|
||||
// at offset 6 has ordinal 1. Choosing MY Bar shrinks that component to two bytes,
|
||||
// introducing four undefined components before the placeholder. Its ordinal is
|
||||
// now 5, but FixUpInfo still records 1. The merge must not use that stale ordinal.
|
||||
chooseOption(DataTypeMergeManager.OPTION_MY);
|
||||
waitForCompletion();
|
||||
|
||||
Structure bar = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Bar");
|
||||
Structure container =
|
||||
(Structure) dtm.getDataType(new CategoryPath("/MISC"), "FixupContainer");
|
||||
DataType target = dtm.getDataType(new CategoryPath("/MISC"), "FixupTarget");
|
||||
assertEquals(2, bar.getLength());
|
||||
assertEquals(7, container.getLength());
|
||||
assertEquals(2, container.getNumDefinedComponents());
|
||||
assertEquals(bar, container.getComponent(0).getDataType());
|
||||
assertEquals(6, container.getComponent(5).getOffset());
|
||||
assertEquals(target, container.getComponent(5).getDataType());
|
||||
checkConflictCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeletedBaseTypeDef() throws Exception {
|
||||
|
||||
|
||||
+101
@@ -28,6 +28,107 @@ import ghidra.program.model.data.*;
|
||||
*/
|
||||
public class DataTypeMergeFixupTest extends AbstractDataTypeMergeTest {
|
||||
|
||||
@Test
|
||||
public void testDefinedComponentFixupAfterResize() throws Exception {
|
||||
checkDefinedComponentFixupAfterLayoutChange(false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedComponentFixupAfterEnablingPacking() throws Exception {
|
||||
checkDefinedComponentFixupAfterLayoutChange(false, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefinedComponentFixupAfterDisablingPacking() throws Exception {
|
||||
checkDefinedComponentFixupAfterLayoutChange(true, false);
|
||||
}
|
||||
|
||||
private void checkDefinedComponentFixupAfterLayoutChange(boolean initiallyPacked,
|
||||
boolean finallyPacked) throws Exception {
|
||||
CategoryPath path = new CategoryPath("/MISC");
|
||||
mtf.initialize("notepad2", new OriginalProgramModifierListener() {
|
||||
@Override
|
||||
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||
// Ensure the zero-length type is already resolved when the container is added.
|
||||
program.getDataTypeManager().addDataType(new ArrayDataType(ByteDataType.dataType, 0),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) throws Exception {
|
||||
Structure bar = (Structure) program.getDataTypeManager().getDataType(path, "Bar");
|
||||
bar.getComponent(0).setComment("Latest Bar component");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) throws Exception {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
Structure bar = (Structure) dtm.getDataType(path, "Bar");
|
||||
bar.delete(1);
|
||||
assertEquals(2, bar.getLength());
|
||||
|
||||
// Allocate the container first so its target components require deferred fixups.
|
||||
Structure container = (Structure) dtm.addDataType(
|
||||
new StructureDataType(path, "LayoutContainer", 0),
|
||||
DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
Structure target = new StructureDataType(path, "LayoutTarget", 0);
|
||||
target.add(ByteDataType.dataType);
|
||||
target = (Structure) dtm.addDataType(target, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
|
||||
container.add(bar, "bar", null);
|
||||
container.growStructure(4);
|
||||
container.insertBitFieldAt(6, 1, 0, ByteDataType.dataType, 3, "bits1", null);
|
||||
container.insertBitFieldAt(6, 1, 3, ByteDataType.dataType, 2, "bits2", null);
|
||||
container.add(new ArrayDataType(ByteDataType.dataType, 0), "zero1", null);
|
||||
container.add(new ArrayDataType(ByteDataType.dataType, 0), "zero2", null);
|
||||
container.add(target, "target1", null);
|
||||
container.add(target, "target2", null);
|
||||
container.setPackingEnabled(initiallyPacked);
|
||||
}
|
||||
});
|
||||
|
||||
executeMerge();
|
||||
waitForPrompting(); // Wait until additions are complete and the Bar conflict is displayed.
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
Structure container = (Structure) dtm.getDataType(path, "LayoutContainer");
|
||||
assertNotNull(container);
|
||||
DataTypeComponent[] components = container.getDefinedComponents();
|
||||
assertEquals(7, components.length);
|
||||
assertEquals(BadDataType.dataType, components[5].getDataType());
|
||||
assertEquals(BadDataType.dataType, components[6].getDataType());
|
||||
|
||||
// The merge is paused at the Bar conflict, after the container fixups were recorded.
|
||||
// Exercise a packing transition without replacing its defined-component sequence.
|
||||
int tx = resultProgram.startTransaction("Change packing with pending fixups");
|
||||
try {
|
||||
container.setPackingEnabled(finallyPacked);
|
||||
}
|
||||
finally {
|
||||
resultProgram.endTransaction(tx, true);
|
||||
}
|
||||
chooseOption(DataTypeMergeManager.OPTION_MY);
|
||||
waitForCompletion();
|
||||
|
||||
container = (Structure) dtm.getDataType(path, "LayoutContainer");
|
||||
components = container.getDefinedComponents();
|
||||
assertEquals(finallyPacked, container.isPackingEnabled());
|
||||
assertEquals(7, components.length);
|
||||
assertEquals(2, components[0].getLength());
|
||||
assertTrue(components[1].isBitFieldComponent());
|
||||
assertTrue(components[2].isBitFieldComponent());
|
||||
assertEquals(components[1].getOffset(), components[2].getOffset());
|
||||
assertEquals(0, components[3].getLength());
|
||||
assertEquals(0, components[4].getLength());
|
||||
assertEquals(components[3].getOffset(), components[4].getOffset());
|
||||
DataType target = dtm.getDataType(path, "LayoutTarget");
|
||||
assertNotNull(target);
|
||||
assertEquals("target1", components[5].getFieldName());
|
||||
assertEquals(target, components[5].getDataType());
|
||||
assertEquals("target2", components[6].getFieldName());
|
||||
assertEquals(target, components[6].getDataType());
|
||||
checkConflictCount(0);
|
||||
}
|
||||
|
||||
private void setupRemoveInnerVsAddOuterContainingChangedInner() throws Exception {
|
||||
|
||||
final CategoryPath rootPath = new CategoryPath("/");
|
||||
|
||||
+12
@@ -746,10 +746,22 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
@Override
|
||||
public int getNumDefinedComponents() {
|
||||
try (Closeable c = lock.read()) {
|
||||
refreshIfNeeded();
|
||||
return components.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentDB getDefinedComponent(int index) throws IndexOutOfBoundsException {
|
||||
try (Closeable c = lock.read()) {
|
||||
refreshIfNeeded();
|
||||
if (index < 0 || index >= components.size()) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
}
|
||||
return components.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentDB getComponent(int ordinal) {
|
||||
try (Closeable c = lock.read()) {
|
||||
|
||||
+9
-4
@@ -389,16 +389,21 @@ class UnionDB extends CompositeDB implements UnionInternal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentDB getComponent(int ordinal) {
|
||||
public DataTypeComponentDB getDefinedComponent(int index) throws IndexOutOfBoundsException {
|
||||
try (Closeable c = lock.read()) {
|
||||
refreshIfNeeded();
|
||||
if (ordinal < 0 || ordinal >= components.size()) {
|
||||
return null;
|
||||
if (index < 0 || index >= components.size()) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
}
|
||||
return components.get(ordinal);
|
||||
return components.get(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentDB getComponent(int ordinal) {
|
||||
return getDefinedComponent(ordinal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentDB[] getComponents() {
|
||||
try (Closeable c = lock.read()) {
|
||||
|
||||
+11
@@ -47,6 +47,17 @@ public interface Composite extends DataType {
|
||||
*/
|
||||
public abstract int getNumDefinedComponents();
|
||||
|
||||
/**
|
||||
* Returns the defined component of this data type at the specified index
|
||||
* within the ordered sequence of {@link #getDefinedComponents() defined components}.
|
||||
* See {@link #getNumDefinedComponents()}.
|
||||
* @param index the index of the defined component (numbering starts at 0).
|
||||
* @return the data type component.
|
||||
* @throws IndexOutOfBoundsException if the index is out of bounds
|
||||
*/
|
||||
public abstract DataTypeComponent getDefinedComponent(int index)
|
||||
throws IndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Returns the component of this data type with the indicated ordinal.
|
||||
* @param ordinal the component's ordinal (numbering starts at 0).
|
||||
|
||||
+8
@@ -448,6 +448,14 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||
dtc.setOrdinal(dtc.getOrdinal() + deltaOrdinal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentImpl getDefinedComponent(int index) throws IndexOutOfBoundsException {
|
||||
if (index < 0 || index >= components.size()) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
}
|
||||
return components.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentImpl getComponent(int ordinal) {
|
||||
if (ordinal < 0 || ordinal >= numComponents) {
|
||||
|
||||
+10
-2
@@ -104,8 +104,16 @@ public class UnionDataType extends CompositeDataTypeImpl implements UnionInterna
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent getComponent(int ordinal) {
|
||||
return components.get(ordinal);
|
||||
public DataTypeComponentImpl getDefinedComponent(int index) throws IndexOutOfBoundsException {
|
||||
if (index < 0 || index >= components.size()) {
|
||||
throw new IndexOutOfBoundsException(index);
|
||||
}
|
||||
return components.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponentImpl getComponent(int ordinal) throws IndexOutOfBoundsException {
|
||||
return getDefinedComponent(ordinal);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user