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,
|
BitFieldEditorDialog dlg = new BitFieldEditorDialog(model.viewComposite,
|
||||||
provider.dtmService, editingRow, ordinal -> {
|
provider.dtmService, editingRow, ordinal -> {
|
||||||
model.fireTableDataChanged();
|
model.notifyCompositeChanged();
|
||||||
model.compositeInfoChanged();
|
|
||||||
});
|
});
|
||||||
Component c = provider.getComponent();
|
Component c = provider.getComponent();
|
||||||
Window w = SwingUtilities.windowForComponent(c);
|
Window w = SwingUtilities.windowForComponent(c);
|
||||||
|
|
|
@ -17,6 +17,8 @@ package ghidra.app.merge.datatypes;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -35,38 +37,48 @@ import ghidra.util.task.TaskMonitorAdapter;
|
||||||
public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCategoryAddRemoveDTAdd() throws Exception {
|
public void testCategoryAddRemoveDTAdd() throws Exception {
|
||||||
|
|
||||||
|
TypeDef td = new TypedefDataType("BF", IntegerDataType.dataType);
|
||||||
|
|
||||||
|
AtomicReference<Structure> structRef = new AtomicReference<>();
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
|
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
DataTypeManager dtm = program.getDataTypeManager();
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
int transactionID = program.startTransaction("test");
|
int transactionID = program.startTransaction("test");
|
||||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||||
try {
|
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);
|
Structure struct =
|
||||||
dt.add(new QWordDataType());
|
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;
|
commit = true;
|
||||||
}
|
}
|
||||||
catch (InvalidNameException e) {
|
catch (Exception e) {
|
||||||
Assert.fail("got InvalidNameException!");
|
e.printStackTrace();
|
||||||
|
Assert.fail(e.toString());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, commit);
|
program.endTransaction(transactionID, commit);
|
||||||
|
@ -79,19 +91,19 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category5"));
|
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category5"));
|
||||||
assertNotNull(c);
|
assertNotNull(c);
|
||||||
assertNotNull(c.getDataType("Test"));
|
DataType dt = c.getDataType("Test");
|
||||||
|
assertNotNull(dt);
|
||||||
|
assertTrue(structRef.get().isEquivalent(dt));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeAddedInMy() throws Exception {
|
public void testDataTypeAddedInMy() throws Exception {
|
||||||
|
|
||||||
// A category was added to Category5 in the latest;
|
// A category was added to Category5 in the latest;
|
||||||
// in My program, rename Category5 to "My Category5" and add a new data type
|
// in My program, rename Category5 to "My Category5" and add a new data type
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -157,20 +166,19 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeAddedInMy2() throws Exception {
|
public void testDataTypeAddedInMy2() throws Exception {
|
||||||
|
|
||||||
|
TypeDef td = new TypedefDataType("BF", IntegerDataType.dataType);
|
||||||
|
|
||||||
|
AtomicReference<Structure> structRef = new AtomicReference<>();
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -179,15 +187,24 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) c.getDataType("IntStruct");
|
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 = new StructureDataType(c.getCategoryPath(), "IntStruct", 0, dtm);
|
||||||
s.add(new QWordDataType());
|
s.add(new QWordDataType(), "f1", "my f1");
|
||||||
s.add(new FloatDataType());
|
s.add(new FloatDataType());
|
||||||
s.add(new ByteDataType());
|
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());
|
s.add(new WordDataType());
|
||||||
|
|
||||||
|
structRef.set(s);
|
||||||
|
|
||||||
c.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
c.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Assert.fail(e.toString());
|
||||||
|
}
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, commit);
|
program.endTransaction(transactionID, commit);
|
||||||
}
|
}
|
||||||
|
@ -199,30 +216,25 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||||
DataType dt = c.getDataType("IntStruct");
|
DataType dt = c.getDataType("IntStruct");
|
||||||
assertNotNull(dt);
|
assertNotNull(dt);
|
||||||
assertTrue(dt instanceof Structure);
|
assertTrue(structRef.get().isEquivalent(dt));
|
||||||
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()));
|
|
||||||
|
|
||||||
|
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
|
@Test
|
||||||
public void testDataTypeAddedInMy3() throws Exception {
|
public void testDataTypeAddedInMy3() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -231,7 +243,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
Category c = dtm.getCategory(new CategoryPath("/Category1/Category2/Category3"));
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) c.getDataType("IntStruct");
|
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 = new StructureDataType(c.getCategoryPath(), "IntStruct", 0);
|
||||||
s.add(new QWordDataType());
|
s.add(new QWordDataType());
|
||||||
s.add(new FloatDataType());
|
s.add(new FloatDataType());
|
||||||
|
@ -270,15 +282,13 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeAddedInLatest() throws Exception {
|
public void testDataTypeAddedInLatest() throws Exception {
|
||||||
|
|
||||||
// Add A category to Category5 in the latest, add
|
// Add A category to Category5 in the latest, add
|
||||||
// add a new data type;
|
// add a new data type;
|
||||||
// in My program, rename Category5 to "My Category5"
|
// in My program, rename Category5 to "My Category5"
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -341,14 +348,12 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeAddedInLatest2() throws Exception {
|
public void testDataTypeAddedInLatest2() throws Exception {
|
||||||
|
|
||||||
// A category was added to Category5 in the latest;
|
// A category was added to Category5 in the latest;
|
||||||
// in My program, rename Category5 to "My Category5" and add a new data type
|
// in My program, rename Category5 to "My Category5" and add a new data type
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -418,20 +420,15 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedInMy() throws Exception {
|
public void testDataTypeDeletedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -443,7 +440,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -461,20 +458,15 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeAddedDeletedInMy() throws Exception {
|
public void testDataTypeAddedDeletedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -487,7 +479,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
DataType dt = dtm.addDataType(s, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -505,12 +497,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedChanged() throws Exception {
|
public void testDataTypeDeletedChanged() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -543,7 +530,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -561,12 +548,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedChanged2() throws Exception {
|
public void testDataTypeDeletedChanged2() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -599,7 +581,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"FloatStruct");
|
"FloatStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -616,12 +598,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedChanged3() throws Exception {
|
public void testDataTypeDeletedChanged3() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -631,7 +611,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -639,9 +619,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -669,12 +646,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedInLatest() throws Exception {
|
public void testDataTypeDeletedInLatest() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad2", new ProgramModifierListener() {
|
mtf.initialize("notepad2", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -684,7 +659,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -692,9 +667,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -728,12 +700,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeDeletedInBoth() throws Exception {
|
public void testDataTypeDeletedInBoth() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -745,7 +715,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -753,9 +723,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -767,7 +734,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -785,20 +752,15 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataTypeRenamedInMy() throws Exception {
|
public void testDataTypeRenamedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
// Make no changes to Latest.
|
// Make no changes to Latest.
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -834,12 +796,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRenamedBoth() throws Exception {
|
public void testRenamedBoth() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -902,12 +859,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRenamedBoth2() throws Exception {
|
public void testRenamedBoth2() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -971,12 +923,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletedInMyRenamedInLatest() throws Exception {
|
public void testDeletedInMyRenamedInLatest() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1016,7 +963,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1032,12 +979,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletedInLatestRenamedInMy() throws Exception {
|
public void testDeletedInLatestRenamedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1047,7 +992,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
"IntStruct");
|
"IntStruct");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1055,9 +1000,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1090,12 +1032,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletedInLatestChangedInMy() throws Exception {
|
public void testDeletedInLatestChangedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1110,7 +1050,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
Structure s = (Structure) dt;
|
Structure s = (Structure) dt;
|
||||||
s.add(new ByteDataType());
|
s.add(new ByteDataType());
|
||||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY_MONITOR);
|
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1118,9 +1058,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1161,12 +1098,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeletedInLatestAddedInMy() throws Exception {
|
public void testDeletedInLatestAddedInMy() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1181,7 +1116,7 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
Structure s = (Structure) dt;
|
Structure s = (Structure) dt;
|
||||||
s.add(new ByteDataType());
|
s.add(new ByteDataType());
|
||||||
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
Category parent = dtm.getCategory(new CategoryPath("/Category1/Category2"));
|
||||||
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY_MONITOR);
|
parent.removeCategory("Category3", TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1189,9 +1124,6 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
@ -1230,12 +1162,10 @@ public class DataTypeMerge1Test extends AbstractDataTypeMergeTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCompositeCommentChanged() throws Exception {
|
public void testCompositeCommentChanged() throws Exception {
|
||||||
|
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
boolean commit = false;
|
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
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
|
|
|
@ -21,11 +21,11 @@ import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.*;
|
||||||
import ghidra.program.database.ProgramModifierListener;
|
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.Enum;
|
import ghidra.program.model.data.Enum;
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
import ghidra.util.task.TaskMonitorAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
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
|
// 2 components should get removed from CoolUnion
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
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
|
// 2 components should get removed from CoolUnion
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
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
|
// 2 components should get removed from CoolUnion
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -296,10 +296,9 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
setErrorsExpected(true);
|
setErrorsExpected(true);
|
||||||
|
|
||||||
executeMerge();
|
executeMerge(true);
|
||||||
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
|
||||||
|
|
||||||
waitForCompletion();
|
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||||
|
|
||||||
checkConflictCount(0);
|
checkConflictCount(0);
|
||||||
|
|
||||||
|
@ -573,7 +572,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -646,7 +645,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
// causes Bar to be marked as changed
|
// causes Bar to be marked as changed
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -720,7 +719,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "Structure_1");
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
// causes Bar to be marked as changed
|
// causes Bar to be marked as changed
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -796,7 +795,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
Structure ms = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
Structure ms = (Structure) dtm.getDataType(new CategoryPath("/Category1/Category2"),
|
||||||
"MyStruct");
|
"MyStruct");
|
||||||
try {
|
try {
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
Structure s1 = new StructureDataType(
|
Structure s1 = new StructureDataType(
|
||||||
new CategoryPath("/Category1/Category2/Category5"), "s1", 0);
|
new CategoryPath("/Category1/Category2/Category5"), "s1", 0);
|
||||||
s1.add(ms);
|
s1.add(ms);
|
||||||
|
@ -884,6 +883,196 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
assertEquals(3, dtcs.length);
|
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
|
@Test
|
||||||
public void testEditUnions() throws Exception {
|
public void testEditUnions() throws Exception {
|
||||||
|
|
||||||
|
@ -896,7 +1085,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
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
|
// 2 components should get removed from CoolUnion
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -988,7 +1177,7 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
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
|
// 2 components should get removed from CoolUnion
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
|
@ -1070,10 +1259,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1157,10 +1346,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1245,10 +1434,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1332,10 +1521,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1425,10 +1614,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1526,10 +1715,10 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
Structure s = (Structure) dtm.getDataType(CategoryPath.ROOT, "DLL_Table");
|
||||||
dtm.remove(s, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(s, TaskMonitorAdapter.DUMMY);
|
||||||
DataType dt =
|
DataType dt =
|
||||||
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
dtm.getDataType(new CategoryPath("/Category1/Category2"), "CoolUnion");
|
||||||
dtm.remove(dt, TaskMonitorAdapter.DUMMY_MONITOR);
|
dtm.remove(dt, TaskMonitorAdapter.DUMMY);
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -1624,4 +1813,109 @@ public class DataTypeMerge3Test extends AbstractDataTypeMergeTest {
|
||||||
checkConflictCount(0);
|
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;
|
package ghidra.app.merge.datatypes;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ import ghidra.util.task.TaskMonitorAdapter;
|
||||||
public class DataTypeMerge8Test extends AbstractDataTypeMergeTest {
|
public class DataTypeMerge8Test extends AbstractDataTypeMergeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConflictFixUpForNonFittingStruct() throws Exception {
|
public void testConflictFixUpForNonFittingStruct() throws Exception {
|
||||||
|
|
||||||
final CategoryPath miscPath = new CategoryPath("/MISC");
|
final CategoryPath miscPath = new CategoryPath("/MISC");
|
||||||
final CategoryPath rootPath = new CategoryPath("/");
|
final CategoryPath rootPath = new CategoryPath("/");
|
||||||
|
@ -163,7 +162,7 @@ public class DataTypeMerge8Test extends AbstractDataTypeMergeTest {
|
||||||
JLabel label = (JLabel) TestUtils.getInstanceField("label", logPanel);
|
JLabel label = (JLabel) TestUtils.getInstanceField("label", logPanel);
|
||||||
String statusText = label.getText();
|
String statusText = label.getText();
|
||||||
String expectedText =
|
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.";
|
"/MISC/ABC at offset 0x4.\nIt needs 3 more byte(s) to be able to fit.";
|
||||||
assertTrue(statusText.contains(expectedText));
|
assertTrue(statusText.contains(expectedText));
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType getParent() {
|
public Composite getParent() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import ghidra.program.model.data.*;
|
||||||
import ghidra.program.model.data.AlignedStructurePacker.StructurePackResult;
|
import ghidra.program.model.data.AlignedStructurePacker.StructurePackResult;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
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
|
@Override
|
||||||
public DataType copy(DataTypeManager dtm) {
|
public DataType copy(DataTypeManager dtm) {
|
||||||
StructureDataType struct =
|
StructureDataType struct =
|
||||||
|
@ -649,6 +657,13 @@ class StructureDB extends CompositeDB implements Structure {
|
||||||
return struct;
|
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
|
@Override
|
||||||
public DataType clone(DataTypeManager dtm) {
|
public DataType clone(DataTypeManager dtm) {
|
||||||
StructureDataType struct =
|
StructureDataType struct =
|
||||||
|
@ -891,12 +906,28 @@ class StructureDB extends CompositeDB implements Structure {
|
||||||
@Override
|
@Override
|
||||||
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length, String name,
|
public DataTypeComponent insertAtOffset(int offset, DataType dataType, int length, String name,
|
||||||
String comment) {
|
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(), name, comment);
|
||||||
|
}
|
||||||
|
catch (InvalidDataTypeException e) {
|
||||||
|
throw new AssertException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lock.acquire();
|
lock.acquire();
|
||||||
try {
|
try {
|
||||||
checkDeleted();
|
checkDeleted();
|
||||||
if (offset < 0) {
|
|
||||||
throw new IllegalArgumentException("Offset cannot be negative.");
|
|
||||||
}
|
|
||||||
validateDataType(dataType);
|
validateDataType(dataType);
|
||||||
|
|
||||||
dataType = resolve(dataType);
|
dataType = resolve(dataType);
|
||||||
|
@ -966,6 +997,10 @@ class StructureDB extends CompositeDB implements Structure {
|
||||||
if (ordinal < 0 || ordinal >= numComponents) {
|
if (ordinal < 0 || ordinal >= numComponents) {
|
||||||
throw new ArrayIndexOutOfBoundsException(ordinal);
|
throw new ArrayIndexOutOfBoundsException(ordinal);
|
||||||
}
|
}
|
||||||
|
if (dataType instanceof BitFieldDataType) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Components may not be replaced with a bit-field");
|
||||||
|
}
|
||||||
validateDataType(dataType);
|
validateDataType(dataType);
|
||||||
|
|
||||||
DataTypeComponent origDtc = getComponent(ordinal);
|
DataTypeComponent origDtc = getComponent(ordinal);
|
||||||
|
@ -1085,19 +1120,14 @@ class StructureDB extends CompositeDB implements Structure {
|
||||||
componentAdapter.removeRecord(dtc.getKey());
|
componentAdapter.removeRecord(dtc.getKey());
|
||||||
}
|
}
|
||||||
components.clear();
|
components.clear();
|
||||||
|
numComponents = 0;
|
||||||
|
structLength = 0;
|
||||||
|
|
||||||
if (flexibleArrayComponent != null) {
|
if (flexibleArrayComponent != null) {
|
||||||
flexibleArrayComponent.getDataType().removeParent(this);
|
flexibleArrayComponent.getDataType().removeParent(this);
|
||||||
componentAdapter.removeRecord(flexibleArrayComponent.getKey());
|
componentAdapter.removeRecord(flexibleArrayComponent.getKey());
|
||||||
flexibleArrayComponent = null;
|
flexibleArrayComponent = null;
|
||||||
}
|
}
|
||||||
if (struct.isNotYetDefined()) {
|
|
||||||
numComponents = 0;
|
|
||||||
structLength = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
structLength = struct.getLength();
|
|
||||||
numComponents = isInternallyAligned() ? 0 : structLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAlignment(struct, false);
|
setAlignment(struct, false);
|
||||||
|
|
||||||
|
@ -1154,14 +1184,17 @@ class StructureDB extends CompositeDB implements Structure {
|
||||||
|
|
||||||
private void doReplaceWithUnaligned(Structure struct) throws IOException {
|
private void doReplaceWithUnaligned(Structure struct) throws IOException {
|
||||||
// assumes components is clear and that alignment characteristics have been set.
|
// assumes components is clear and that alignment characteristics have been set.
|
||||||
|
if (struct.isNotYetDefined()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: unaligned bitfields should remain unchanged when
|
structLength = struct.getLength();
|
||||||
// transitioning endianess even though it makes little sense.
|
numComponents = structLength;
|
||||||
// Unaligned structures are not intended to be portable!
|
|
||||||
|
|
||||||
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
||||||
for (int i = 0; i < otherComponents.length; i++) {
|
for (int i = 0; i < otherComponents.length; i++) {
|
||||||
DataTypeComponent dtc = otherComponents[i];
|
DataTypeComponent dtc = otherComponents[i];
|
||||||
|
|
||||||
DataType dt = resolve(dtc.getDataType());
|
DataType dt = resolve(dtc.getDataType());
|
||||||
checkAncestry(dt);
|
checkAncestry(dt);
|
||||||
|
|
||||||
|
|
|
@ -196,9 +196,8 @@ public interface Structure extends Composite {
|
||||||
public void deleteAtOffset(int offset);
|
public void deleteAtOffset(int offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all components from this structure, effectively setting the
|
* Remove all components from this structure (including flex-array),
|
||||||
* length to zero.
|
* effectively setting the length to zero.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public void deleteAll();
|
public void deleteAll();
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import ghidra.program.model.data.AlignedStructurePacker.StructurePackResult;
|
||||||
import ghidra.program.model.mem.MemBuffer;
|
import ghidra.program.model.mem.MemBuffer;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.UniversalID;
|
import ghidra.util.UniversalID;
|
||||||
|
import ghidra.util.exception.AssertException;
|
||||||
import ghidra.util.exception.InvalidInputException;
|
import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,9 +298,25 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
@Override
|
@Override
|
||||||
public DataTypeComponentImpl insertAtOffset(int offset, DataType dataType, int length,
|
public DataTypeComponentImpl insertAtOffset(int offset, DataType dataType, int length,
|
||||||
String componentName, String comment) {
|
String componentName, String comment) {
|
||||||
|
|
||||||
if (offset < 0) {
|
if (offset < 0) {
|
||||||
throw new IllegalArgumentException("Offset cannot be negative.");
|
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);
|
validateDataType(dataType);
|
||||||
|
|
||||||
dataType = dataType.clone(dataMgr);
|
dataType = dataType.clone(dataMgr);
|
||||||
|
@ -524,7 +541,7 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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)
|
DataType baseDataType, int bitSize, String componentName, String comment)
|
||||||
throws InvalidDataTypeException {
|
throws InvalidDataTypeException {
|
||||||
|
|
||||||
|
@ -847,6 +864,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
return available;
|
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
|
@Override
|
||||||
public DataType copy(DataTypeManager dtm) {
|
public DataType copy(DataTypeManager dtm) {
|
||||||
StructureDataType struct = new StructureDataType(categoryPath, getName(), getLength(), dtm);
|
StructureDataType struct = new StructureDataType(categoryPath, getName(), getLength(), dtm);
|
||||||
|
@ -855,6 +879,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
return struct;
|
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
|
@Override
|
||||||
public DataType clone(DataTypeManager dtm) {
|
public DataType clone(DataTypeManager dtm) {
|
||||||
if (dataMgr == dtm) {
|
if (dataMgr == dtm) {
|
||||||
|
@ -907,15 +938,9 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
int oldLength = structLength;
|
int oldLength = structLength;
|
||||||
|
|
||||||
components.clear();
|
components.clear();
|
||||||
|
structLength = 0;
|
||||||
|
numComponents = 0;
|
||||||
flexibleArrayComponent = null;
|
flexibleArrayComponent = null;
|
||||||
if (struct.isNotYetDefined()) {
|
|
||||||
structLength = 0;
|
|
||||||
numComponents = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
structLength = struct.getLength();
|
|
||||||
numComponents = isInternallyAligned() ? 0 : structLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAlignment(struct);
|
setAlignment(struct);
|
||||||
|
|
||||||
|
@ -950,14 +975,17 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
|
||||||
|
|
||||||
private void doReplaceWithUnaligned(Structure struct) {
|
private void doReplaceWithUnaligned(Structure struct) {
|
||||||
// assumes components is clear and that alignment characteristics have been set.
|
// assumes components is clear and that alignment characteristics have been set.
|
||||||
|
if (struct.isNotYetDefined()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: unaligned bitfields should remain unchanged when
|
structLength = struct.getLength();
|
||||||
// transitioning endianess even though it makes little sense.
|
numComponents = structLength;
|
||||||
// Unaligned structures are not intended to be portable!
|
|
||||||
|
|
||||||
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
DataTypeComponent[] otherComponents = struct.getDefinedComponents();
|
||||||
for (int i = 0; i < otherComponents.length; i++) {
|
for (int i = 0; i < otherComponents.length; i++) {
|
||||||
DataTypeComponent dtc = otherComponents[i];
|
DataTypeComponent dtc = otherComponents[i];
|
||||||
|
|
||||||
DataType dt = dtc.getDataType().clone(dataMgr);
|
DataType dt = dtc.getDataType().clone(dataMgr);
|
||||||
checkAncestry(dt);
|
checkAncestry(dt);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue