mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/patch'
Conflicts: Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java
This commit is contained in:
commit
c081a87ede
9 changed files with 1187 additions and 481 deletions
File diff suppressed because it is too large
Load diff
|
@ -162,8 +162,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
|
||||
BitFieldEditorDialog dlg = new BitFieldEditorDialog(model.viewComposite,
|
||||
provider.dtmService, editingRow, ordinal -> {
|
||||
model.fireTableDataChanged();
|
||||
model.compositeInfoChanged();
|
||||
model.notifyCompositeChanged();
|
||||
});
|
||||
Component c = provider.getComponent();
|
||||
Window w = SwingUtilities.windowForComponent(c);
|
||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.app.merge.datatypes;
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -36,37 +38,47 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
@Test
|
||||
public void testCategoryAddRemoveDTAdd() throws Exception {
|
||||
|
||||
TypeDef td = new TypedefDataType("BF", IntegerDataType.dataType);
|
||||
|
||||
AtomicReference<Structure> structRef = new AtomicReference<>();
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
|
||||
boolean commit = false;
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||
try {
|
||||
c.removeCategory("Category5", TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
Category c5 = c.createCategory("Category5");
|
||||
Structure dt = new StructureDataType("Test", 0);
|
||||
dt.add(new ByteDataType());
|
||||
dt.add(new WordDataType());
|
||||
|
||||
dt = (Structure) c5.addDataType(dt, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
dt.add(new QWordDataType());
|
||||
Structure struct =
|
||||
new StructureDataType("Test", 0, program.getDataTypeManager());
|
||||
struct.add(new ByteDataType());
|
||||
struct.add(new WordDataType());
|
||||
struct.insertBitFieldAt(3, 2, 6, td, 2, "bf1", null);
|
||||
struct.insertBitFieldAt(3, 2, 4, td, 2, "bf2", null);
|
||||
struct.add(new QWordDataType());
|
||||
|
||||
struct.setFlexibleArrayComponent(td, "flex", "my flex");
|
||||
|
||||
structRef.set(struct);
|
||||
|
||||
c.removeCategory("Category5", TaskMonitorAdapter.DUMMY);
|
||||
Category c5 = c.createCategory("Category5");
|
||||
c5.addDataType(struct, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
commit = true;
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
Assert.fail("got InvalidNameException!");
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.toString());
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, commit);
|
||||
|
@ -79,7 +91,9 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category5"));
|
||||
assertNotNull(c);
|
||||
assertNotNull(c.getDataType("Test"));
|
||||
DataType dt = c.getDataType("Test");
|
||||
assertNotNull(dt);
|
||||
assertTrue(structRef.get().isEquivalent(dt));
|
||||
|
||||
}
|
||||
|
||||
|
@ -89,9 +103,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
// A category was added to Category5 in the latest;
|
||||
// in My program, rename Category5 to "My Category5" and add a new data type
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -111,9 +123,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -159,18 +168,17 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
@Test
|
||||
public void testDataTypeAddedInMy2() throws Exception {
|
||||
|
||||
TypeDef td = new TypedefDataType("BF", IntegerDataType.dataType);
|
||||
|
||||
AtomicReference<Structure> structRef = new AtomicReference<>();
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -179,15 +187,24 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||
try {
|
||||
Structure s = (Structure) c.getDataType("IntStruct");
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
|
||||
s.add(new QWordDataType());
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0, dtm);
|
||||
s.add(new QWordDataType(), "f1", "my f1");
|
||||
s.add(new FloatDataType());
|
||||
s.add(new ByteDataType());
|
||||
s.insertBitFieldAt(16, 2, 6, td, 2, "bf1", "my bf1");
|
||||
s.insertBitFieldAt(16, 2, 4, td, 2, "bf2", "my bf2");
|
||||
s.add(new WordDataType());
|
||||
|
||||
structRef.set(s);
|
||||
|
||||
c.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
commit = true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.toString());
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, commit);
|
||||
}
|
||||
|
@ -199,30 +216,25 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||
DataType dt = c.getDataType("IntStruct");
|
||||
assertNotNull(dt);
|
||||
assertTrue(dt instanceof Structure);
|
||||
Structure s = (Structure) dt;
|
||||
assertTrue(new QWordDataType().isEquivalent(s.getComponent(0).getDataType()));
|
||||
assertTrue(new FloatDataType().isEquivalent(s.getComponent(1).getDataType()));
|
||||
assertTrue(new ByteDataType().isEquivalent(s.getComponent(2).getDataType()));
|
||||
assertTrue(new WordDataType().isEquivalent(s.getComponent(3).getDataType()));
|
||||
assertTrue(structRef.get().isEquivalent(dt));
|
||||
|
||||
Structure s = (Structure) dt;
|
||||
assertEquals("my f1", s.getComponent(0).getComment());
|
||||
DataTypeComponent dtc = s.getComponentAt(17);
|
||||
assertEquals(7, dtc.getOrdinal());
|
||||
assertEquals("my bf1", dtc.getComment());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataTypeAddedInMy3() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -231,7 +243,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||
try {
|
||||
Structure s = (Structure) c.getDataType("IntStruct");
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
c.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
s = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
|
||||
s.add(new QWordDataType());
|
||||
s.add(new FloatDataType());
|
||||
|
@ -276,9 +288,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
// add a new data type;
|
||||
// in My program, rename Category5 to "My Category5"
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -303,9 +313,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -346,9 +353,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
// A category was added to Category5 in the latest;
|
||||
// in My program, rename Category5 to "My Category5" and add a new data type
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -372,9 +377,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -421,17 +423,12 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -443,7 +440,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -464,17 +461,12 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeAddedDeletedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -487,7 +479,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -508,9 +500,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedChanged() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -529,9 +519,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -543,7 +530,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -564,9 +551,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedChanged2() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -585,9 +570,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -599,7 +581,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"FloatStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -619,9 +601,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedChanged3() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -631,7 +611,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -639,9 +619,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -672,9 +649,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedInLatest() throws Exception {
|
||||
|
||||
mtf.initialize("notepad2", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -684,7 +659,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -692,9 +667,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -731,9 +703,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeDeletedInBoth() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -745,7 +715,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -753,9 +723,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -767,7 +734,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -788,17 +755,12 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDataTypeRenamedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
// Make no changes to Latest.
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -837,9 +799,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testRenamedBoth() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -865,9 +825,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -905,9 +862,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testRenamedBoth2() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -933,9 +888,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -974,9 +926,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDeletedInMyRenamedInLatest() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1002,9 +952,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1016,7 +963,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1035,9 +982,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDeletedInLatestRenamedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1047,7 +992,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
"IntStruct");
|
||||
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1055,9 +1000,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1093,9 +1035,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDeletedInLatestChangedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1110,7 +1050,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
Structure s = (Structure) dt;
|
||||
s.add(new ByteDataType());
|
||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1118,9 +1058,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1164,9 +1101,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testDeletedInLatestAddedInMy() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1181,7 +1116,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
Structure s = (Structure) dt;
|
||||
s.add(new ByteDataType());
|
||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1189,9 +1124,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1233,9 +1165,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
public void testCompositeCommentChanged() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
@ -1258,9 +1188,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
|||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
||||
*/
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
|
|
|
@ -21,11 +21,11 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
|
||||
import docking.widgets.OptionDialog;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.database.ProgramModifierListener;
|
||||
import ghidra.program.database.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.data.Enum;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
import ghidra.util.task.TaskMonitorAdapter;
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
// 2 components should get removed from CoolUnion
|
||||
commit = true;
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
// 2 components should get removed from CoolUnion
|
||||
commit = true;
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
// 2 components should get removed from CoolUnion
|
||||
commit = true;
|
||||
}
|
||||
|
@ -296,10 +296,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
setErrorsExpected(true);
|
||||
|
||||
executeMerge();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
executeMerge(true);
|
||||
|
||||
waitForCompletion();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
|
||||
checkConflictCount(0);
|
||||
|
||||
|
@ -573,7 +572,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -646,7 +645,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
// causes Bar to be marked as changed
|
||||
commit = true;
|
||||
}
|
||||
|
@ -720,7 +719,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
// causes Bar to be marked as changed
|
||||
commit = true;
|
||||
}
|
||||
|
@ -796,7 +795,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
Structure ms = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||
"MyStruct");
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
Structure s1 = new StructureDataType(
|
||||
new CategoryPath("/Category1/Category2/Category5"), "s1", 0);
|
||||
s1.add(ms);
|
||||
|
@ -884,6 +883,196 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
assertEquals(3, dtcs.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConflictUpdate5() throws Exception {
|
||||
|
||||
TypeDef td = new TypedefDataType(new CategoryPath("/Category1/Category2"), "BF",
|
||||
IntegerDataType.dataType);
|
||||
|
||||
mtf.initialize("notepad2", new OriginalProgramModifierListener() {
|
||||
|
||||
@Override
|
||||
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
try {
|
||||
dtm.addDataType(td, null);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
DataType dt = dtm.getDataType(new CategoryPath("/Category1/Category2"), "BF");
|
||||
try {
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
Structure s1 = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||
"Structure_1");
|
||||
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||
try {
|
||||
s1.insertBitFieldAt(3, 2, 6, td, 2, "bf1", "my bf1");
|
||||
s1.insertBitFieldAt(3, 2, 4, td, 2, "bf2", "my bf2");
|
||||
foo.add(new FloatDataType());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.toString());
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// bitfield silently transitions to int since typedef BF was removed
|
||||
|
||||
executeMerge();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
|
||||
Structure s1 =
|
||||
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||
assertNotNull(s1);
|
||||
DataTypeComponent[] dtcs = s1.getComponents();
|
||||
assertEquals(7, dtcs.length);
|
||||
|
||||
assertEquals(4, dtcs[3].getOffset()); // base on original 2-byte length 1st byte remains undefined
|
||||
assertEquals("bf1", dtcs[3].getFieldName());
|
||||
assertEquals("my bf1", dtcs[3].getComment());
|
||||
|
||||
DataType dt = dtcs[3].getDataType();
|
||||
assertTrue(dt instanceof BitFieldDataType);
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dt;
|
||||
assertTrue(bfDt.getBaseDataType() instanceof IntegerDataType);
|
||||
assertEquals(2, bfDt.getDeclaredBitSize());
|
||||
assertEquals(6, bfDt.getBitOffset());
|
||||
|
||||
assertEquals(4, dtcs[4].getOffset()); // base on original 2-byte length 1st byte remains undefined
|
||||
assertEquals("bf2", dtcs[4].getFieldName());
|
||||
assertEquals("my bf2", dtcs[4].getComment());
|
||||
|
||||
dt = dtcs[4].getDataType();
|
||||
assertTrue(dt instanceof BitFieldDataType);
|
||||
bfDt = (BitFieldDataType) dt;
|
||||
assertTrue(bfDt.getBaseDataType() instanceof IntegerDataType);
|
||||
assertEquals(2, bfDt.getDeclaredBitSize());
|
||||
assertEquals(4, bfDt.getBitOffset());
|
||||
|
||||
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||
// Structure_1 should contain MY Foo
|
||||
assertEquals(foo, dtcs[5].getDataType());
|
||||
|
||||
dtcs = foo.getComponents();
|
||||
assertEquals(5, dtcs.length);
|
||||
assertTrue(dtcs[4].getDataType().isEquivalent(new FloatDataType()));
|
||||
checkConflictCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConflictUpdate6() throws Exception {
|
||||
|
||||
TypeDef td = new TypedefDataType(new CategoryPath("/Category1/Category2"), "BF",
|
||||
IntegerDataType.dataType);
|
||||
|
||||
mtf.initialize("notepad2", new ProgramModifierListener() {
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
try {
|
||||
// add new BF not compatible with BitFields
|
||||
dtm.addDataType(
|
||||
new StructureDataType(new CategoryPath("/Category1/Category2"), "BF", 0),
|
||||
null);
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
Structure s1 = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||
"Structure_1");
|
||||
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||
try {
|
||||
s1.insertBitFieldAt(3, 2, 6, td, 2, "bf1", "my bf1");
|
||||
s1.insertBitFieldAt(3, 2, 4, td, 2, "bf2", "my bf2");
|
||||
foo.add(new FloatDataType());
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.toString());
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// bitfield silently transitions to BF.conflict since two different BF types were added
|
||||
|
||||
executeMerge();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
|
||||
Structure s1 =
|
||||
(Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||
assertNotNull(s1);
|
||||
DataTypeComponent[] dtcs = s1.getComponents();
|
||||
assertEquals(7, dtcs.length);
|
||||
|
||||
assertEquals(4, dtcs[3].getOffset()); // base on original 2-byte length 1st byte remains undefined
|
||||
assertEquals("bf1", dtcs[3].getFieldName());
|
||||
assertEquals("my bf1", dtcs[3].getComment());
|
||||
|
||||
DataType dt = dtcs[3].getDataType();
|
||||
assertTrue(dt instanceof BitFieldDataType);
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dt;
|
||||
DataType bdt = bfDt.getBaseDataType();
|
||||
assertEquals("/Category1/Category2/BF.conflict", bdt.getPathName());
|
||||
assertTrue(bdt.isEquivalent(td));
|
||||
assertEquals(2, bfDt.getDeclaredBitSize());
|
||||
assertEquals(6, bfDt.getBitOffset());
|
||||
|
||||
assertEquals(4, dtcs[4].getOffset()); // base on original 2-byte length 1st byte remains undefined
|
||||
assertEquals("bf2", dtcs[4].getFieldName());
|
||||
assertEquals("my bf2", dtcs[4].getComment());
|
||||
|
||||
dt = dtcs[4].getDataType();
|
||||
assertTrue(dt instanceof BitFieldDataType);
|
||||
bfDt = (BitFieldDataType) dt;
|
||||
bdt = bfDt.getBaseDataType();
|
||||
assertEquals("/Category1/Category2/BF.conflict", bdt.getPathName());
|
||||
assertTrue(bdt.isEquivalent(td));
|
||||
assertEquals(2, bfDt.getDeclaredBitSize());
|
||||
assertEquals(4, bfDt.getBitOffset());
|
||||
|
||||
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||
// Structure_1 should contain MY Foo
|
||||
assertEquals(foo, dtcs[5].getDataType());
|
||||
|
||||
dtcs = foo.getComponents();
|
||||
assertEquals(5, dtcs.length);
|
||||
assertTrue(dtcs[4].getDataType().isEquivalent(new FloatDataType()));
|
||||
checkConflictCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditUnions() throws Exception {
|
||||
|
||||
|
@ -896,7 +1085,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
// 2 components should get removed from CoolUnion
|
||||
commit = true;
|
||||
}
|
||||
|
@ -988,7 +1177,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
// 2 components should get removed from CoolUnion
|
||||
commit = true;
|
||||
}
|
||||
|
@ -1070,10 +1259,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1157,10 +1346,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1245,10 +1434,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1332,10 +1521,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1425,10 +1614,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1526,10 +1715,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
|
||||
try {
|
||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||
DataType dt =
|
||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
|
@ -1624,4 +1813,109 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
|||
checkConflictCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditUnions9() throws Exception {
|
||||
|
||||
mtf.initialize("notepad", new OriginalProgramModifierListener() {
|
||||
|
||||
@Override
|
||||
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||
boolean commit = false;
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
|
||||
try {
|
||||
Enum enumm = new EnumDataType(new CategoryPath("/Category1"), "XYZ", 1);
|
||||
enumm.add("one", 1);
|
||||
enumm.add("two", 2);
|
||||
enumm.add("three", 3);
|
||||
dtm.addDataType(
|
||||
new TypedefDataType(new CategoryPath("/Category1"), "TD_MyEnum", enumm),
|
||||
null);
|
||||
commit = true;
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, commit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyLatest(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
|
||||
try {
|
||||
DataType enumm = dtm.getDataType(new CategoryPath("/Category1"), "XYZ");
|
||||
dtm.remove(enumm, TaskMonitor.DUMMY);
|
||||
|
||||
Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||
"CoolUnion");
|
||||
// NOTE: bit field component byte sizing is currently auto-sized and packed within unions
|
||||
union.insertBitField(1, IntegerDataType.dataType, 4, "bf1", "latest bf1");
|
||||
union.insertBitField(2, IntegerDataType.dataType, 2, "bf2", "latest bf2");
|
||||
commit = true;
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, commit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyPrivate(ProgramDB program) {
|
||||
boolean commit = false;
|
||||
DataTypeManager dtm = program.getDataTypeManager();
|
||||
int transactionID = program.startTransaction("test");
|
||||
|
||||
try {
|
||||
DataType enumm = dtm.getDataType(new CategoryPath("/Category1"), "XYZ");
|
||||
assertTrue(enumm instanceof Enum);
|
||||
|
||||
Union union = (Union) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||
"CoolUnion");
|
||||
// NOTE: bit field component byte sizing is currently auto-sized and packed within unions
|
||||
union.insertBitField(1, enumm, 4, "BF1", "my bf1");
|
||||
union.insertBitField(2, enumm, 2, "BF2", "my bf2");
|
||||
|
||||
commit = true;
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail();
|
||||
}
|
||||
finally {
|
||||
program.endTransaction(transactionID, commit);
|
||||
}
|
||||
}
|
||||
});
|
||||
executeMerge();
|
||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||
|
||||
chooseOption(DataTypeMergeManager.OPTION_MY);// MY bitfields w/ enum
|
||||
|
||||
waitForCompletion();
|
||||
|
||||
// primitive type of byte used in absence of enum
|
||||
Union union =
|
||||
(Union) dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||
//@formatter:off
|
||||
assertEquals("/Category1/Category2/CoolUnion\n" +
|
||||
"Unaligned\n" +
|
||||
"Union CoolUnion {\n" +
|
||||
" 0 qword 8 null \"\"\n" +
|
||||
" 0 byte:4(4) 1 BF1 \"my bf1\"\n" +
|
||||
" 0 byte:2(6) 1 BF2 \"my bf2\"\n" +
|
||||
" 0 word 2 null \"\"\n" +
|
||||
" 0 undefined * * * * * 4 null \"\"\n" +
|
||||
" 0 DLL_Table 96 null \"\"\n" +
|
||||
" 0 DLL_Table * 4 null \"\"\n" +
|
||||
"}\n" +
|
||||
"Size = 96 Actual Alignment = 1\n", union.toString());
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.merge.datatypes;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
|
@ -163,7 +162,7 @@ public class DataTypeMerge8Test extends AbstractDataTypeMergeTest {
|
|||
JLabel label = (JLabel) TestUtils.getInstanceField("label", logPanel);
|
||||
String statusText = label.getText();
|
||||
String expectedText =
|
||||
"Merging Data Types: Not enough undefined bytes to fit /XYZ in structure " +
|
||||
"Structure Merge: Not enough undefined bytes to fit /XYZ in structure " +
|
||||
"/MISC/ABC at offset 0x4.\nIt needs 3 more byte(s) to be able to fit.";
|
||||
assertTrue(statusText.contains(expectedText));
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataType getParent() {
|
||||
public Composite getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import ghidra.program.model.data.*;
|
|||
import ghidra.program.model.data.AlignedStructurePacker.StructurePackResult;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
/**
|
||||
|
@ -640,6 +641,13 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create copy of structure for target dtm (source archive information is discarded).
|
||||
* WARNING! copying unaligned structures which contain bitfields can produce
|
||||
* invalid results when switching endianess due to the differences in packing order.
|
||||
* @param dtm target data type manager
|
||||
* @return cloned structure
|
||||
*/
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
StructureDataType struct =
|
||||
|
@ -649,6 +657,13 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
return struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create cloned structure for target dtm preserving source archive information.
|
||||
* WARNING! cloning unaligned structures which contain bitfields can produce
|
||||
* invalid results when switching endianess due to the differences in packing order.
|
||||
* @param dtm target data type manager
|
||||
* @return cloned structure
|
||||
*/
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
StructureDataType struct =
|
||||
|
@ -891,12 +906,28 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
@Override
|
||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length, String name,
|
||||
String comment) {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
|
||||
if (offset < 0) {
|
||||
throw new IllegalArgumentException("Offset cannot be negative.");
|
||||
}
|
||||
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||
if (length <= 0) {
|
||||
length = dataType.getLength();
|
||||
}
|
||||
try {
|
||||
return insertBitFieldAt(offset, length, bfDt.getBitOffset(), bfDt.getBaseDataType(),
|
||||
bfDt.getDeclaredBitSize(), name, comment);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = resolve(dataType);
|
||||
|
@ -966,6 +997,10 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
if (ordinal < 0 || ordinal >= numComponents) {
|
||||
throw new ArrayIndexOutOfBoundsException(ordinal);
|
||||
}
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
throw new IllegalArgumentException(
|
||||
"Components may not be replaced with a bit-field");
|
||||
}
|
||||
validateDataType(dataType);
|
||||
|
||||
DataTypeComponent origDtc = getComponent(ordinal);
|
||||
|
@ -1085,19 +1120,14 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
componentAdapter.removeRecord(dtc.getKey());
|
||||
}
|
||||
components.clear();
|
||||
numComponents = 0;
|
||||
structLength = 0;
|
||||
|
||||
if (flexibleArrayComponent != null) {
|
||||
flexibleArrayComponent.getDataType().removeParent(this);
|
||||
componentAdapter.removeRecord(flexibleArrayComponent.getKey());
|
||||
flexibleArrayComponent = null;
|
||||
}
|
||||
if (struct.isNotYetDefined()) {
|
||||
numComponents = 0;
|
||||
structLength = 0;
|
||||
}
|
||||
else {
|
||||
structLength = struct.getLength();
|
||||
numComponents = isInternallyAligned() ? 0 : structLength;
|
||||
}
|
||||
|
||||
setAlignment(struct, false);
|
||||
|
||||
|
@ -1154,14 +1184,17 @@ class StructureDB extends CompositeDB implements Structure {
|
|||
|
||||
private void doReplaceWithUnaligned(Structure struct) throws IOException {
|
||||
// assumes components is clear and that alignment characteristics have been set.
|
||||
if (struct.isNotYetDefined()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: unaligned bitfields should remain unchanged when
|
||||
// transitioning endianess even though it makes little sense.
|
||||
// Unaligned structures are not intended to be portable!
|
||||
structLength = struct.getLength();
|
||||
numComponents = structLength;
|
||||
|
||||
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
||||
for (int i = 0; i < otherComponents.length; i++) {
|
||||
DataTypeComponent dtc = otherComponents[i];
|
||||
|
||||
DataType dt = resolve(dtc.getDataType());
|
||||
checkAncestry(dt);
|
||||
|
||||
|
|
|
@ -196,9 +196,8 @@ public interface Structure extends Composite {
|
|||
public void deleteAtOffset(int offset);
|
||||
|
||||
/**
|
||||
* Remove all components from this structure, effectively setting the
|
||||
* length to zero.
|
||||
*
|
||||
* Remove all components from this structure (including flex-array),
|
||||
* effectively setting the length to zero.
|
||||
*/
|
||||
public void deleteAll();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import ghidra.program.model.data.AlignedStructurePacker.StructurePackResult;
|
|||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.UniversalID;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.InvalidInputException;
|
||||
|
||||
/**
|
||||
|
@ -297,9 +298,25 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
@Override
|
||||
public DataTypeComponentImpl insertAtOffset(int offset, DataType dataType, int length,
|
||||
String componentName, String comment) {
|
||||
|
||||
if (offset < 0) {
|
||||
throw new IllegalArgumentException("Offset cannot be negative.");
|
||||
}
|
||||
|
||||
if (dataType instanceof BitFieldDataType) {
|
||||
BitFieldDataType bfDt = (BitFieldDataType) dataType;
|
||||
if (length <= 0) {
|
||||
length = dataType.getLength();
|
||||
}
|
||||
try {
|
||||
return insertBitFieldAt(offset, length, bfDt.getBitOffset(), bfDt.getBaseDataType(),
|
||||
bfDt.getDeclaredBitSize(), componentName, comment);
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
validateDataType(dataType);
|
||||
|
||||
dataType = dataType.clone(dataMgr);
|
||||
|
@ -524,7 +541,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent insertBitFieldAt(int byteOffset, int byteWidth, int bitOffset,
|
||||
public DataTypeComponentImpl insertBitFieldAt(int byteOffset, int byteWidth, int bitOffset,
|
||||
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||
throws InvalidDataTypeException {
|
||||
|
||||
|
@ -847,6 +864,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
return available;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create copy of structure for target dtm (source archive information is discarded).
|
||||
* WARNING! copying unaligned structures which contain bitfields can produce
|
||||
* invalid results when switching endianess due to the differences in packing order.
|
||||
* @param dtm target data type manager
|
||||
* @return cloned structure
|
||||
*/
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
StructureDataType struct = new StructureDataType(categoryPath, getName(), getLength(), dtm);
|
||||
|
@ -855,6 +879,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
return struct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create cloned structure for target dtm preserving source archive information.
|
||||
* WARNING! cloning unaligned structures which contain bitfields can produce
|
||||
* invalid results when switching endianess due to the differences in packing order.
|
||||
* @param dtm target data type manager
|
||||
* @return cloned structure
|
||||
*/
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
if (dataMgr == dtm) {
|
||||
|
@ -907,15 +938,9 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
int oldLength = structLength;
|
||||
|
||||
components.clear();
|
||||
flexibleArrayComponent = null;
|
||||
if (struct.isNotYetDefined()) {
|
||||
structLength = 0;
|
||||
numComponents = 0;
|
||||
}
|
||||
else {
|
||||
structLength = struct.getLength();
|
||||
numComponents = isInternallyAligned() ? 0 : structLength;
|
||||
}
|
||||
flexibleArrayComponent = null;
|
||||
|
||||
setAlignment(struct);
|
||||
|
||||
|
@ -950,14 +975,17 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
|||
|
||||
private void doReplaceWithUnaligned(Structure struct) {
|
||||
// assumes components is clear and that alignment characteristics have been set.
|
||||
if (struct.isNotYetDefined()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: unaligned bitfields should remain unchanged when
|
||||
// transitioning endianess even though it makes little sense.
|
||||
// Unaligned structures are not intended to be portable!
|
||||
structLength = struct.getLength();
|
||||
numComponents = structLength;
|
||||
|
||||
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
||||
for (int i = 0; i < otherComponents.length; i++) {
|
||||
DataTypeComponent dtc = otherComponents[i];
|
||||
|
||||
DataType dt = dtc.getDataType().clone(dataMgr);
|
||||
checkAncestry(dt);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue