GP-302 additional corrections to DataUtilities.

This commit is contained in:
ghidra1 2020-10-28 12:58:27 -04:00
parent c10d1f1b50
commit aa6319b8c6
2 changed files with 54 additions and 14 deletions

View File

@ -25,6 +25,7 @@ import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.data.*;
import ghidra.program.model.data.DataUtilities.ClearDataMode;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.RefType;
import ghidra.program.model.symbol.SourceType;
@ -130,7 +131,7 @@ public class CreateDataCmdTest extends AbstractGenericTest {
assertTrue(d.getDataType() instanceof ByteDataType);
// Byte becomes Word and consumes next Default data byte
cmd = new CreateDataCmd(addr, new WordDataType());
cmd = new CreateDataCmd(addr, new WordDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
cmd.applyTo(program);
d = listing.getDataAt(addr);
@ -161,7 +162,7 @@ public class CreateDataCmdTest extends AbstractGenericTest {
assertTrue(d.getDataType() instanceof WordDataType);
// Word becomes Byte immediately followed by Default data
cmd = new CreateDataCmd(addr, new ByteDataType());
cmd = new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
cmd.applyTo(program);
d = listing.getDataAt(addr);
@ -376,6 +377,36 @@ public class CreateDataCmdTest extends AbstractGenericTest {
}
@Test
public void testCreatePointerOnMultipleUndefined1Data() {
Address addr = addr(UNDEFINED_AREA);
CreateDataCmd cmd = new CreateDataCmd(addr, new Undefined1DataType());
cmd.applyTo(program);
cmd = new CreateDataCmd(addr.next(), new Undefined1DataType());
cmd.applyTo(program);
// two Undefined1 data becomes Pointer
cmd = new CreateDataCmd(addr, false, true, new PointerDataType());
cmd.applyTo(program);
Data d = listing.getDataAt(addr);
assertNotNull(d);
assertTrue(d.isDefined());
assertEquals(4, d.getLength());
DataType dt = d.getDataType();
assertTrue(dt instanceof Pointer);
assertEquals(addr.getPointerSize(), dt.getLength());
Pointer pdt = (Pointer) dt;
assertNull(pdt.getDataType());
d = listing.getDataAfter(addr);
assertNotNull(d);
assertTrue(!d.isDefined());
assertEquals(4, d.getMinAddress().getOffset() - UNDEFINED_AREA);
}
@Test
public void testCreatePointerOnPointer() {
@ -693,7 +724,7 @@ public class CreateDataCmdTest extends AbstractGenericTest {
assertEquals(10, dt.getLength());
// Byte[] becomes Byte
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType());
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
cmd.applyTo(program);
d = listing.getDataAt(addr);
@ -761,7 +792,7 @@ public class CreateDataCmdTest extends AbstractGenericTest {
assertEquals(10, dt.getLength());
// struct becomes Byte
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType());
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
cmd.applyTo(program);
d = listing.getDataAt(addr);

View File

@ -129,13 +129,14 @@ public final class DataUtilities {
return data;
}
if (clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
if (!stackPointers && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
!Undefined.isUndefined(existingDT)) {
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
}
// Check for external reference on pointer
if (existingDT instanceof Pointer) {
if ((stackPointers || newDataType instanceof Pointer) &&
existingDT instanceof Pointer) {
// TODO: This can probably be eliminated
Reference[] refs = refMgr.getReferencesFrom(addr);
for (Reference ref : refs) {
@ -174,19 +175,26 @@ public final class DataUtilities {
throw new CodeUnitInsertionException(
"Could not create DataType " + newDataType.getDisplayName());
}
if (stackPointers && existingDT instanceof Pointer && newDataType instanceof Pointer) {
listing.clearCodeUnits(addr, addr, false);
}
Data newData;
try {
return listing.createData(addr, dti.getDataType(), dti.getLength());
newData = listing.createData(addr, dti.getDataType(), dti.getLength());
}
catch (CodeUnitInsertionException e) {
// ok lets see if we need to clear some code units
if (clearMode == ClearDataMode.CLEAR_SINGLE_DATA) {
listing.clearCodeUnits(addr, addr, false);
}
else {
checkEnoughSpace(program, addr, existingDataLen, dti, clearMode);
}
newData = listing.createData(addr, dti.getDataType(), dti.getLength());
}
if (clearMode == ClearDataMode.CLEAR_SINGLE_DATA) {
listing.clearCodeUnits(addr, addr, false);
}
else {
checkEnoughSpace(program, addr, existingDataLen, dti, clearMode);
}
Data newData = listing.createData(addr, dti.getDataType(), dti.getLength());
// if this was a pointer and had an external reference, put it back!
if ((newDataType instanceof Pointer) && extRef != null) {
ExternalLocation extLoc = ((ExternalReference) extRef).getExternalLocation();
@ -203,6 +211,7 @@ public final class DataUtilities {
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
Listing listing = program.getListing();
try {
Address end = addr.addNoWrap(existingDataLen - 1);