mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-04 06:34:32 +08:00
GP-1403 Improved support for auto-named typedefs. Updated create
typedef action from pointer to use auto-naming. Replaced old ImageBaseOffsetDataType 32/64-bit BuiltIn types with new pointer-typedef based implementations. Improved settings modification restrictions. Resolved various bugs.
This commit is contained in:
+10
@@ -20,6 +20,7 @@ import java.util.Collection;
|
|||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.docking.settings.SettingsDefinition;
|
import ghidra.docking.settings.SettingsDefinition;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
|
import ghidra.program.model.data.TypeDefSettingsDefinition;
|
||||||
import ghidra.program.model.symbol.RefType;
|
import ghidra.program.model.symbol.RefType;
|
||||||
import ghidra.program.model.symbol.SourceType;
|
import ghidra.program.model.symbol.SourceType;
|
||||||
import ghidra.trace.database.data.DBTraceDataSettingsOperations;
|
import ghidra.trace.database.data.DBTraceDataSettingsOperations;
|
||||||
@@ -68,6 +69,15 @@ public interface DBTraceDataAdapter extends DBTraceCodeUnitAdapter, DataAdapterM
|
|||||||
|
|
||||||
DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent);
|
DBTraceDataSettingsOperations getSettingsSpace(boolean createIfAbsent);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default boolean isChangeAllowed(SettingsDefinition settingsDefinition) {
|
||||||
|
if (settingsDefinition instanceof TypeDefSettingsDefinition) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// assume instance setting allowed if default setting allowed
|
||||||
|
return getDefaultSettings().isChangeAllowed(settingsDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void setLong(String name, long value) {
|
default void setLong(String name, long value) {
|
||||||
try (LockHold hold = getTrace().lockWrite()) {
|
try (LockHold hold = getTrace().lockWrite()) {
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ dependencies {
|
|||||||
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
testImplementation project(path: ':Generic', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
testImplementation project(path: ':Project', configuration: 'testArtifacts')
|
||||||
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
|
testImplementation project(path: ':SoftwareModeling', configuration: 'testArtifacts')
|
||||||
|
testImplementation project(path: ':DB', configuration: 'testArtifacts')
|
||||||
|
|
||||||
javacc 'net.java.dev.javacc:javacc:5.0'
|
javacc 'net.java.dev.javacc:javacc:5.0'
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-7
@@ -800,7 +800,16 @@
|
|||||||
|
|
||||||
<P>A Typedef created with a Pointer base type will allow additional Settings to be made
|
<P>A Typedef created with a Pointer base type will allow additional Settings to be made
|
||||||
which can influence how such a pointer should be interpretted
|
which can influence how such a pointer should be interpretted
|
||||||
(see <A href="#Pointer_Typedef_Settings">Pointer-Typedef Settings</A>).</P>
|
(see <A href="#Pointer_Typedef_Settings">Pointer-Typedef Settings</A>).
|
||||||
|
If no name is assigned to a new Pointer-Typedef is will be treated as an "auto-typedef"
|
||||||
|
where a dynamic name will be assigned based upon the underlying pointer and assigned
|
||||||
|
typedef attribute settings. Examples:
|
||||||
|
<ul>
|
||||||
|
<li><i>char * __((space(ram)))</i></li>
|
||||||
|
<li><i>int * __((offset(0x8)))</i></li>
|
||||||
|
<li><i>pointer __((image-base-relative))</i></li>
|
||||||
|
</ul>
|
||||||
|
</P>
|
||||||
|
|
||||||
<H4>Creating a Pointer</H4>
|
<H4>Creating a Pointer</H4>
|
||||||
<P>To create a <B>pointer</B>, you can click <I><B>New<IMG src="../../shared/arrow.gif"
|
<P>To create a <B>pointer</B>, you can click <I><B>New<IMG src="../../shared/arrow.gif"
|
||||||
@@ -1076,18 +1085,18 @@
|
|||||||
<P>The following Pointer-Typedef settings are currently supported:</P>
|
<P>The following Pointer-Typedef settings are currently supported:</P>
|
||||||
<UL>
|
<UL>
|
||||||
<LI><B>Address Space</B> (case-sensitive string) - Allows a specific address space to be associated with a pointer.
|
<LI><B>Address Space</B> (case-sensitive string) - Allows a specific address space to be associated with a pointer.
|
||||||
If an unknown name is used it will be silently ignored. </LI>
|
If an unknown name is used it will be silently ignored. Auto name attribute format: __((space(<i>name</i>))</LI>
|
||||||
<LI><B>Component Offset</B> (signed value) - Allows a base-relative offset to be specified. When applied
|
<LI><B>Component Offset</B> (signed value) - Allows a base-relative offset to be specified. When applied
|
||||||
to memory an Offset Reference will be generated. I addition, type analysis may use the offset to identify
|
to memory an Offset Reference will be generated. I addition, type analysis may use the offset to identify
|
||||||
a component relative to the pointer's base-datatype (e.g., structure).</LI>
|
a component relative to the pointer's base-datatype (e.g., structure). Auto name attribute format: __((offset(<i>signed_value</i>))</LI>
|
||||||
<LI><B>Offset Mask</B> (64-bit mask) - Allows a bit-mask to be applied to a stored value when computing the
|
<LI><B>Offset Mask</B> (64-bit mask) - Allows a bit-mask to be applied to a stored value when computing the
|
||||||
absolute memory offset. This bit-mask will be applied prior to any applied bit-shift.</LI>
|
absolute memory offset. This bit-mask will be applied prior to any applied bit-shift. Auto name attribute format: __((mask(<i>hex_mask</i>))</LI>
|
||||||
<LI><B>Offset Shift</B> (-64..0..64) - Allows a bit-shift (left=negative, right=positive) to be applied to a
|
<LI><B>Offset Shift</B> (-64..0..64) - Allows a bit-shift (left=negative, right=positive) to be applied to a
|
||||||
stored value when computing the absolute memory offset.</LI>
|
stored value when computing the absolute memory offset. Auto name attribute format: __((shift(<i>bitshift_amount</i>))</LI>
|
||||||
<LI><B>Pointer Type</B> (<I>default, IBO, relative, file-offset</I>) - allows the overall interpretation of a
|
<LI><B>Pointer Type</B> (<I>default, image-base-relative, relative, file-offset</I>) - allows the overall interpretation of a
|
||||||
pointer to be specified. The <I>relative</I> pointer type has limited applicabaility and is only
|
pointer to be specified. The <I>relative</I> pointer type has limited applicabaility and is only
|
||||||
intended to be applied to pointers stored in memory since their storage location is used in computing
|
intended to be applied to pointers stored in memory since their storage location is used in computing
|
||||||
the absolute address that the pointer refers to. (IBO: Image Base Offset Relative).</LI>
|
the absolute address that the pointer refers to.</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<P><IMG src="../../shared/note.png" alt="" border="0">All Typedef Settings must be established on
|
<P><IMG src="../../shared/note.png" alt="" border="0">All Typedef Settings must be established on
|
||||||
|
|||||||
+45
-11
@@ -665,7 +665,6 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
* in RESULT; false if the data type did not have to be added
|
* in RESULT; false if the data type did not have to be added
|
||||||
*/
|
*/
|
||||||
private boolean dataTypeRenamedOrMoved(long id) {
|
private boolean dataTypeRenamedOrMoved(long id) {
|
||||||
|
|
||||||
DataType newDt = null;
|
DataType newDt = null;
|
||||||
|
|
||||||
switch (conflictOption) {
|
switch (conflictOption) {
|
||||||
@@ -700,7 +699,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
DataType resultDt = dtms[RESULT].getDataType(id);
|
DataType resultDt = dtms[RESULT].getDataType(id);
|
||||||
DataType newDt = null;
|
DataType newDt = null;
|
||||||
if (resultDt != null) {
|
if (resultDt != null) {
|
||||||
setDataTypeName(resultDt, dt.getName());
|
setDataTypeName(resultDt, dt);
|
||||||
setCategoryPath(resultDt, dt.getCategoryPath());
|
setCategoryPath(resultDt, dt.getCategoryPath());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1645,8 +1644,12 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String name = category.getName();
|
String newName = category.getName();
|
||||||
String newName = name;
|
String baseName = newName;
|
||||||
|
int index = newName.indexOf(DataType.CONFLICT_SUFFIX);
|
||||||
|
if (index > 0) {
|
||||||
|
baseName = newName.substring(0, index);
|
||||||
|
}
|
||||||
int oneUpNumber = 0;
|
int oneUpNumber = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
@@ -1656,7 +1659,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
++oneUpNumber;
|
++oneUpNumber;
|
||||||
newName = name + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
newName = baseName + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
throw new AssertException("Got DuplicateNameException");
|
throw new AssertException("Got DuplicateNameException");
|
||||||
@@ -1673,6 +1676,11 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String name = newName;
|
String name = newName;
|
||||||
|
String baseName = newName;
|
||||||
|
int index = newName.indexOf(DataType.CONFLICT_SUFFIX);
|
||||||
|
if (index > 0) {
|
||||||
|
baseName = newName.substring(0, index);
|
||||||
|
}
|
||||||
int oneUpNumber = 0;
|
int oneUpNumber = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
@@ -1681,7 +1689,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
++oneUpNumber;
|
++oneUpNumber;
|
||||||
name = newName + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
name = baseName + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
||||||
}
|
}
|
||||||
catch (InvalidNameException e) {
|
catch (InvalidNameException e) {
|
||||||
throw new AssertException("Got InvalidNameException: " + e);
|
throw new AssertException("Got InvalidNameException: " + e);
|
||||||
@@ -1689,20 +1697,31 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setDataTypeName(DataType dt, String newName) {
|
private void setDataTypeName(DataType dt, DataType dtToCopy) {
|
||||||
|
if (isAutoNamedTypedef(dtToCopy)) {
|
||||||
|
if (dt instanceof TypeDef) {
|
||||||
|
((TypeDef) dt).enableAutoNaming();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String newName = dtToCopy.getName();
|
||||||
if (dt.getName().equals(newName)) {
|
if (dt.getName().equals(newName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String name = newName;
|
String baseName = newName;
|
||||||
|
int index = newName.indexOf(DataType.CONFLICT_SUFFIX);
|
||||||
|
if (index > 0) {
|
||||||
|
baseName = newName.substring(0, index);
|
||||||
|
}
|
||||||
int oneUpNumber = 0;
|
int oneUpNumber = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
try {
|
try {
|
||||||
dt.setName(name);
|
dt.setName(newName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (DuplicateNameException e) {
|
catch (DuplicateNameException e) {
|
||||||
++oneUpNumber;
|
++oneUpNumber;
|
||||||
name = newName + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
newName = baseName + DataType.CONFLICT_SUFFIX + oneUpNumber;
|
||||||
}
|
}
|
||||||
catch (InvalidNameException e) {
|
catch (InvalidNameException e) {
|
||||||
throw new AssertException("Got InvalidNameException: " + e);
|
throw new AssertException("Got InvalidNameException: " + e);
|
||||||
@@ -1710,6 +1729,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private boolean categoryWasMoved(long id, DataTypeManager dtm1, DataTypeManager dtm2) {
|
private boolean categoryWasMoved(long id, DataTypeManager dtm1, DataTypeManager dtm2) {
|
||||||
Category cat1 = dtm1.getCategory(id);
|
Category cat1 = dtm1.getCategory(id);
|
||||||
Category cat2 = dtm2.getCategory(id);
|
Category cat2 = dtm2.getCategory(id);
|
||||||
@@ -1765,10 +1785,24 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
return dataTypeWasRenamed(id, dtms[ORIGINAL], dtm);
|
return dataTypeWasRenamed(id, dtms[ORIGINAL], dtm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAutoNamedTypedef(DataType dt) {
|
||||||
|
if (dt instanceof TypeDef) {
|
||||||
|
TypeDef td = (TypeDef) dt;
|
||||||
|
return td.isAutoNamed();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean dataTypeWasRenamed(long id, DataTypeManager dtm1, DataTypeManager dtm2) {
|
private boolean dataTypeWasRenamed(long id, DataTypeManager dtm1, DataTypeManager dtm2) {
|
||||||
DataType dt1 = dtm1.getDataType(id);
|
DataType dt1 = dtm1.getDataType(id);
|
||||||
DataType dt2 = dtm2.getDataType(id);
|
DataType dt2 = dtm2.getDataType(id);
|
||||||
if (dt1 != null && dt2 != null) {
|
if (dt1 != null && dt2 != null) {
|
||||||
|
if (isAutoNamedTypedef(dt1)) {
|
||||||
|
return isAutoNamedTypedef(dt2);
|
||||||
|
}
|
||||||
|
else if (isAutoNamedTypedef(dt2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
String name1 = dt1.getName();
|
String name1 = dt1.getName();
|
||||||
String name2 = dt2.getName();
|
String name2 = dt2.getName();
|
||||||
return !name1.equals(name2);
|
return !name1.equals(name2);
|
||||||
@@ -2695,7 +2729,7 @@ public class DataTypeMergeManager implements MergeResolver {
|
|||||||
DataType dt = dtms[RESULT].getDataType(id);
|
DataType dt = dtms[RESULT].getDataType(id);
|
||||||
if (dataTypeWasRenamed(id, dtms[MY])) {
|
if (dataTypeWasRenamed(id, dtms[MY])) {
|
||||||
if (dt != null) {
|
if (dt != null) {
|
||||||
setDataTypeName(dt, myDt.getName());
|
setDataTypeName(dt, myDt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-25
@@ -57,7 +57,6 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
private int currentConflict;
|
private int currentConflict;
|
||||||
private int totalConflictCount;
|
private int totalConflictCount;
|
||||||
private ProgramMultiUserMergeManager mergeManager;
|
private ProgramMultiUserMergeManager mergeManager;
|
||||||
private int progressIndex;
|
|
||||||
private int propertyListChoice = ASK_USER;
|
private int propertyListChoice = ASK_USER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +156,7 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mergeManager.updateProgress(100);
|
mergeManager.updateProgress(100);
|
||||||
currentMonitor.initialize(myNamesCount);
|
|
||||||
try {
|
try {
|
||||||
processConflicts();
|
processConflicts();
|
||||||
commit = true;
|
commit = true;
|
||||||
@@ -193,7 +192,6 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addProperty(list, resultList, optionName);
|
addProperty(list, resultList, optionName);
|
||||||
currentMonitor.setProgress(++progressIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -251,7 +249,6 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
|
|
||||||
if (latestValue.equals(origValue)) {
|
if (latestValue.equals(origValue)) {
|
||||||
latestList.removeOption(propertyName);
|
latestList.removeOption(propertyName);
|
||||||
currentMonitor.setProgress(++progressIndex);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String listName = latestList.getName();
|
String listName = latestList.getName();
|
||||||
@@ -275,25 +272,28 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
Object resultValue = getValue(resultList, propertyName);
|
Object resultValue = getValue(resultList, propertyName);
|
||||||
Object origValue = getValue(origList, propertyName);
|
Object origValue = getValue(origList, propertyName);
|
||||||
|
|
||||||
if (!SystemUtilities.isEqual(resultValue, myValue)) {
|
if (SystemUtilities.isEqual(origValue, myValue) ||
|
||||||
if (propertyName.equals(Program.ANALYZED) && (myValue instanceof Boolean)) {
|
SystemUtilities.isEqual(resultValue, myValue)) {
|
||||||
// If latest or my version sets "Analyzed" to true, then it should result in true.
|
// value was not modified in my program or it was changed the same as in latest
|
||||||
setValue(resultList, propertyName, myList.getType(propertyName), Boolean.TRUE);
|
return;
|
||||||
currentMonitor.setProgress(++progressIndex);
|
}
|
||||||
return;
|
if (propertyName.equals(Program.ANALYZED) && Boolean.TRUE.equals(myValue)) {
|
||||||
}
|
// If my version sets "Analyzed" to true, then it should result in true.
|
||||||
if (SystemUtilities.isEqual(resultValue, origValue)) {
|
setValue(resultList, propertyName, myList.getType(propertyName), Boolean.TRUE);
|
||||||
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
return;
|
||||||
currentMonitor.setProgress(++progressIndex);
|
}
|
||||||
}
|
if (SystemUtilities.isEqual(resultValue, origValue)) {
|
||||||
else {
|
// no change by latest - use my value
|
||||||
String listName = resultList.getName();
|
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
||||||
ArrayList<ConflictInfo> mapList = getConflictList(listName);
|
}
|
||||||
mapList.add(new ConflictInfo(listName, propertyName,
|
else {
|
||||||
resultList.getType(propertyName), myList.getType(propertyName),
|
// my change conflicts with latest change
|
||||||
origList.getType(propertyName), resultValue, myValue, origValue));
|
String listName = resultList.getName();
|
||||||
++totalConflictCount;
|
ArrayList<ConflictInfo> mapList = getConflictList(listName);
|
||||||
}
|
mapList.add(new ConflictInfo(listName, propertyName,
|
||||||
|
resultList.getType(propertyName), myList.getType(propertyName),
|
||||||
|
origList.getType(propertyName), resultValue, myValue, origValue));
|
||||||
|
++totalConflictCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +322,6 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
|
|
||||||
if (!myValue.equals(origValue)) {
|
if (!myValue.equals(origValue)) {
|
||||||
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
setValue(resultList, propertyName, myList.getType(propertyName), myValue);
|
||||||
currentMonitor.setProgress(++progressIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -412,7 +411,7 @@ public class PropertyListMergeManager implements MergeResolver {
|
|||||||
String currentListName) throws CancelledException {
|
String currentListName) throws CancelledException {
|
||||||
|
|
||||||
for (int i = 0; i < conflictList.size(); i++) {
|
for (int i = 0; i < conflictList.size(); i++) {
|
||||||
currentMonitor.setProgress(++progressIndex);
|
currentMonitor.setProgress(i);
|
||||||
|
|
||||||
ConflictInfo info = conflictList.get(i);
|
ConflictInfo info = conflictList.get(i);
|
||||||
|
|
||||||
|
|||||||
+30
-3
@@ -67,7 +67,11 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
|
|||||||
Settings originalSettings) {
|
Settings originalSettings) {
|
||||||
super(title, true, false, true, false);
|
super(title, true, false, true, false);
|
||||||
this.settingsDefinitions = settingDefinitions;
|
this.settingsDefinitions = settingDefinitions;
|
||||||
settings = new SettingsImpl(originalSettings);
|
settings = new SettingsImpl(originalSettings) {
|
||||||
|
public boolean isChangeAllowed(SettingsDefinition settingsDefinition) {
|
||||||
|
return originalSettings.isChangeAllowed(settingsDefinition);
|
||||||
|
}
|
||||||
|
};
|
||||||
defaultSettings = settings.getDefaultSettings();
|
defaultSettings = settings.getDefaultSettings();
|
||||||
if (originalSettings != null && defaultSettings == null) {
|
if (originalSettings != null && defaultSettings == null) {
|
||||||
// ensure we have defaults to facilitate revert to default
|
// ensure we have defaults to facilitate revert to default
|
||||||
@@ -206,6 +210,17 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
workPanel.add(scrollpane, BorderLayout.CENTER);
|
workPanel.add(scrollpane, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
boolean hasImmutableSettings = false;
|
||||||
|
for (SettingsDefinition def : settingsDefinitions) {
|
||||||
|
if (!settings.isChangeAllowed(def)) {
|
||||||
|
hasImmutableSettings = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasImmutableSettings) {
|
||||||
|
workPanel.add(new JLabel("* Immutable setting"), BorderLayout.SOUTH);
|
||||||
|
}
|
||||||
|
|
||||||
return workPanel;
|
return workPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,6 +381,10 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
|
|||||||
return definition.getName();
|
return definition.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isEditable() {
|
||||||
|
return settings.isChangeAllowed(definition);
|
||||||
|
}
|
||||||
|
|
||||||
Object getSettingsObject() {
|
Object getSettingsObject() {
|
||||||
if (definition instanceof EnumSettingsDefinition) {
|
if (definition instanceof EnumSettingsDefinition) {
|
||||||
StringChoices choices = getChoices((EnumSettingsDefinition) definition);
|
StringChoices choices = getChoices((EnumSettingsDefinition) definition);
|
||||||
@@ -464,7 +483,11 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCellEditable(int row, int col) {
|
public boolean isCellEditable(int row, int col) {
|
||||||
return col != 0;
|
if (col == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SettingsRowObject rowObject = rows.get(row);
|
||||||
|
return rowObject.isEditable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -503,7 +526,11 @@ public abstract class AbstractSettingsDialog extends DialogComponentProvider {
|
|||||||
public Object getColumnValueForRow(SettingsRowObject t, int columnIndex) {
|
public Object getColumnValueForRow(SettingsRowObject t, int columnIndex) {
|
||||||
switch (columnIndex) {
|
switch (columnIndex) {
|
||||||
case 0:
|
case 0:
|
||||||
return t.getName();
|
String name = t.getName();
|
||||||
|
if (!t.isEditable()) {
|
||||||
|
name += "*"; // append immutable indicator
|
||||||
|
}
|
||||||
|
return name;
|
||||||
case 1:
|
case 1:
|
||||||
return t.getSettingsObject();
|
return t.getSettingsObject();
|
||||||
case 2:
|
case 2:
|
||||||
|
|||||||
+2
@@ -63,6 +63,8 @@ public class DataTypeSettingsDialog extends AbstractSettingsDialog {
|
|||||||
if (dtm instanceof DataTypeManagerDB) {
|
if (dtm instanceof DataTypeManagerDB) {
|
||||||
long id = dtm.getID(dt);
|
long id = dtm.getID(dt);
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
|
// FIXME: this does not handle re-mapped BuiltIn datatypes
|
||||||
|
// since multiple instances may be defined
|
||||||
if (dt == dtm.getDataType(id)) {
|
if (dt == dtm.getDataType(id)) {
|
||||||
return; // valid original instance
|
return; // valid original instance
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ public class DataTypeSyncInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getRefDtPath() {
|
public String getRefDtPath() {
|
||||||
return refDt.getPathName();
|
return refDt.getCategoryPath().getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastChangeTime(boolean useSource) {
|
public long getLastChangeTime(boolean useSource) {
|
||||||
|
|||||||
+25
-3
@@ -119,7 +119,7 @@ public class DataTypeSynchronizer {
|
|||||||
long lastChangeTime = refDT.getLastChangeTime();
|
long lastChangeTime = refDT.getLastChangeTime();
|
||||||
DataType sourceDT = sourceDTM.resolve(refDT, DataTypeConflictHandler.REPLACE_HANDLER);
|
DataType sourceDT = sourceDTM.resolve(refDT, DataTypeConflictHandler.REPLACE_HANDLER);
|
||||||
if (!namesAreEquivalent(refDT, sourceDT)) {
|
if (!namesAreEquivalent(refDT, sourceDT)) {
|
||||||
renameDataType(sourceDTM, sourceDT, refDT.getName());
|
renameDataType(sourceDTM, sourceDT, refDT);
|
||||||
}
|
}
|
||||||
if (!StringUtils.equals(refDT.getDescription(), sourceDT.getDescription())) {
|
if (!StringUtils.equals(refDT.getDescription(), sourceDT.getDescription())) {
|
||||||
sourceDT.setDescription(refDT.getDescription());
|
sourceDT.setDescription(refDT.getDescription());
|
||||||
@@ -132,7 +132,7 @@ public class DataTypeSynchronizer {
|
|||||||
long lastChangeTime = sourceDT.getLastChangeTime();
|
long lastChangeTime = sourceDT.getLastChangeTime();
|
||||||
DataType refDT = refDTM.resolve(sourceDT, DataTypeConflictHandler.REPLACE_HANDLER);
|
DataType refDT = refDTM.resolve(sourceDT, DataTypeConflictHandler.REPLACE_HANDLER);
|
||||||
if (!namesAreEquivalent(refDT, sourceDT)) {
|
if (!namesAreEquivalent(refDT, sourceDT)) {
|
||||||
renameDataType(refDTM, refDT, sourceDT.getName());
|
renameDataType(refDTM, refDT, sourceDT);
|
||||||
}
|
}
|
||||||
if (!StringUtils.equals(sourceDT.getDescription(), refDT.getDescription())) {
|
if (!StringUtils.equals(sourceDT.getDescription(), refDT.getDescription())) {
|
||||||
refDT.setDescription(sourceDT.getDescription());
|
refDT.setDescription(sourceDT.getDescription());
|
||||||
@@ -231,7 +231,15 @@ public class DataTypeSynchronizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renameDataType(DataTypeManager sourceDTM, DataType sourceDT, String name) {
|
private static void renameDataType(DataTypeManager sourceDTM, DataType sourceDT,
|
||||||
|
DataType dtToCopy) {
|
||||||
|
if (isAutoNamedTypedef(dtToCopy)) {
|
||||||
|
if (sourceDT instanceof TypeDef) {
|
||||||
|
((TypeDef) sourceDT).enableAutoNaming();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String name = dtToCopy.getName();
|
||||||
int index = name.indexOf(DataType.CONFLICT_SUFFIX);
|
int index = name.indexOf(DataType.CONFLICT_SUFFIX);
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
name = name.substring(0, index);
|
name = name.substring(0, index);
|
||||||
@@ -254,7 +262,21 @@ public class DataTypeSynchronizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isAutoNamedTypedef(DataType dt) {
|
||||||
|
if (dt instanceof TypeDef) {
|
||||||
|
TypeDef td = (TypeDef) dt;
|
||||||
|
return td.isAutoNamed();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean namesAreEquivalent(DataType dt1, DataType dt2) {
|
public static boolean namesAreEquivalent(DataType dt1, DataType dt2) {
|
||||||
|
if (isAutoNamedTypedef(dt1)) {
|
||||||
|
return isAutoNamedTypedef(dt2);
|
||||||
|
}
|
||||||
|
else if (isAutoNamedTypedef(dt2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
String name1 = dt1.getName();
|
String name1 = dt1.getName();
|
||||||
String name2 = dt2.getName();
|
String name2 = dt2.getName();
|
||||||
if (name1.equals(name2)) {
|
if (name1.equals(name2)) {
|
||||||
|
|||||||
+33
-9
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,16 +15,17 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.datamgr.actions;
|
package ghidra.app.plugin.core.datamgr.actions;
|
||||||
|
|
||||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
|
||||||
import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
|
|
||||||
import ghidra.program.model.data.*;
|
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.ComponentProvider;
|
import docking.ComponentProvider;
|
||||||
import docking.action.DockingAction;
|
import docking.action.DockingAction;
|
||||||
import docking.widgets.tree.GTreeNode;
|
import docking.widgets.tree.GTreeNode;
|
||||||
|
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||||
|
import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
|
||||||
abstract class AbstractTypeDefAction extends DockingAction {
|
abstract class AbstractTypeDefAction extends DockingAction {
|
||||||
|
|
||||||
@@ -55,15 +55,27 @@ abstract class AbstractTypeDefAction extends DockingAction {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createNewDataType(gTree, dataType, categoryPath, dataTypeManager, typeDefName);
|
if (StringUtils.isBlank(typeDefName)) {
|
||||||
|
// use auto-naming for pointer-typedef
|
||||||
|
if (dataType instanceof Pointer) {
|
||||||
|
// category ignored
|
||||||
|
TypeDef typedef = new PointerTypedef(null, (Pointer) dataType, dataTypeManager);
|
||||||
|
return createNewTypeDef(gTree, typedef, categoryPath, dataTypeManager);
|
||||||
|
}
|
||||||
|
// generate default typedef name
|
||||||
|
String baseName = getBaseName(dataType) + "Typedef";
|
||||||
|
typeDefName = dataTypeManager.getUniqueName(dataType.getCategoryPath(), baseName);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeDef typedef = new TypedefDataType(categoryPath, typeDefName, dataType);
|
||||||
|
return createNewTypeDef(gTree, typedef, categoryPath, dataTypeManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataType createNewDataType(Component parentComponent, DataType dataType,
|
private DataType createNewTypeDef(Component parentComponent, TypeDef typedef,
|
||||||
CategoryPath categoryPath, DataTypeManager dataTypeManager, String name) {
|
CategoryPath categoryPath, DataTypeManager dataTypeManager) {
|
||||||
DataType newdt = null;
|
DataType newdt = null;
|
||||||
int transactionID = dataTypeManager.startTransaction("Create Typedef");
|
int transactionID = dataTypeManager.startTransaction("Create Typedef");
|
||||||
try {
|
try {
|
||||||
DataType typedef = new TypedefDataType(categoryPath, name, dataType);
|
|
||||||
newdt = dataTypeManager.addDataType(typedef, plugin.getConflictHandler());
|
newdt = dataTypeManager.addDataType(typedef, plugin.getConflictHandler());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@@ -72,4 +84,16 @@ abstract class AbstractTypeDefAction extends DockingAction {
|
|||||||
|
|
||||||
return newdt;
|
return newdt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static String getBaseName(DataType dt) {
|
||||||
|
if (dt instanceof Pointer) {
|
||||||
|
DataType dataType = ((Pointer) dt).getDataType();
|
||||||
|
if (dataType == null) {
|
||||||
|
// must be a generic pointer type
|
||||||
|
return dt.getName();
|
||||||
|
}
|
||||||
|
return getBaseName(dataType) + "Ptr";
|
||||||
|
}
|
||||||
|
return dt.getDisplayName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-14
@@ -113,16 +113,15 @@ public class CreateTypeDefAction extends AbstractTypeDefAction {
|
|||||||
DataTypeNode dataTypeNode = (DataTypeNode) selectionPaths[0].getLastPathComponent();
|
DataTypeNode dataTypeNode = (DataTypeNode) selectionPaths[0].getLastPathComponent();
|
||||||
DataType dataType = dataTypeNode.getDataType();
|
DataType dataType = dataTypeNode.getDataType();
|
||||||
|
|
||||||
String baseName = getBaseName(dataType) + "Typedef";
|
|
||||||
DerivativeDataTypeInfo info =
|
DerivativeDataTypeInfo info =
|
||||||
new DerivativeDataTypeInfo(plugin, gTree, dataTypeNode, dataType);
|
new DerivativeDataTypeInfo(plugin, gTree, dataTypeNode, dataType);
|
||||||
|
|
||||||
DataTypeManager dataTypeManager = info.getDataTypeManager();
|
DataTypeManager dataTypeManager = info.getDataTypeManager();
|
||||||
String name = dataTypeManager.getUniqueName(dataType.getCategoryPath(), baseName);
|
|
||||||
|
|
||||||
CategoryPath categoryPath = info.getCategoryPath();
|
CategoryPath categoryPath = info.getCategoryPath();
|
||||||
DataType newTypeDef = createTypeDef(dataTypeManager, dataType, categoryPath, context,
|
DataType newTypeDef = createTypeDef(dataTypeManager, dataType, categoryPath, context,
|
||||||
dataTypeNode.getParent(), name);
|
dataTypeNode.getParent(), null);
|
||||||
if (newTypeDef == null) {
|
if (newTypeDef == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -133,15 +132,5 @@ public class CreateTypeDefAction extends AbstractTypeDefAction {
|
|||||||
gTree.startEditing(finalParentNode, newNodeName);
|
gTree.startEditing(finalParentNode, newNodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getBaseName(DataType dt) {
|
|
||||||
if (dt instanceof Pointer) {
|
|
||||||
DataType dataType = ((Pointer) dt).getDataType();
|
|
||||||
if (dataType == null) {
|
|
||||||
// must be a generic pointer type
|
|
||||||
return dt.getName();
|
|
||||||
}
|
|
||||||
return getBaseName(dataType) + "Ptr";
|
|
||||||
}
|
|
||||||
return dt.getDisplayName();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -176,6 +176,13 @@ public abstract class AbstractReferenceHover extends AbstractConfigurableHover {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (programLocation instanceof MnemonicFieldLocation) {
|
||||||
|
CodeUnit cu = program.getListing().getCodeUnitAt(programLocation.getAddress());
|
||||||
|
if (!(cu instanceof Instruction)) {
|
||||||
|
return null; // defer to mnemonic hover for Data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Address refAddr = programLocation.getRefAddress();
|
Address refAddr = programLocation.getRefAddress();
|
||||||
if (refAddr != null && refAddr.isExternalAddress()) {
|
if (refAddr != null && refAddr.isExternalAddress()) {
|
||||||
return createExternalToolTipComponent(program, refAddr);
|
return createExternalToolTipComponent(program, refAddr);
|
||||||
|
|||||||
@@ -118,7 +118,6 @@ class DbViewerComponent extends JPanel {
|
|||||||
if (dbh == null) {
|
if (dbh == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Msg.info(this, "Updating dbViewer...");
|
|
||||||
synchronized (dbh) {
|
synchronized (dbh) {
|
||||||
updateTableChoices((TableItem) combo.getSelectedItem());
|
updateTableChoices((TableItem) combo.getSelectedItem());
|
||||||
updateTable();
|
updateTable();
|
||||||
|
|||||||
@@ -70,11 +70,11 @@ public interface StructConverter {
|
|||||||
/**
|
/**
|
||||||
* Reusable 32-bit image base offset datatype.
|
* Reusable 32-bit image base offset datatype.
|
||||||
*/
|
*/
|
||||||
public final static DataType IBO32 = new ImageBaseOffset32DataType();
|
public final static DataType IBO32 = IBO32DataType.dataType;
|
||||||
/**
|
/**
|
||||||
* Reusable 64-bit image base offset datatype.
|
* Reusable 64-bit image base offset datatype.
|
||||||
*/
|
*/
|
||||||
public final static DataType IBO64 = new ImageBaseOffset64DataType();
|
public final static DataType IBO64 = IBO64DataType.dataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a structure datatype representing the
|
* Returns a structure datatype representing the
|
||||||
|
|||||||
+2
-2
@@ -173,7 +173,7 @@ public class ControlFlowGuard {
|
|||||||
IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK) >> IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT;
|
IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK) >> IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT;
|
||||||
|
|
||||||
// Pre-define base data types used to define table entry data type
|
// Pre-define base data types used to define table entry data type
|
||||||
DataType ibo32 = new ImageBaseOffset32DataType();
|
DataType ibo32 = new IBO32DataType();
|
||||||
DataType byteType = ByteDataType.dataType;
|
DataType byteType = ByteDataType.dataType;
|
||||||
|
|
||||||
CategoryPath categoryPath = new CategoryPath(CategoryPath.ROOT, "CFG");
|
CategoryPath categoryPath = new CategoryPath(CategoryPath.ROOT, "CFG");
|
||||||
@@ -255,7 +255,7 @@ public class ControlFlowGuard {
|
|||||||
program.getSymbolTable()
|
program.getSymbolTable()
|
||||||
.createLabel(tableAddr, GuardCFAddressTakenIatTableName, SourceType.IMPORTED);
|
.createLabel(tableAddr, GuardCFAddressTakenIatTableName, SourceType.IMPORTED);
|
||||||
// Each table entry is an RVA (32-bit image base offset)
|
// Each table entry is an RVA (32-bit image base offset)
|
||||||
DataType ibo32 = new ImageBaseOffset32DataType();
|
DataType ibo32 = new IBO32DataType();
|
||||||
for (long i = 0; i < functionCount; i++) {
|
for (long i = 0; i < functionCount; i++) {
|
||||||
Data d =
|
Data d =
|
||||||
PeUtils.createData(program, tableAddr.add(i * ibo32.getLength()), ibo32, log);
|
PeUtils.createData(program, tableAddr.add(i * ibo32.getLength()), ibo32, log);
|
||||||
|
|||||||
+1
-1
@@ -299,7 +299,7 @@ public class DelayImportDescriptor implements StructConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType toDataType() throws DuplicateNameException, IOException {
|
public DataType toDataType() throws DuplicateNameException, IOException {
|
||||||
DataType ibo32 = new ImageBaseOffset32DataType();
|
DataType ibo32 = new IBO32DataType();
|
||||||
StructureDataType struct = new StructureDataType(NAME, 0);
|
StructureDataType struct = new StructureDataType(NAME, 0);
|
||||||
struct.add(DWORD, "grAttrs", null);
|
struct.add(DWORD, "grAttrs", null);
|
||||||
struct.add(ibo32, "szName", null);
|
struct.add(ibo32, "szName", null);
|
||||||
|
|||||||
+2
-1
@@ -84,7 +84,8 @@ public class LoadConfigDataDirectory extends DataDirectory {
|
|||||||
if (monitor.isCancelled()) {
|
if (monitor.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DataType dt = ntHeader.getOptionalHeader().is64bit() ? new ImageBaseOffset64DataType() : new ImageBaseOffset32DataType();
|
DataType dt = ntHeader.getOptionalHeader().is64bit() ? IBO64DataType.dataType
|
||||||
|
: IBO32DataType.dataType;
|
||||||
|
|
||||||
PeUtils.createData(program, addr, dt, log);
|
PeUtils.createData(program, addr, dt, log);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ public class PEx64UnwindInfoDataType extends DynamicDataType {
|
|||||||
private final static int UNWIND_OP_INFO_FIELD_LENGTH = 0x04;
|
private final static int UNWIND_OP_INFO_FIELD_LENGTH = 0x04;
|
||||||
|
|
||||||
private final static DataType BYTE = ByteDataType.dataType;
|
private final static DataType BYTE = ByteDataType.dataType;
|
||||||
private final static DataType IBO32 = new ImageBaseOffset32DataType();
|
private final static DataType IBO32 = new IBO32DataType();
|
||||||
|
|
||||||
public PEx64UnwindInfoDataType() {
|
public PEx64UnwindInfoDataType() {
|
||||||
this(null);
|
this(null);
|
||||||
|
|||||||
+1
-1
@@ -273,7 +273,7 @@ public class MSDataTypeUtils {
|
|||||||
*/
|
*/
|
||||||
public static DataType getReferenceDataType(Program program, DataType referredToDataType) {
|
public static DataType getReferenceDataType(Program program, DataType referredToDataType) {
|
||||||
DataTypeManager dtm = program.getDataTypeManager();
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
return is64Bit(program) ? new ImageBaseOffset32DataType(dtm)
|
return is64Bit(program) ? new IBO32DataType(dtm)
|
||||||
: new PointerDataType(referredToDataType);
|
: new PointerDataType(referredToDataType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-3
@@ -86,9 +86,6 @@ public class TypeDefDataTypeHTMLRepresentation extends HTMLDataTypeRepresentatio
|
|||||||
DataType basedataType = dataType;
|
DataType basedataType = dataType;
|
||||||
while (basedataType instanceof TypeDef) {
|
while (basedataType instanceof TypeDef) {
|
||||||
basedataType = ((TypeDef) basedataType).getDataType();
|
basedataType = ((TypeDef) basedataType).getDataType();
|
||||||
while (basedataType instanceof Pointer) {
|
|
||||||
basedataType = ((Pointer) basedataType).getDataType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return basedataType;
|
return basedataType;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -71,6 +71,11 @@ public class ByteCountSettingsDefinition implements EnumSettingsDefinition {
|
|||||||
return BYTE_COUNT;
|
return BYTE_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return BYTE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Selects the number of bytes to display";
|
return "Selects the number of bytes to display";
|
||||||
|
|||||||
+5
@@ -90,6 +90,11 @@ public class CodeUnitCountSettingsDefinition implements EnumSettingsDefinition {
|
|||||||
return CODE_UNIT_COUNT;
|
return CODE_UNIT_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return CODE_UNIT_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Selects the number of bytes to display";
|
return "Selects the number of bytes to display";
|
||||||
|
|||||||
+5
@@ -92,6 +92,11 @@ public class CodeUnitOffsetSettingsDefinition implements EnumSettingsDefinition
|
|||||||
return MEMORY_OFFSET;
|
return MEMORY_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return MEMORY_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Selects the relative byte offset from which to display";
|
return "Selects the relative byte offset from which to display";
|
||||||
|
|||||||
+5
@@ -77,6 +77,11 @@ public class FunctionInlineSettingsDefinition implements BooleanSettingsDefiniti
|
|||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return INLINE;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasValue(Settings settings) {
|
public boolean hasValue(Settings settings) {
|
||||||
return settings.getValue(INLINE) != null;
|
return settings.getValue(INLINE) != null;
|
||||||
|
|||||||
+5
@@ -77,6 +77,11 @@ public class FunctionNoReturnSettingsDefinition implements BooleanSettingsDefini
|
|||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return NORETURN;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasValue(Settings settings) {
|
public boolean hasValue(Settings settings) {
|
||||||
return settings.getValue(NORETURN) != null;
|
return settings.getValue(NORETURN) != null;
|
||||||
|
|||||||
+5
@@ -76,6 +76,11 @@ public class FunctionThunkSettingsDefinition implements BooleanSettingsDefinitio
|
|||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return THUNK;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasValue(Settings settings) {
|
public boolean hasValue(Settings settings) {
|
||||||
return settings.getValue(THUNK) != null;
|
return settings.getValue(THUNK) != null;
|
||||||
|
|||||||
+5
@@ -91,6 +91,11 @@ public class MemoryOffsetSettingsDefinition implements EnumSettingsDefinition {
|
|||||||
return MEMORY_OFFSET;
|
return MEMORY_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStorageKey() {
|
||||||
|
return MEMORY_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return "Selects the relative byte offset from which to display";
|
return "Selects the relative byte offset from which to display";
|
||||||
|
|||||||
+207
-1
@@ -24,6 +24,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import ghidra.docking.settings.Settings;
|
import ghidra.docking.settings.Settings;
|
||||||
import ghidra.program.database.*;
|
import ghidra.program.database.*;
|
||||||
|
import ghidra.program.database.data.DataTypeUtilities;
|
||||||
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.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
@@ -1433,7 +1434,7 @@ public class DataTypeMerge5Test extends AbstractDataTypeMergeTest {
|
|||||||
// NOTE: these are not viable settings but are intended to exercise all of them
|
// NOTE: these are not viable settings but are intended to exercise all of them
|
||||||
Settings settings = td.getDefaultSettings();
|
Settings settings = td.getDefaultSettings();
|
||||||
PointerTypeSettingsDefinition.DEF.setType(settings,
|
PointerTypeSettingsDefinition.DEF.setType(settings,
|
||||||
PointerType.IBO);
|
PointerType.IMAGE_BASE_RELATIVE);
|
||||||
AddressSpaceSettingsDefinition.DEF.setValue(settings, "ROM");
|
AddressSpaceSettingsDefinition.DEF.setValue(settings, "ROM");
|
||||||
ComponentOffsetSettingsDefinition.DEF.setValue(settings, 0x10);
|
ComponentOffsetSettingsDefinition.DEF.setValue(settings, 0x10);
|
||||||
OffsetMaskSettingsDefinition.DEF.setValue(settings, 0x1234);
|
OffsetMaskSettingsDefinition.DEF.setValue(settings, 0x1234);
|
||||||
@@ -1515,6 +1516,211 @@ public class DataTypeMerge5Test extends AbstractDataTypeMergeTest {
|
|||||||
checkConflictCount(0);
|
checkConflictCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String formatAttributes(String attrs) {
|
||||||
|
StringBuilder buf = new StringBuilder(DataType.TYPEDEF_ATTRIBUTE_PREFIX);
|
||||||
|
buf.append(attrs);
|
||||||
|
buf.append(DataType.TYPEDEF_ATTRIBUTE_SUFFIX);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTypeDefs11() throws Exception {
|
||||||
|
|
||||||
|
// Exercise pointer-typedef auto-naming with setting changes
|
||||||
|
|
||||||
|
mtf.initialize("notepad2", new OriginalProgramModifierListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||||
|
boolean commit = false;
|
||||||
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
// must specify datatype manager when constructing to allow for settings to be made
|
||||||
|
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||||
|
PointerTypedef td =
|
||||||
|
new PointerTypedef(null, foo, -1, dtm, PointerType.IMAGE_BASE_RELATIVE);
|
||||||
|
DataType dt = dtm.resolve(td, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||||
|
assertEquals("Foo * " + formatAttributes("image-base-relative"), dt.getName());
|
||||||
|
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 {
|
||||||
|
TypeDef td = (TypeDef) dtm.getDataType(new CategoryPath("/MISC"),
|
||||||
|
"Foo * " + formatAttributes("image-base-relative"));
|
||||||
|
assertNotNull(td);
|
||||||
|
td.setName("Bob_Ptr_Td");
|
||||||
|
|
||||||
|
Settings settings = td.getDefaultSettings();
|
||||||
|
PointerTypeSettingsDefinition.DEF.setType(settings,
|
||||||
|
PointerType.RELATIVE);
|
||||||
|
|
||||||
|
Structure st = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||||
|
st.setName("Bob");
|
||||||
|
|
||||||
|
commit = true;
|
||||||
|
}
|
||||||
|
catch (InvalidNameException | DuplicateNameException e) {
|
||||||
|
failWithException("unexpected", e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, commit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyPrivate(ProgramDB program) {
|
||||||
|
boolean commit = false;
|
||||||
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
TypeDef td = (TypeDef) dtm.getDataType(new CategoryPath("/MISC"),
|
||||||
|
"Foo * " + formatAttributes("image-base-relative"));
|
||||||
|
assertNotNull(td);
|
||||||
|
|
||||||
|
Settings settings = td.getDefaultSettings();
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.setValue(settings, 0x123);
|
||||||
|
|
||||||
|
Structure st = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||||
|
st.setName("Bill");
|
||||||
|
|
||||||
|
commit = true;
|
||||||
|
}
|
||||||
|
catch (InvalidNameException | DuplicateNameException e) {
|
||||||
|
failWithException("unexpected", e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, commit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
executeMerge();
|
||||||
|
|
||||||
|
chooseOption(DataTypeMergeManager.OPTION_MY); // choose Bill rename of Foo
|
||||||
|
chooseOption(DataTypeMergeManager.OPTION_LATEST); // choose RELATIVE setting and Bob_Ptr_Td rename
|
||||||
|
|
||||||
|
waitForCompletion();
|
||||||
|
|
||||||
|
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||||
|
TypeDef td = (TypeDef) dtm.getDataType(new CategoryPath("/MISC"), "Bob_Ptr_Td");
|
||||||
|
assertNotNull(td);
|
||||||
|
|
||||||
|
DataType dt = DataTypeUtilities.getBaseDataType(td.getDataType());
|
||||||
|
assertTrue(dt instanceof Structure);
|
||||||
|
assertEquals("Bill", dt.getName());
|
||||||
|
|
||||||
|
Settings settings = td.getDefaultSettings();
|
||||||
|
assertEquals(
|
||||||
|
"Expected pointer-typedef type: relative",
|
||||||
|
PointerType.RELATIVE, PointerTypeSettingsDefinition.DEF.getType(settings));
|
||||||
|
assertFalse(
|
||||||
|
"Unexpected setting: " +
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.getAttributeSpecification(settings),
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.hasValue(settings));
|
||||||
|
|
||||||
|
checkConflictCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTypeDefs12() throws Exception {
|
||||||
|
|
||||||
|
// Exercise pointer-typedef auto-naming with setting changes
|
||||||
|
|
||||||
|
mtf.initialize("notepad2", new OriginalProgramModifierListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||||
|
boolean commit = false;
|
||||||
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
// must specify datatype manager when constructing to allow for settings to be made
|
||||||
|
Structure foo = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||||
|
PointerTypedef td =
|
||||||
|
new PointerTypedef(null, foo, -1, dtm, PointerType.IMAGE_BASE_RELATIVE);
|
||||||
|
DataType dt = dtm.resolve(td, DataTypeConflictHandler.DEFAULT_HANDLER);
|
||||||
|
assertEquals("Foo * " + formatAttributes("image-base-relative"), dt.getName());
|
||||||
|
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 {
|
||||||
|
TypeDef td = (TypeDef) dtm.getDataType(new CategoryPath("/MISC"),
|
||||||
|
"Foo * " + formatAttributes("image-base-relative"));
|
||||||
|
assertNotNull(td);
|
||||||
|
td.setName("Bob_Ptr_Td");
|
||||||
|
|
||||||
|
Settings settings = td.getDefaultSettings();
|
||||||
|
PointerTypeSettingsDefinition.DEF.setType(settings,
|
||||||
|
PointerType.RELATIVE);
|
||||||
|
|
||||||
|
commit = true;
|
||||||
|
}
|
||||||
|
catch (InvalidNameException | DuplicateNameException e) {
|
||||||
|
failWithException("unexpected", e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, commit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyPrivate(ProgramDB program) {
|
||||||
|
boolean commit = false;
|
||||||
|
DataTypeManager dtm = program.getDataTypeManager();
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
Structure st = (Structure) dtm.getDataType(new CategoryPath("/MISC"), "Foo");
|
||||||
|
st.setName("Bill");
|
||||||
|
commit = true;
|
||||||
|
}
|
||||||
|
catch (InvalidNameException | DuplicateNameException e) {
|
||||||
|
failWithException("unexpected", e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, commit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
executeMerge(true);
|
||||||
|
|
||||||
|
DataTypeManager dtm = resultProgram.getDataTypeManager();
|
||||||
|
TypeDef td = (TypeDef) dtm.getDataType(new CategoryPath("/MISC"), "Bob_Ptr_Td");
|
||||||
|
assertNotNull(td);
|
||||||
|
|
||||||
|
DataType dt = DataTypeUtilities.getBaseDataType(td.getDataType());
|
||||||
|
assertTrue(dt instanceof Structure);
|
||||||
|
assertEquals("Bill", dt.getName());
|
||||||
|
|
||||||
|
Settings settings = td.getDefaultSettings();
|
||||||
|
assertEquals(
|
||||||
|
"Expected pointer-typedef type: relative",
|
||||||
|
PointerType.RELATIVE, PointerTypeSettingsDefinition.DEF.getType(settings));
|
||||||
|
assertFalse(
|
||||||
|
"Unexpected setting: " +
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.getAttributeSpecification(settings),
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.hasValue(settings));
|
||||||
|
|
||||||
|
checkConflictCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testArrays() throws Exception {
|
public void testArrays() throws Exception {
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -15,8 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.merge.listing;
|
package ghidra.app.merge.listing;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
@@ -1165,7 +1164,7 @@ public class ProgramContextMergeManagerTest extends AbstractListingMergeManagerT
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Address addr(String address) {
|
public Address addr(String address) {
|
||||||
return mtf.getResultProgram().getAddressFactory().getAddress(address);
|
return mtf.getOriginalProgram().getAddressFactory().getAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setRegValue(ProgramContext pc, Address start, Address end, Register reg,
|
private void setRegValue(ProgramContext pc, Address start, Address end, Register reg,
|
||||||
|
|||||||
+30
-37
@@ -522,19 +522,7 @@ public class PropertyListMergeManager2Test extends AbstractMergeTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnalyzedFalseInLatest() throws Exception {
|
public void testAnalyzedFalseInLatest() throws Exception {
|
||||||
mtf.initialize("notepad", new OriginalProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void modifyOriginal(ProgramDB program) throws Exception {
|
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
|
||||||
Options list = program.getOptions("Program Information");
|
|
||||||
list.setBoolean("Analyzed", false);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
@@ -605,19 +593,7 @@ public class PropertyListMergeManager2Test extends AbstractMergeTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAnalyzedFalseInMy() throws Exception {
|
public void testAnalyzedFalseInMy() throws Exception {
|
||||||
mtf.initialize("notepad", new OriginalProgramModifierListener() {
|
mtf.initialize("notepad", new ProgramModifierListener() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void modifyOriginal(ProgramDB program) throws Exception {
|
|
||||||
int transactionID = program.startTransaction("test");
|
|
||||||
try {
|
|
||||||
Options list = program.getOptions("Program Information");
|
|
||||||
list.setBoolean("Analyzed", false);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
program.endTransaction(transactionID, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
@@ -734,10 +710,20 @@ public class PropertyListMergeManager2Test extends AbstractMergeTest {
|
|||||||
public void testAnalyzedTrueInLatestFalseInMy() throws Exception {
|
public void testAnalyzedTrueInLatestFalseInMy() throws Exception {
|
||||||
// test case: conflict because both values changed
|
// test case: conflict because both values changed
|
||||||
// Choose 'latest'
|
// Choose 'latest'
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new OriginalProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
@Override
|
||||||
*/
|
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
Options list = program.getOptions("Program Information");
|
||||||
|
list.setBoolean("Analyzed", false); // revert to default state
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
int transactionID = program.startTransaction("test");
|
int transactionID = program.startTransaction("test");
|
||||||
@@ -777,10 +763,20 @@ public class PropertyListMergeManager2Test extends AbstractMergeTest {
|
|||||||
public void testAnalyzedFalseInLatestTrueInMy() throws Exception {
|
public void testAnalyzedFalseInLatestTrueInMy() throws Exception {
|
||||||
// test case: conflict because both values changed
|
// test case: conflict because both values changed
|
||||||
// Choose 'latest'
|
// Choose 'latest'
|
||||||
mtf.initialize("notepad", new ProgramModifierListener() {
|
mtf.initialize("notepad", new OriginalProgramModifierListener() {
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyLatest(ghidra.program.database.ProgramDB)
|
@Override
|
||||||
*/
|
public void modifyOriginal(ProgramDB program) throws Exception {
|
||||||
|
int transactionID = program.startTransaction("test");
|
||||||
|
try {
|
||||||
|
Options list = program.getOptions("Program Information");
|
||||||
|
list.setBoolean("Analyzed", false); // revert to default value
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
program.endTransaction(transactionID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyLatest(ProgramDB program) {
|
public void modifyLatest(ProgramDB program) {
|
||||||
int transactionID = program.startTransaction("test");
|
int transactionID = program.startTransaction("test");
|
||||||
@@ -793,9 +789,6 @@ public class PropertyListMergeManager2Test extends AbstractMergeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.framework.data.ProgramModifierListener#modifyPrivate(ghidra.program.database.ProgramDB)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void modifyPrivate(ProgramDB program) {
|
public void modifyPrivate(ProgramDB program) {
|
||||||
int transactionID = program.startTransaction("test");
|
int transactionID = program.startTransaction("test");
|
||||||
|
|||||||
+14
-4
@@ -25,6 +25,8 @@ import ghidra.program.database.ProgramBuilder;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
import ghidra.program.model.data.ProgramBasedDataTypeManager;
|
||||||
|
import ghidra.program.model.data.StringDataType;
|
||||||
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.program.model.mem.MemoryBlock;
|
import ghidra.program.model.mem.MemoryBlock;
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
@@ -44,6 +46,10 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||||||
private volatile boolean success;
|
private volatile boolean success;
|
||||||
private volatile String errMsg;
|
private volatile String errMsg;
|
||||||
|
|
||||||
|
// Suitable settings allowed for StringDataType data
|
||||||
|
private static String LONG_SETTING_NAME = "mutability";
|
||||||
|
private static String STRING_SETTING_NAME = "charset";
|
||||||
|
|
||||||
private Program buildProgram1(String programName) throws Exception {
|
private Program buildProgram1(String programName) throws Exception {
|
||||||
ProgramBuilder builder = new ProgramBuilder(programName, ProgramBuilder._TOY);
|
ProgramBuilder builder = new ProgramBuilder(programName, ProgramBuilder._TOY);
|
||||||
builder.createMemory(".text", Long.toHexString(0x1001000), 0x6600);
|
builder.createMemory(".text", Long.toHexString(0x1001000), 0x6600);
|
||||||
@@ -80,11 +86,13 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||||||
model.initialize(block);
|
model.initialize(block);
|
||||||
|
|
||||||
int transactionID = x8051.startTransaction("Set settings");
|
int transactionID = x8051.startTransaction("Set settings");
|
||||||
|
|
||||||
ProgramBasedDataTypeManager dtm = x8051.getDataTypeManager();
|
ProgramBasedDataTypeManager dtm = x8051.getDataTypeManager();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Address a = getAddr(x8051, "BITS", i);
|
Address a = getAddr(x8051, "BITS", i);
|
||||||
dtm.setStringSettingsValue(a, "color", "red" + i);
|
Data d = x8051.getListing().createData(a, StringDataType.dataType, 1);
|
||||||
dtm.setLongSettingsValue(a, "someLongValue", i);
|
dtm.setStringSettingsValue(d, STRING_SETTING_NAME, "red" + i);
|
||||||
|
dtm.setLongSettingsValue(d, LONG_SETTING_NAME, i);
|
||||||
}
|
}
|
||||||
x8051.endTransaction(transactionID, true);
|
x8051.endTransaction(transactionID, true);
|
||||||
}
|
}
|
||||||
@@ -198,11 +206,13 @@ public class MoveBlockModelTest extends AbstractGhidraHeadedIntegrationTest
|
|||||||
ProgramBasedDataTypeManager dtm = x8051.getDataTypeManager();
|
ProgramBasedDataTypeManager dtm = x8051.getDataTypeManager();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Address a = getAddr(x8051, "CODE", 0x2000 + i);
|
Address a = getAddr(x8051, "CODE", 0x2000 + i);
|
||||||
|
Data d = x8051.getListing().getDataAt(a);
|
||||||
|
assertNotNull(d);
|
||||||
|
|
||||||
String s = dtm.getStringSettingsValue(a, "color");
|
String s = dtm.getStringSettingsValue(d, STRING_SETTING_NAME);
|
||||||
assertEquals("red" + i, s);
|
assertEquals("red" + i, s);
|
||||||
|
|
||||||
Long lvalue = dtm.getLongSettingsValue(a, "someLongValue");
|
Long lvalue = dtm.getLongSettingsValue(d, LONG_SETTING_NAME);
|
||||||
assertEquals(i, lvalue.longValue());
|
assertEquals(i, lvalue.longValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ package ghidra.program.database.data;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
import ghidra.docking.settings.SettingsDefinition;
|
import ghidra.docking.settings.SettingsDefinition;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
@@ -29,8 +31,6 @@ import ghidra.program.model.mem.Memory;
|
|||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
import ghidra.util.task.TaskMonitorAdapter;
|
||||||
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* To change the template for this generated type comment go to
|
* To change the template for this generated type comment go to
|
||||||
@@ -171,15 +171,15 @@ public class ArrayTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Data comp = data.getComponent(i);
|
Data comp = data.getComponent(i);
|
||||||
assertEquals(null, comp.getLong("MySetting"));
|
assertEquals(null, comp.getLong("format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Data component4 = data.getComponent(4);
|
Data component4 = data.getComponent(4);
|
||||||
component4.setLong("MySetting", 10L);
|
component4.setLong("format", 10L);
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Data comp = data.getComponent(i);
|
Data comp = data.getComponent(i);
|
||||||
assertEquals((Long) 10L, comp.getLong("MySetting"));
|
assertEquals((Long) 10L, comp.getLong("format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -199,15 +199,15 @@ public class ArrayTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Data comp = subData.getComponent(i);
|
Data comp = subData.getComponent(i);
|
||||||
assertEquals(null, comp.getLong("MySetting"));
|
assertEquals(null, comp.getLong("format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Data component4 = subData.getComponent(4);
|
Data component4 = subData.getComponent(4);
|
||||||
component4.setLong("MySetting", 10L);
|
component4.setLong("format", 10L);
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Data comp = subData.getComponent(i);
|
Data comp = subData.getComponent(i);
|
||||||
assertEquals((Long) 10L, comp.getLong("MySetting"));
|
assertEquals((Long) 10L, comp.getLong("format"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+133
-111
@@ -27,6 +27,7 @@ import ghidra.program.database.ProgramDB;
|
|||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
import ghidra.program.model.data.*;
|
import ghidra.program.model.data.*;
|
||||||
|
import ghidra.program.model.data.DataUtilities.ClearDataMode;
|
||||||
import ghidra.program.model.listing.Data;
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.listing.Listing;
|
import ghidra.program.model.listing.Listing;
|
||||||
import ghidra.program.model.mem.Memory;
|
import ghidra.program.model.mem.Memory;
|
||||||
@@ -47,6 +48,10 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
private AddressSpace space;
|
private AddressSpace space;
|
||||||
private int transactionID;
|
private int transactionID;
|
||||||
|
|
||||||
|
// Suitable settings allowed for StringDataType data
|
||||||
|
private static String LONG_SETTING_NAME = "mutability";
|
||||||
|
private static String STRING_SETTING_NAME = "charset";
|
||||||
|
|
||||||
// NOTE: Datatypes must be resolved before settings may be changed
|
// NOTE: Datatypes must be resolved before settings may be changed
|
||||||
// with the exception of TypeDefDataType which does permit
|
// with the exception of TypeDefDataType which does permit
|
||||||
// TypeDefSettingsDefinition settings defined by the base-datatype.
|
// TypeDefSettingsDefinition settings defined by the base-datatype.
|
||||||
@@ -63,6 +68,16 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
listing = program.getListing();
|
listing = program.getListing();
|
||||||
transactionID = program.startTransaction("Test");
|
transactionID = program.startTransaction("Test");
|
||||||
addBlock();
|
addBlock();
|
||||||
|
// pointer-typedef has the largest
|
||||||
|
// System.out.println("Defined string settings:");
|
||||||
|
// for (SettingsDefinition def : StringDataType.dataType.getSettingsDefinitions()) {
|
||||||
|
// System.out.println(def.getStorageKey());
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (int i = 0; i < 40; i++) {
|
||||||
|
DataUtilities.createData(program, addr(i), StringDataType.dataType, 1, false,
|
||||||
|
ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -76,31 +91,33 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSetDefaultSettings() throws Exception {
|
public void testSetDefaultSettings() throws Exception {
|
||||||
|
|
||||||
DataType dt = ByteDataType.dataType;
|
DataType dt = StringDataType.dataType;
|
||||||
|
|
||||||
Settings defaultSettings = dt.getDefaultSettings();
|
Settings defaultSettings = dt.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
|
||||||
|
|
||||||
assertNull(defaultSettings.getString("color"));
|
// immutable warnings expected
|
||||||
assertNull(defaultSettings.getLong("someLongValue"));
|
defaultSettings.setString(STRING_SETTING_NAME, "red");
|
||||||
|
defaultSettings.setLong(LONG_SETTING_NAME, 10);
|
||||||
|
|
||||||
|
assertNull(defaultSettings.getString(STRING_SETTING_NAME));
|
||||||
|
assertNull(defaultSettings.getLong(LONG_SETTING_NAME));
|
||||||
|
|
||||||
// May modify byte default settings after resolve
|
// May modify byte default settings after resolve
|
||||||
dt = dataMgr.resolve(dt, null);
|
dt = dataMgr.resolve(dt, null);
|
||||||
|
|
||||||
defaultSettings = dt.getDefaultSettings();
|
defaultSettings = dt.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
defaultSettings.setString(STRING_SETTING_NAME, "red");
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
defaultSettings.setLong(LONG_SETTING_NAME, 10);
|
||||||
|
|
||||||
assertEquals("red", defaultSettings.getString("color"));
|
assertEquals("red", defaultSettings.getString(STRING_SETTING_NAME));
|
||||||
Long lv = defaultSettings.getLong("someLongValue");
|
Long lv = defaultSettings.getLong(LONG_SETTING_NAME);
|
||||||
assertNotNull(lv);
|
assertNotNull(lv);
|
||||||
assertEquals(10, lv.longValue());
|
assertEquals(10, lv.longValue());
|
||||||
|
|
||||||
defaultSettings.setValue("long", 10L);
|
defaultSettings.setValue(LONG_SETTING_NAME, 20L);
|
||||||
Object obj = defaultSettings.getValue("long");
|
Object obj = defaultSettings.getValue(LONG_SETTING_NAME);
|
||||||
assertNotNull(obj);
|
assertTrue(obj instanceof Long);
|
||||||
assertEquals(10, ((Long) obj).longValue());
|
assertEquals(20, ((Long) obj).longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -112,31 +129,32 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertEquals(0, ByteDataType.dataType.getTypeDefSettingsDefinitions().length);
|
assertEquals(0, ByteDataType.dataType.getTypeDefSettingsDefinitions().length);
|
||||||
|
|
||||||
Settings defaultSettings = typeDef.getDefaultSettings();
|
Settings defaultSettings = typeDef.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
|
||||||
|
|
||||||
assertNull(defaultSettings.getString("color"));
|
// immutable warnings expected
|
||||||
assertNull(defaultSettings.getLong("someLongValue"));
|
FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.CHAR);
|
||||||
|
EndianSettingsDefinition.DEF.setBigEndian(defaultSettings, false);
|
||||||
|
PaddingSettingsDefinition.DEF.setPadded(defaultSettings, true);
|
||||||
|
|
||||||
|
assertNull(defaultSettings.getLong("format"));
|
||||||
|
assertNull(defaultSettings.getLong("endian"));
|
||||||
|
assertNull(defaultSettings.getLong("padding"));
|
||||||
|
|
||||||
// May modify arbitrary typedef default settings after resolve
|
// May modify arbitrary typedef default settings after resolve
|
||||||
typeDef = (TypeDef) dataMgr.resolve(typeDef, null);
|
typeDef = (TypeDef) dataMgr.resolve(typeDef, null);
|
||||||
|
|
||||||
defaultSettings = typeDef.getDefaultSettings();
|
defaultSettings = typeDef.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.CHAR);
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
EndianSettingsDefinition.DEF.setBigEndian(defaultSettings, false);
|
||||||
|
PaddingSettingsDefinition.DEF.setPadded(defaultSettings, true);
|
||||||
|
|
||||||
assertEquals("red", defaultSettings.getString("color"));
|
assertEquals(FormatSettingsDefinition.CHAR, defaultSettings.getLong("format").longValue());
|
||||||
Long lv = defaultSettings.getLong("someLongValue");
|
assertEquals(EndianSettingsDefinition.LITTLE,
|
||||||
assertNotNull(lv);
|
defaultSettings.getLong("endian").longValue());
|
||||||
assertEquals(10, lv.longValue());
|
assertEquals(PaddingSettingsDefinition.PADDED_VALUE,
|
||||||
|
defaultSettings.getLong("padded").longValue());
|
||||||
defaultSettings.setValue("long", 10L);
|
|
||||||
Object obj = defaultSettings.getValue("long");
|
|
||||||
assertNotNull(obj);
|
|
||||||
assertEquals(10, ((Long) obj).longValue());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
defaultSettings.setValue("color", Color.RED);
|
defaultSettings.setValue("format", Color.RED);
|
||||||
Assert.fail("Should not be able to set arbitrary objects");
|
Assert.fail("Should not be able to set arbitrary objects");
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
@@ -147,10 +165,10 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testIsEmpty() throws Exception {
|
public void testIsEmpty() throws Exception {
|
||||||
|
|
||||||
DataType dt = dataMgr.resolve(ByteDataType.dataType, null);
|
Data data = listing.getDataAt(addr(10));
|
||||||
Settings defaultSettings = dt.getDefaultSettings();
|
Settings defaultSettings = data.getDataType().getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
defaultSettings.setString(STRING_SETTING_NAME, "red");
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
defaultSettings.setLong(LONG_SETTING_NAME, 10);
|
||||||
|
|
||||||
assertTrue(!defaultSettings.isEmpty());
|
assertTrue(!defaultSettings.isEmpty());
|
||||||
|
|
||||||
@@ -161,107 +179,99 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetNames() throws Exception {
|
public void testGetNames() throws Exception {
|
||||||
|
|
||||||
DataType dt = dataMgr.resolve(ByteDataType.dataType, null);
|
DataType dt = dataMgr.resolve(StringDataType.dataType, null);
|
||||||
Settings defaultSettings = dt.getDefaultSettings();
|
Settings defaultSettings = dt.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
defaultSettings.setString(STRING_SETTING_NAME, "red");
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
defaultSettings.setLong(LONG_SETTING_NAME, 10);
|
||||||
defaultSettings.setString("endian", "big Endian");
|
|
||||||
|
|
||||||
String[] names = defaultSettings.getNames();
|
String[] names = defaultSettings.getNames();
|
||||||
assertEquals(3, names.length);
|
assertEquals(2, names.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearSetting() throws Exception {
|
public void testClearSetting() throws Exception {
|
||||||
|
|
||||||
DataType dt = dataMgr.resolve(ByteDataType.dataType, null);
|
DataType dt = dataMgr.resolve(StringDataType.dataType, null);
|
||||||
Settings defaultSettings = dt.getDefaultSettings();
|
Settings defaultSettings = dt.getDefaultSettings();
|
||||||
defaultSettings.setString("color", "red");
|
defaultSettings.setString(STRING_SETTING_NAME, "red");
|
||||||
defaultSettings.setLong("someLongValue", 10);
|
defaultSettings.setLong(LONG_SETTING_NAME, 10);
|
||||||
|
|
||||||
defaultSettings.clearSetting("color");
|
defaultSettings.clearSetting(STRING_SETTING_NAME);
|
||||||
assertNull(defaultSettings.getString("color"));
|
assertNull(defaultSettings.getString(STRING_SETTING_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInstanceSettings() throws Exception {
|
public void testInstanceSettings() throws Exception {
|
||||||
|
|
||||||
listing.createData(addr(10), new ByteDataType(), 1);
|
Data data = DataUtilities.createData(program, addr(10), ByteDataType.dataType, 1, false,
|
||||||
Data data = listing.getDataAt(addr(10));
|
ClearDataMode.CLEAR_ALL_CONFLICT_DATA);
|
||||||
ByteDataType dt = (ByteDataType) data.getDataType();
|
|
||||||
|
DataType dt = data.getDataType();
|
||||||
Settings defaultSettings = dt.getDefaultSettings();
|
Settings defaultSettings = dt.getDefaultSettings();
|
||||||
defaultSettings.setLong("format", FormatSettingsDefinition.CHAR);
|
FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.CHAR);
|
||||||
defaultSettings.setLong("signed", 0);
|
EndianSettingsDefinition.DEF.setBigEndian(defaultSettings, false);
|
||||||
defaultSettings.setLong("padded", 1);
|
PaddingSettingsDefinition.DEF.setPadded(defaultSettings, true);
|
||||||
|
|
||||||
SettingsDefinition[] defs = dt.getSettingsDefinitions();
|
assertEquals(FormatSettingsDefinition.CHAR, data.getLong("format").longValue());
|
||||||
for (int i = 0; i < defs.length; i++) {
|
FormatSettingsDefinition.DEF.setChoice(data, FormatSettingsDefinition.DECIMAL);
|
||||||
|
assertEquals(FormatSettingsDefinition.DECIMAL, data.getLong("format").longValue());
|
||||||
|
|
||||||
if (defs[i] instanceof EnumSettingsDefinition) {
|
assertEquals(EndianSettingsDefinition.LITTLE, data.getLong("endian").longValue());
|
||||||
EnumSettingsDefinition enumDef = (EnumSettingsDefinition) defs[i];
|
EndianSettingsDefinition.DEF.setChoice(data, EndianSettingsDefinition.BIG);
|
||||||
int value = enumDef.getChoice(data);
|
assertEquals(EndianSettingsDefinition.BIG, data.getLong("endian").longValue());
|
||||||
enumDef.setChoice(data, value);
|
|
||||||
if (i == 0) {
|
|
||||||
assertEquals(FormatSettingsDefinition.CHAR, data.getLong("format").longValue());
|
|
||||||
}
|
|
||||||
else if (i == 1) {
|
|
||||||
assertEquals(0, data.getLong("signed").longValue());
|
|
||||||
}
|
|
||||||
else if (i == 2) {
|
|
||||||
assertEquals(1, data.getLong("padded").longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
assertEquals(PaddingSettingsDefinition.PADDED_VALUE, data.getLong("padded").longValue());
|
||||||
}
|
PaddingSettingsDefinition.DEF.setChoice(data, PaddingSettingsDefinition.UNPADDED_VALUE);
|
||||||
|
assertEquals(PaddingSettingsDefinition.UNPADDED_VALUE, data.getLong("padded").longValue());
|
||||||
|
|
||||||
|
FormatSettingsDefinition.DEF.setChoice(defaultSettings, FormatSettingsDefinition.HEX);
|
||||||
|
EndianSettingsDefinition.DEF.clear(defaultSettings);
|
||||||
|
PaddingSettingsDefinition.DEF.clear(defaultSettings);
|
||||||
|
|
||||||
|
assertEquals(FormatSettingsDefinition.DECIMAL, data.getLong("format").longValue());
|
||||||
|
assertEquals(EndianSettingsDefinition.BIG, data.getLong("endian").longValue());
|
||||||
|
assertEquals(PaddingSettingsDefinition.UNPADDED_VALUE, data.getLong("padded").longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetInstanceNames() throws Exception {
|
public void testGetInstanceNames() throws Exception {
|
||||||
listing.createData(addr(10), new ByteDataType(), 1);
|
|
||||||
Data data = listing.getDataAt(addr(10));
|
Data data = listing.getDataAt(addr(10));
|
||||||
data.setString("color", "red");
|
data.setString(STRING_SETTING_NAME, "red");
|
||||||
data.setLong("someLongValue", 10);
|
data.setLong(LONG_SETTING_NAME, 10);
|
||||||
data.setString("endian", "big Endian");
|
|
||||||
|
|
||||||
String[] names = data.getNames();
|
String[] names = data.getNames();
|
||||||
assertEquals(3, names.length);
|
assertEquals(2, names.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearInstanceSettings() throws Exception {
|
public void testClearInstanceSettings() throws Exception {
|
||||||
listing.createData(addr(10), new ByteDataType(), 1);
|
|
||||||
Data data = listing.getDataAt(addr(10));
|
Data data = listing.getDataAt(addr(10));
|
||||||
|
|
||||||
data.setString("color", "red");
|
data.setString(STRING_SETTING_NAME, "red");
|
||||||
data.setLong("someLongValue", 10);
|
data.setLong(LONG_SETTING_NAME, 10);
|
||||||
|
|
||||||
data.clearSetting("color");
|
data.clearSetting(STRING_SETTING_NAME);
|
||||||
assertNull(data.getString("color"));
|
assertNull(data.getString(STRING_SETTING_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testClearAllInstanceSettings() throws Exception {
|
public void testClearAllInstanceSettings() throws Exception {
|
||||||
listing.createData(addr(10), new ByteDataType(), 1);
|
|
||||||
Data data = listing.getDataAt(addr(10));
|
Data data = listing.getDataAt(addr(10));
|
||||||
|
|
||||||
data.setString("color", "red");
|
data.setString(STRING_SETTING_NAME, "red");
|
||||||
data.setLong("someLongValue", 10);
|
data.setLong(LONG_SETTING_NAME, 10);
|
||||||
data.setString("endian", "big Endian");
|
|
||||||
|
|
||||||
data.clearAllSettings();
|
data.clearAllSettings();
|
||||||
assertNull(data.getString("color"));
|
assertNull(data.getString(STRING_SETTING_NAME));
|
||||||
assertNull(data.getLong("someLongValue"));
|
assertNull(data.getLong(LONG_SETTING_NAME));
|
||||||
assertNull(data.getString("endian"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsEmptyInstanceSettings() throws Exception {
|
public void testIsEmptyInstanceSettings() throws Exception {
|
||||||
listing.createData(addr(10), new ByteDataType(), 1);
|
|
||||||
Data data = listing.getDataAt(addr(10));
|
Data data = listing.getDataAt(addr(10));
|
||||||
|
|
||||||
data.setString("color", "red");
|
data.setString(STRING_SETTING_NAME, "red");
|
||||||
data.setLong("someLongValue", 10);
|
data.setLong(LONG_SETTING_NAME, 10);
|
||||||
data.setString("endian", "big Endian");
|
|
||||||
|
|
||||||
assertTrue(!data.isEmpty());
|
assertTrue(!data.isEmpty());
|
||||||
data.clearAllSettings();
|
data.clearAllSettings();
|
||||||
@@ -269,23 +279,29 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertTrue(data.isEmpty());
|
assertTrue(data.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Data getDataAt(long offset) {
|
||||||
|
Data data = listing.getDataAt(addr(offset));
|
||||||
|
assertNotNull("expected data at address 0x" + Long.toHexString(offset));
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMoveSettings() throws Exception {
|
public void testMoveSettings() throws Exception {
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
dataMgr.setStringSettingsValue(a, "color", "red" + i);
|
dataMgr.setStringSettingsValue(d, STRING_SETTING_NAME, "red" + i);
|
||||||
dataMgr.setLongSettingsValue(a, "someLongValue", i);
|
dataMgr.setLongSettingsValue(d, LONG_SETTING_NAME, i);
|
||||||
}
|
}
|
||||||
dataMgr.moveAddressRange(addr(0), addr(20), 10, TaskMonitor.DUMMY);
|
dataMgr.moveAddressRange(addr(0), addr(20), 10, TaskMonitor.DUMMY);
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 20; i < 30; i++, j++) {
|
for (int i = 20; i < 30; i++, j++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
|
|
||||||
String s = dataMgr.getStringSettingsValue(a, "color");
|
String s = dataMgr.getStringSettingsValue(d, STRING_SETTING_NAME);
|
||||||
assertEquals("red" + j, s);
|
assertEquals("red" + j, s);
|
||||||
|
|
||||||
Long lvalue = dataMgr.getLongSettingsValue(a, "someLongValue");
|
Long lvalue = dataMgr.getLongSettingsValue(d, LONG_SETTING_NAME);
|
||||||
assertEquals(j, lvalue.longValue());
|
assertEquals(j, lvalue.longValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,9 +310,9 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
public void testMoveSettings2() {
|
public void testMoveSettings2() {
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
dataMgr.setStringSettingsValue(a, "color", "red" + i);
|
dataMgr.setStringSettingsValue(d, STRING_SETTING_NAME, "red" + i);
|
||||||
dataMgr.setLongSettingsValue(a, "someLongValue", i);
|
dataMgr.setLongSettingsValue(d, LONG_SETTING_NAME, i);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
dataMgr.moveAddressRange(addr(0), addr(5), 10, TaskMonitor.DUMMY);
|
dataMgr.moveAddressRange(addr(0), addr(5), 10, TaskMonitor.DUMMY);
|
||||||
@@ -307,12 +323,12 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 5; i < 15; i++, j++) {
|
for (int i = 5; i < 15; i++, j++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
|
|
||||||
String s = dataMgr.getStringSettingsValue(a, "color");
|
String s = dataMgr.getStringSettingsValue(d, STRING_SETTING_NAME);
|
||||||
assertEquals("red" + j, s);
|
assertEquals("red" + j, s);
|
||||||
|
|
||||||
Long lvalue = dataMgr.getLongSettingsValue(a, "someLongValue");
|
Long lvalue = dataMgr.getLongSettingsValue(d, LONG_SETTING_NAME);
|
||||||
assertEquals(j, lvalue.longValue());
|
assertEquals(j, lvalue.longValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,9 +338,9 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
int j = 20;
|
int j = 20;
|
||||||
for (int i = 20; i < 30; i++, j++) {
|
for (int i = 20; i < 30; i++, j++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
dataMgr.setStringSettingsValue(a, "color", "red" + i);
|
dataMgr.setStringSettingsValue(d, STRING_SETTING_NAME, "red" + i);
|
||||||
dataMgr.setLongSettingsValue(a, "someLongValue", i);
|
dataMgr.setLongSettingsValue(d, LONG_SETTING_NAME, i);
|
||||||
}
|
}
|
||||||
j = 20;
|
j = 20;
|
||||||
try {
|
try {
|
||||||
@@ -334,12 +350,12 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
Assert.fail("Unexpected cancelled exception");
|
Assert.fail("Unexpected cancelled exception");
|
||||||
}
|
}
|
||||||
for (int i = 5; i < 15; i++, j++) {
|
for (int i = 5; i < 15; i++, j++) {
|
||||||
Address a = addr(i);
|
Data d = getDataAt(i);
|
||||||
|
|
||||||
String s = dataMgr.getStringSettingsValue(a, "color");
|
String s = dataMgr.getStringSettingsValue(d, STRING_SETTING_NAME);
|
||||||
assertEquals("red" + j, s);
|
assertEquals("red" + j, s);
|
||||||
|
|
||||||
Long lvalue = dataMgr.getLongSettingsValue(a, "someLongValue");
|
Long lvalue = dataMgr.getLongSettingsValue(d, LONG_SETTING_NAME);
|
||||||
assertEquals(j, lvalue.longValue());
|
assertEquals(j, lvalue.longValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,8 +394,7 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
DataType byteDT = dataMgr.resolve(new ByteDataType(), null);
|
DataType byteDT = dataMgr.resolve(new ByteDataType(), null);
|
||||||
SettingsDefinition[] settingsDefinitions = byteDT.getSettingsDefinitions();
|
SettingsDefinition[] settingsDefinitions = byteDT.getSettingsDefinitions();
|
||||||
Settings settings = byteDT.getDefaultSettings();
|
Settings settings = byteDT.getDefaultSettings();
|
||||||
settings.setLong("format", FormatSettingsDefinition.OCTAL);
|
FormatSettingsDefinition.DEF.setChoice(settings, FormatSettingsDefinition.OCTAL);
|
||||||
settings.setString("color", "red");
|
|
||||||
|
|
||||||
TypedefDataType tdt = new TypedefDataType("ByteTypedef", byteDT);
|
TypedefDataType tdt = new TypedefDataType("ByteTypedef", byteDT);
|
||||||
TypeDef td = (TypeDef) dataMgr.addDataType(tdt, null);
|
TypeDef td = (TypeDef) dataMgr.addDataType(tdt, null);
|
||||||
@@ -388,11 +403,18 @@ public class SettingsTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertTrue(sdefs.length >= settingsDefinitions.length); // TypeDef may add some of its own
|
assertTrue(sdefs.length >= settingsDefinitions.length); // TypeDef may add some of its own
|
||||||
|
|
||||||
Settings defSettings = td.getDefaultSettings();
|
Settings defSettings = td.getDefaultSettings();
|
||||||
defSettings.setLong("someLongValue", 10);
|
assertEquals(FormatSettingsDefinition.OCTAL,
|
||||||
|
FormatSettingsDefinition.DEF.getChoice(defSettings));
|
||||||
|
|
||||||
|
FormatSettingsDefinition.DEF.setChoice(defSettings, FormatSettingsDefinition.DECIMAL);
|
||||||
|
assertEquals(FormatSettingsDefinition.DECIMAL,
|
||||||
|
FormatSettingsDefinition.DEF.getChoice(defSettings));
|
||||||
|
|
||||||
|
FormatSettingsDefinition.DEF.setChoice(settings, FormatSettingsDefinition.HEX);
|
||||||
|
|
||||||
|
assertEquals(FormatSettingsDefinition.DECIMAL,
|
||||||
|
FormatSettingsDefinition.DEF.getChoice(defSettings)); // unchanged
|
||||||
|
|
||||||
assertEquals((long) FormatSettingsDefinition.OCTAL, defSettings.getValue("format")); // inherits from byteDt
|
|
||||||
assertEquals("red", defSettings.getValue("color")); // inherits from byteDt
|
|
||||||
assertEquals(10L, defSettings.getValue("someLongValue"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+198
-30
@@ -19,6 +19,8 @@ import static org.junit.Assert.*;
|
|||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
import ghidra.docking.settings.Settings;
|
||||||
|
import ghidra.program.database.DatabaseObject;
|
||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.data.PointerTypedefInspector;
|
import ghidra.program.database.data.PointerTypedefInspector;
|
||||||
import ghidra.program.model.address.AddressSpace;
|
import ghidra.program.model.address.AddressSpace;
|
||||||
@@ -63,75 +65,241 @@ public class PointerTypedefDataTypeTest extends AbstractGhidraHeadedIntegrationT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIBOBuiltIn() throws Exception {
|
public void testBuiltInIBODataTypes() throws Exception {
|
||||||
|
|
||||||
DataType dt = builtInDtm.getDataType(CategoryPath.ROOT, IBO32DataType.NAME);
|
DataType dt = builtInDtm.getDataType(CategoryPath.ROOT, IBO32DataType.NAME);
|
||||||
assertTrue(dt instanceof TypeDef);
|
assertTrue(dt instanceof IBO32DataType);
|
||||||
assertFalse(dt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
|
||||||
assertEquals(IBO32DataType.NAME, dt.getName());
|
assertEquals(IBO32DataType.NAME, dt.getName());
|
||||||
assertFalse(dt.hasLanguageDependantLength());
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
assertTrue(dt.isEquivalent(dtm.resolve(dt, null)));
|
|
||||||
|
|
||||||
dt = new IBO32DataType(CharDataType.dataType, dtm);
|
|
||||||
assertTrue(dt instanceof TypeDef);
|
|
||||||
assertTrue(dt instanceof BuiltIn);
|
|
||||||
assertEquals("char *32 __attribute__((image-base-relative))", dt.getName());
|
|
||||||
DataType dbDt = dtm.resolve(dt, null);
|
DataType dbDt = dtm.resolve(dt, null);
|
||||||
assertTrue(dbDt instanceof TypeDef);
|
assertTrue(dbDt instanceof IBO32DataType);
|
||||||
assertFalse(dbDt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
|
||||||
assertTrue(dt.isEquivalent(dbDt));
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
dt = builtInDtm.getDataType(CategoryPath.ROOT, IBO64DataType.NAME);
|
dt = builtInDtm.getDataType(CategoryPath.ROOT, IBO64DataType.NAME);
|
||||||
assertTrue(dt instanceof TypeDef);
|
assertTrue(dt instanceof IBO64DataType);
|
||||||
assertFalse(dt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
|
||||||
assertEquals(IBO64DataType.NAME, dt.getName());
|
assertEquals(IBO64DataType.NAME, dt.getName());
|
||||||
assertFalse(dt.hasLanguageDependantLength());
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
assertTrue(dt.isEquivalent(dtm.resolve(dt, null)));
|
|
||||||
|
|
||||||
dt = new IBO64DataType(CharDataType.dataType, dtm);
|
|
||||||
assertTrue(dt instanceof TypeDef);
|
|
||||||
assertTrue(dt instanceof BuiltIn);
|
|
||||||
assertEquals("char *64 __attribute__((image-base-relative))", dt.getName());
|
|
||||||
dbDt = dtm.resolve(dt, null);
|
dbDt = dtm.resolve(dt, null);
|
||||||
assertTrue(dbDt instanceof TypeDef);
|
assertTrue(dbDt instanceof IBO64DataType);
|
||||||
assertFalse(dbDt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
|
||||||
assertTrue(dt.isEquivalent(dbDt));
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPointerTypedef() throws Exception {
|
public void testPointerTypedef() throws Exception {
|
||||||
|
|
||||||
DataType dt = new PointerTypedef(null, CharDataType.dataType, -1, dtm,
|
DataType dt = new PointerTypedef(null, CharDataType.dataType, -1, dtm, 0x8);
|
||||||
program.getAddressFactory().getRegisterSpace());
|
|
||||||
assertTrue(dt.hasLanguageDependantLength());
|
assertTrue(dt.hasLanguageDependantLength());
|
||||||
assertEquals(4, dt.getLength());
|
assertEquals(4, dt.getLength());
|
||||||
assertTrue(dt instanceof TypeDef);
|
assertTrue(dt instanceof TypeDef);
|
||||||
assertTrue(dt instanceof BuiltIn);
|
assertEquals("char * " + formatAttributes("offset(0x8)"), dt.getName());
|
||||||
assertEquals("char * __attribute__((space(register)))", dt.getName());
|
|
||||||
DataType dbDt = dtm.resolve(dt, null);
|
DataType dbDt = dtm.resolve(dt, null);
|
||||||
assertTrue(dbDt instanceof TypeDef);
|
assertTrue(dbDt instanceof TypeDef);
|
||||||
assertFalse(dbDt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
assertTrue(dt.isEquivalent(dbDt));
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
AddressSpace space = PointerTypedefInspector.getPointerAddressSpace((TypeDef) dbDt,
|
AddressSpace space = PointerTypedefInspector.getPointerAddressSpace((TypeDef) dbDt,
|
||||||
program.getAddressFactory());
|
program.getAddressFactory());
|
||||||
assertTrue(program.getAddressFactory().getRegisterSpace().equals(space));
|
assertNull(space);
|
||||||
|
|
||||||
dt = new PointerTypedef(null, CharDataType.dataType, -1, dtm,
|
dt = new PointerTypedef(null, CharDataType.dataType, -1, dtm,
|
||||||
PointerType.RELATIVE);
|
PointerType.RELATIVE);
|
||||||
assertTrue(dt.hasLanguageDependantLength());
|
assertTrue(dt.hasLanguageDependantLength());
|
||||||
assertEquals(4, dt.getLength());
|
assertEquals(4, dt.getLength());
|
||||||
assertTrue(dt instanceof TypeDef);
|
assertTrue(dt instanceof TypeDef);
|
||||||
assertTrue(dt instanceof BuiltIn);
|
assertEquals("char * " + formatAttributes("relative"), dt.getName());
|
||||||
assertEquals("char * __attribute__((relative))", dt.getName());
|
|
||||||
dbDt = dtm.resolve(dt, null);
|
dbDt = dtm.resolve(dt, null);
|
||||||
assertTrue(dbDt instanceof TypeDef);
|
assertTrue(dbDt instanceof TypeDef);
|
||||||
assertFalse(dbDt instanceof BuiltIn); // transforms from BuiltIn to DataTypeDB
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
assertTrue(dt.isEquivalent(dbDt));
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
assertEquals(PointerType.RELATIVE, PointerTypedefInspector.getPointerType((TypeDef) dbDt));
|
assertEquals(PointerType.RELATIVE, PointerTypedefInspector.getPointerType((TypeDef) dbDt));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointerTypedefWithAddrSpace() throws Exception {
|
||||||
|
|
||||||
|
DataType dt = new PointerTypedef(null, CharDataType.dataType, -1, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
|
assertEquals(2, dt.getLength());
|
||||||
|
assertTrue(dt instanceof TypeDef);
|
||||||
|
assertEquals("char *16 " + formatAttributes("space(register)"), dt.getName());
|
||||||
|
DataType dbDt = dtm.resolve(dt, null);
|
||||||
|
assertTrue(dbDt instanceof TypeDef);
|
||||||
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
|
AddressSpace space = PointerTypedefInspector.getPointerAddressSpace((TypeDef) dbDt,
|
||||||
|
program.getAddressFactory());
|
||||||
|
assertTrue(program.getAddressFactory().getRegisterSpace().equals(space));
|
||||||
|
|
||||||
|
dt = new PointerTypedef(null, CharDataType.dataType, 4, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
|
assertEquals(4, dt.getLength());
|
||||||
|
assertTrue(dt instanceof TypeDef);
|
||||||
|
assertEquals("char *32 " + formatAttributes("space(register)"), dt.getName());
|
||||||
|
dbDt = dtm.resolve(dt, null);
|
||||||
|
assertTrue(dbDt instanceof TypeDef);
|
||||||
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
|
space = PointerTypedefInspector.getPointerAddressSpace((TypeDef) dbDt,
|
||||||
|
program.getAddressFactory());
|
||||||
|
assertTrue(program.getAddressFactory().getRegisterSpace().equals(space));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointerTypedefAutoNaming() throws Exception {
|
||||||
|
|
||||||
|
DataType st = dtm.resolve(new StructureDataType("foo", 10), null);
|
||||||
|
|
||||||
|
DataType dt = new PointerTypedef(null, st, -1, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
|
assertEquals(2, dt.getLength());
|
||||||
|
assertTrue(dt instanceof TypeDef);
|
||||||
|
assertEquals("foo *16 " + formatAttributes("space(register)"), dt.getName());
|
||||||
|
DataType dbDt = dtm.resolve(dt, null);
|
||||||
|
assertTrue(dbDt instanceof TypeDef);
|
||||||
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
|
st.setName("bob");
|
||||||
|
|
||||||
|
// auto-name should update
|
||||||
|
assertEquals("bob *16 " + formatAttributes("space(register)"), dbDt.getName());
|
||||||
|
|
||||||
|
Settings settings = dbDt.getDefaultSettings();
|
||||||
|
|
||||||
|
OffsetMaskSettingsDefinition.DEF.setValue(settings, 0x123456789abcdef0L);
|
||||||
|
assertEquals("bob *16 " + formatAttributes("space(register),mask(0x123456789abcdef0)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.setValue(settings, 0x123);
|
||||||
|
assertEquals(
|
||||||
|
"bob *16 " + formatAttributes("space(register),mask(0x123456789abcdef0),offset(0x123)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
OffsetShiftSettingsDefinition.DEF.setValue(settings, 16);
|
||||||
|
assertEquals(
|
||||||
|
"bob *16 " + formatAttributes(
|
||||||
|
"space(register),mask(0x123456789abcdef0),shift(16),offset(0x123)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
PointerTypeSettingsDefinition.DEF.setType(settings, PointerType.IMAGE_BASE_RELATIVE);
|
||||||
|
assertEquals(
|
||||||
|
"bob *16 " + formatAttributes(
|
||||||
|
"image-base-relative,space(register),mask(0x123456789abcdef0),shift(16),offset(0x123)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
st.setName("bill");
|
||||||
|
assertEquals(
|
||||||
|
"bill *16 " + formatAttributes(
|
||||||
|
"image-base-relative,space(register),mask(0x123456789abcdef0),shift(16),offset(0x123)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
PointerTypeSettingsDefinition.DEF.clear(settings);
|
||||||
|
assertEquals(
|
||||||
|
"bill *16 " + formatAttributes(
|
||||||
|
"space(register),mask(0x123456789abcdef0),shift(16),offset(0x123)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
ComponentOffsetSettingsDefinition.DEF.clear(settings);
|
||||||
|
assertEquals(
|
||||||
|
"bill *16 " + formatAttributes("space(register),mask(0x123456789abcdef0),shift(16)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
// NOTE: Changing address space setting will not alter pointer size
|
||||||
|
|
||||||
|
AddressSpaceSettingsDefinition.DEF.clear(settings);
|
||||||
|
assertEquals(
|
||||||
|
"bill *16 " + formatAttributes("mask(0x123456789abcdef0),shift(16)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
OffsetShiftSettingsDefinition.DEF.clear(settings);
|
||||||
|
assertEquals(
|
||||||
|
"bill *16 " + formatAttributes("mask(0x123456789abcdef0)"),
|
||||||
|
dbDt.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointerTypedefEquivalence() throws Exception {
|
||||||
|
|
||||||
|
DataType st = dtm.resolve(new StructureDataType("foo", 10), null);
|
||||||
|
|
||||||
|
TypeDef dt = new PointerTypedef(null, st, -1, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertTrue(dt.isAutoNamed());
|
||||||
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
|
assertEquals(2, dt.getLength());
|
||||||
|
assertEquals("foo *16 " + formatAttributes("space(register)"), dt.getName());
|
||||||
|
TypeDef dbDt = (TypeDef) dtm.resolve(dt, null);
|
||||||
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
|
dt = (TypeDef) dt.copy(dtm);
|
||||||
|
assertTrue(dbDt == dtm.resolve(dt, null)); // should resolve to same instance
|
||||||
|
|
||||||
|
dt = (TypeDef) dt.copy(dtm);
|
||||||
|
PointerTypeSettingsDefinition.DEF.setType(dt.getDefaultSettings(), PointerType.IMAGE_BASE_RELATIVE);
|
||||||
|
TypeDef dbDt2 = (TypeDef) dtm.resolve(dt, null); // should resolve to new instance
|
||||||
|
assertTrue(dbDt != dbDt2);
|
||||||
|
assertEquals("foo *16 " + formatAttributes("image-base-relative,space(register)"),
|
||||||
|
dbDt2.getName());
|
||||||
|
|
||||||
|
PointerTypeSettingsDefinition.DEF.clear(dbDt2.getDefaultSettings());
|
||||||
|
assertEquals("foo *16 " + formatAttributes("space(register)") + DataType.CONFLICT_SUFFIX,
|
||||||
|
dbDt2.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPointerTypedefEquivalence2() throws Exception {
|
||||||
|
|
||||||
|
DataType st = dtm.resolve(new StructureDataType("foo", 10), null);
|
||||||
|
|
||||||
|
TypeDef dt = new PointerTypedef(null, st, -1, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertTrue(dt.isAutoNamed());
|
||||||
|
assertFalse(dt.hasLanguageDependantLength());
|
||||||
|
assertEquals(2, dt.getLength());
|
||||||
|
assertEquals("foo *16 " + formatAttributes("space(register)"), dt.getName());
|
||||||
|
TypeDef dbDt = (TypeDef) dtm.resolve(dt, null);
|
||||||
|
assertTrue(dbDt instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt.isEquivalent(dbDt));
|
||||||
|
assertEquals(dt.getName(), dbDt.getName());
|
||||||
|
|
||||||
|
TypeDef dt2 = new PointerTypedef("john", st, -1, dtm,
|
||||||
|
program.getAddressFactory().getRegisterSpace());
|
||||||
|
assertFalse(dt2.isAutoNamed());
|
||||||
|
assertFalse(dt2.hasLanguageDependantLength());
|
||||||
|
assertEquals(2, dt.getLength());
|
||||||
|
assertEquals("john", dt2.getName());
|
||||||
|
TypeDef dbDt2 = (TypeDef) dtm.resolve(dt2, null);
|
||||||
|
assertTrue(dbDt != dbDt2);
|
||||||
|
assertFalse(dbDt.isEquivalent(dbDt2));
|
||||||
|
assertFalse(dbDt2.isEquivalent(dbDt));
|
||||||
|
assertTrue(dbDt2 instanceof DatabaseObject); // transforms to TypedefDB
|
||||||
|
assertTrue(dt2.isEquivalent(dbDt2));
|
||||||
|
assertEquals(dt2.getName(), dbDt2.getName());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatAttributes(String attrs) {
|
||||||
|
StringBuilder buf = new StringBuilder(DataType.TYPEDEF_ATTRIBUTE_PREFIX);
|
||||||
|
buf.append(attrs);
|
||||||
|
buf.append(DataType.TYPEDEF_ATTRIBUTE_SUFFIX);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package ghidra.program.database;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import db.*;
|
||||||
import db.buffers.BufferFile;
|
import db.buffers.BufferFile;
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||||
@@ -28,6 +29,7 @@ import ghidra.program.model.listing.ProgramChangeSet;
|
|||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.util.InvalidNameException;
|
import ghidra.util.InvalidNameException;
|
||||||
import ghidra.util.exception.CancelledException;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.exception.VersionException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +107,7 @@ public abstract class AbstractMTFModel {
|
|||||||
return privateChangeSet;
|
return privateChangeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProgramChangeSet getResultChangeSet() {
|
public ProgramChangeSet getLatestChangeSet() {
|
||||||
return latestChangeSet;
|
return latestChangeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ public abstract class AbstractMTFModel {
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void disableAutoAnalysis(Program p) {
|
protected static void disableAutoAnalysis(Program p) {
|
||||||
// Disable all analysis
|
// Disable all analysis
|
||||||
AutoAnalysisManager analysisMgr = AutoAnalysisManager.getAnalysisManager(p);
|
AutoAnalysisManager analysisMgr = AutoAnalysisManager.getAnalysisManager(p);
|
||||||
AbstractGenericTest.setInstanceField("isEnabled", analysisMgr, Boolean.FALSE);
|
AbstractGenericTest.setInstanceField("isEnabled", analysisMgr, Boolean.FALSE);
|
||||||
@@ -169,4 +171,25 @@ public abstract class AbstractMTFModel {
|
|||||||
throws Exception;
|
throws Exception;
|
||||||
|
|
||||||
public abstract void initialize(String programName, ProgramModifierListener l) throws Exception;
|
public abstract void initialize(String programName, ProgramModifierListener l) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone a program to a new instance. The new instance will be assigned an empty change-set.
|
||||||
|
* @param prog program to be cloned
|
||||||
|
* @param consumer new program consumer
|
||||||
|
* @return new program instance
|
||||||
|
* @throws IOException if a file IO error occurs
|
||||||
|
*/
|
||||||
|
public static ProgramDB cloneProgram(ProgramDB prog, Object consumer) throws IOException {
|
||||||
|
try {
|
||||||
|
DBHandle newDbh = DBTestUtils.cloneDbHandle(prog.getDBHandle());
|
||||||
|
ProgramDB newProg =
|
||||||
|
new ProgramDB(newDbh, DBConstants.UPDATE, TaskMonitor.DUMMY, consumer);
|
||||||
|
newProg.setChangeSet(new ProgramDBChangeSet(newProg.getAddressMap(), 20));
|
||||||
|
disableAutoAnalysis(newProg);
|
||||||
|
return newProg;
|
||||||
|
}
|
||||||
|
catch (CancelledException | VersionException e) {
|
||||||
|
throw new RuntimeException(e); // unexpected
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -90,7 +90,7 @@ public class MergeTestFacilitator {
|
|||||||
* Get the change set for Result program.
|
* Get the change set for Result program.
|
||||||
*/
|
*/
|
||||||
public ProgramChangeSet getResultChangeSet() {
|
public ProgramChangeSet getResultChangeSet() {
|
||||||
return model.getResultChangeSet();
|
return model.getLatestChangeSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
|
|||||||
+15
-61
@@ -1,6 +1,5 @@
|
|||||||
/* ###
|
/* ###
|
||||||
* IP: GHIDRA
|
* IP: GHIDRA
|
||||||
* REVIEWED: YES
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -30,11 +29,7 @@ import ghidra.util.exception.AssertException;
|
|||||||
// TODO rename--this is no longer using real programs
|
// TODO rename--this is no longer using real programs
|
||||||
public class RealProgramMTFModel extends AbstractMTFModel {
|
public class RealProgramMTFModel extends AbstractMTFModel {
|
||||||
|
|
||||||
/**
|
// Use simple ID generation
|
||||||
* We install our test ID generator to ensure that all datatypes we create will share the
|
|
||||||
* same ID across all versions of the programs we create. If we do not do this, then they will
|
|
||||||
* be different, which breaks many tests.
|
|
||||||
*/
|
|
||||||
private TestUniversalIdGenerator universalIdGenerator = new TestUniversalIdGenerator();
|
private TestUniversalIdGenerator universalIdGenerator = new TestUniversalIdGenerator();
|
||||||
|
|
||||||
RealProgramMTFModel(TestEnv env) {
|
RealProgramMTFModel(TestEnv env) {
|
||||||
@@ -46,12 +41,15 @@ public class RealProgramMTFModel extends AbstractMTFModel {
|
|||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
MergeProgramGenerator programGenerator = createProgramGenerator(programName);
|
MergeProgramGenerator programGenerator = createProgramGenerator(programName);
|
||||||
generatePrograms(programName, programGenerator);
|
originalProgram = programGenerator.generateProgram(programName);
|
||||||
|
|
||||||
disableAutoAnalysis();
|
latestProgram = cloneProgram(originalProgram, this);
|
||||||
|
modifier.modifyLatest(latestProgram);
|
||||||
|
|
||||||
makeIncomingChanges(modifier);
|
resultProgram = cloneProgram(latestProgram, this);
|
||||||
makeLocalChanges(modifier);
|
|
||||||
|
privateProgram = cloneProgram(originalProgram, this);
|
||||||
|
modifier.modifyPrivate(privateProgram);
|
||||||
|
|
||||||
recordChanges();
|
recordChanges();
|
||||||
clearChanges();
|
clearChanges();
|
||||||
@@ -63,36 +61,21 @@ public class RealProgramMTFModel extends AbstractMTFModel {
|
|||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
MergeProgramGenerator programGenerator = createProgramGenerator(programName);
|
MergeProgramGenerator programGenerator = createProgramGenerator(programName);
|
||||||
generatePrograms(programName, programGenerator);
|
originalProgram = programGenerator.generateProgram(programName);
|
||||||
|
modifier.modifyOriginal(originalProgram);
|
||||||
|
|
||||||
disableAutoAnalysis();
|
privateProgram = cloneProgram(originalProgram, this);
|
||||||
|
modifier.modifyPrivate(privateProgram);
|
||||||
|
|
||||||
createCustomStartingProgram(modifier);
|
latestProgram = cloneProgram(originalProgram, this);
|
||||||
clearChanges();
|
modifier.modifyLatest(latestProgram);
|
||||||
|
|
||||||
makeIncomingChanges(modifier);
|
resultProgram = cloneProgram(latestProgram, this);
|
||||||
makeLocalChanges(modifier);
|
|
||||||
|
|
||||||
recordChanges();
|
recordChanges();
|
||||||
clearChanges();
|
clearChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests that use this method are creating a new 'original' program, rather than using
|
|
||||||
* a pre-fabricated one from a program builder.
|
|
||||||
*/
|
|
||||||
private void createCustomStartingProgram(OriginalProgramModifierListener modifier)
|
|
||||||
throws Exception {
|
|
||||||
universalIdGenerator.checkpoint();
|
|
||||||
modifier.modifyOriginal(originalProgram);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
modifier.modifyOriginal(privateProgram);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
modifier.modifyOriginal(latestProgram);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
modifier.modifyOriginal(resultProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
private MergeProgramGenerator createProgramGenerator(String programName) {
|
private MergeProgramGenerator createProgramGenerator(String programName) {
|
||||||
if (programName.toLowerCase().contains("notepad")) {
|
if (programName.toLowerCase().contains("notepad")) {
|
||||||
return new MergeProgramGenerator_Notepads(this);
|
return new MergeProgramGenerator_Notepads(this);
|
||||||
@@ -117,35 +100,6 @@ public class RealProgramMTFModel extends AbstractMTFModel {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableAutoAnalysis() {
|
|
||||||
disableAutoAnalysis(privateProgram);
|
|
||||||
disableAutoAnalysis(resultProgram);
|
|
||||||
disableAutoAnalysis(latestProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void makeLocalChanges(ProgramModifierListener modifier) throws Exception {
|
|
||||||
modifier.modifyPrivate(privateProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void makeIncomingChanges(ProgramModifierListener modifier) throws Exception {
|
|
||||||
universalIdGenerator.checkpoint();
|
|
||||||
modifier.modifyLatest(latestProgram);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
modifier.modifyLatest(resultProgram);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generatePrograms(String programName, MergeProgramGenerator programGenerator)
|
|
||||||
throws Exception {
|
|
||||||
universalIdGenerator.checkpoint();
|
|
||||||
privateProgram = programGenerator.generateProgram(programName);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
originalProgram = programGenerator.generateProgram(programName);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
resultProgram = programGenerator.generateProgram(programName);
|
|
||||||
universalIdGenerator.restore();
|
|
||||||
latestProgram = programGenerator.generateProgram(programName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recordChanges() {
|
private void recordChanges() {
|
||||||
// ...keep track of the changes we've made
|
// ...keep track of the changes we've made
|
||||||
latestChangeSet = latestProgram.getChanges();
|
latestChangeSet = latestProgram.getChanges();
|
||||||
|
|||||||
@@ -581,8 +581,8 @@ public class ExtendedFlatProgramAPI extends FlatProgramAPI {
|
|||||||
|
|
||||||
int addressSize = address.getSize();
|
int addressSize = address.getSize();
|
||||||
if (addressSize == 64 && getIboIf64bit) {
|
if (addressSize == 64 && getIboIf64bit) {
|
||||||
ImageBaseOffset32DataType ibo32 =
|
IBO32DataType ibo32 =
|
||||||
new ImageBaseOffset32DataType(currentProgram.getDataTypeManager());
|
new IBO32DataType(currentProgram.getDataTypeManager());
|
||||||
int length = ibo32.getLength();
|
int length = ibo32.getLength();
|
||||||
DumbMemBufferImpl compMemBuffer =
|
DumbMemBufferImpl compMemBuffer =
|
||||||
new DumbMemBufferImpl(currentProgram.getMemory(), address);
|
new DumbMemBufferImpl(currentProgram.getMemory(), address);
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.*;
|
import ghidra.app.cmd.data.*;
|
||||||
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
|
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
|
||||||
@@ -116,7 +116,7 @@ public class EHCatchHandlerModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[1] */
|
/* comps[1] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispType", null);
|
struct.add(compDt, "dispType", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -136,7 +136,7 @@ public class EHCatchHandlerModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[3] */
|
/* comps[3] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispOfHandler", null);
|
struct.add(compDt, "dispOfHandler", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -101,7 +101,7 @@ public class EHESTypeListModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[1] */
|
/* comps[1] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispTypeArray", null);
|
struct.add(compDt, "dispTypeArray", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+6
-6
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -150,7 +150,7 @@ public class EHFunctionInfoModel extends AbstractCreateDataTypeModel {
|
|||||||
DataTypeManager dataTypeManager = getProgram().getDataTypeManager();
|
DataTypeManager dataTypeManager = getProgram().getDataTypeManager();
|
||||||
int intSize = new IntegerDataType(dataTypeManager).getLength();
|
int intSize = new IntegerDataType(dataTypeManager).getLength();
|
||||||
int uintSize = new UnsignedIntegerDataType(dataTypeManager).getLength();
|
int uintSize = new UnsignedIntegerDataType(dataTypeManager).getLength();
|
||||||
int ibo32Size = new ImageBaseOffset32DataType(dataTypeManager).getLength();
|
int ibo32Size = new IBO32DataType(dataTypeManager).getLength();
|
||||||
int defaultPointerSize = getDefaultPointerSize();
|
int defaultPointerSize = getDefaultPointerSize();
|
||||||
int size20;
|
int size20;
|
||||||
int additional21;
|
int additional21;
|
||||||
@@ -316,7 +316,7 @@ public class EHFunctionInfoModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[2] */
|
/* comps[2] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispUnwindMap", null);
|
struct.add(compDt, "dispUnwindMap", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -330,7 +330,7 @@ public class EHFunctionInfoModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[4] */
|
/* comps[4] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispTryBlockMap", null);
|
struct.add(compDt, "dispTryBlockMap", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -344,7 +344,7 @@ public class EHFunctionInfoModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[6] */
|
/* comps[6] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispIPToStateMap", null);
|
struct.add(compDt, "dispIPToStateMap", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -359,7 +359,7 @@ public class EHFunctionInfoModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
if (isV2 || isV3) {
|
if (isV2 || isV3) {
|
||||||
if (isRelative) { /* comps[8] */
|
if (isRelative) { /* comps[8] */
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispESTypeList", null);
|
struct.add(compDt, "dispESTypeList", null);
|
||||||
}
|
}
|
||||||
else { /* comps[7] */
|
else { /* comps[7] */
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -102,7 +102,7 @@ public class EHIPToStateModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[0] */
|
/* comps[0] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DataType dwordDt = new TypedefDataType(new CategoryPath("/WinDef.h"), "DWORD",
|
DataType dwordDt = new TypedefDataType(new CategoryPath("/WinDef.h"), "DWORD",
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -114,7 +114,7 @@ public class EHTryBlockModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[4] */
|
/* comps[4] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
struct.add(compDt, "dispHandlerArray", null);
|
struct.add(compDt, "dispHandlerArray", null);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.exceptionhandling;
|
package ghidra.app.cmd.data.exceptionhandling;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModel;
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -106,7 +106,7 @@ public class EHUnwindModel extends AbstractCreateDataTypeModel {
|
|||||||
|
|
||||||
/* comps[1] */
|
/* comps[1] */
|
||||||
if (isRelative) {
|
if (isRelative) {
|
||||||
compDt = new ImageBaseOffset32DataType(dataTypeManager);
|
compDt = new IBO32DataType(dataTypeManager);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -232,7 +232,7 @@ public class Rtti1Model extends AbstractCreateRttiDataModel {
|
|||||||
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
||||||
Structure rtti1Struct = (Structure) DataTypeUtils.getBaseDataType(rtti1Dt);
|
Structure rtti1Struct = (Structure) DataTypeUtils.getBaseDataType(rtti1Dt);
|
||||||
DataType rtti3RefDt =
|
DataType rtti3RefDt =
|
||||||
is64Bit ? new ImageBaseOffset32DataType(dataTypeManager) : new PointerDataType(rtti3Dt);
|
is64Bit ? new IBO32DataType(dataTypeManager) : new PointerDataType(rtti3Dt);
|
||||||
rtti1Struct.replace(CLASS_HIERARCHY_POINTER_ORDINAL, rtti3RefDt, rtti3RefDt.getLength(),
|
rtti1Struct.replace(CLASS_HIERARCHY_POINTER_ORDINAL, rtti3RefDt, rtti3RefDt.getLength(),
|
||||||
"pClassHierarchyDescriptor", "ref to ClassHierarchyDescriptor (RTTI 3) for class");
|
"pClassHierarchyDescriptor", "ref to ClassHierarchyDescriptor (RTTI 3) for class");
|
||||||
}
|
}
|
||||||
@@ -248,9 +248,9 @@ public class Rtti1Model extends AbstractCreateRttiDataModel {
|
|||||||
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
||||||
DataType rtti0Dt = TypeDescriptorModel.getDataType(program);
|
DataType rtti0Dt = TypeDescriptorModel.getDataType(program);
|
||||||
DataType rtti0RefDt =
|
DataType rtti0RefDt =
|
||||||
is64Bit ? new ImageBaseOffset32DataType(dataTypeManager) : new PointerDataType(rtti0Dt);
|
is64Bit ? new IBO32DataType(dataTypeManager) : new PointerDataType(rtti0Dt);
|
||||||
DataType rtti3RefDt =
|
DataType rtti3RefDt =
|
||||||
is64Bit ? new ImageBaseOffset32DataType(dataTypeManager) : new PointerDataType();
|
is64Bit ? new IBO32DataType(dataTypeManager) : new PointerDataType();
|
||||||
|
|
||||||
CategoryPath categoryPath = new CategoryPath(CATEGORY_PATH);
|
CategoryPath categoryPath = new CategoryPath(CATEGORY_PATH);
|
||||||
StructureDataType struct =
|
StructureDataType struct =
|
||||||
|
|||||||
+5
-11
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.rtti;
|
package ghidra.app.cmd.data.rtti;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getReferencedAddress;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -145,11 +145,8 @@ public class Rtti2Model extends AbstractCreateRttiDataModel {
|
|||||||
|
|
||||||
DataTypeManager dataTypeManager = program.getDataTypeManager();
|
DataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
|
|
||||||
if (MSDataTypeUtils.is64Bit(program)) {
|
return MSDataTypeUtils.is64Bit(program) ? IBO32DataType.createIBO32PointerTypedef(rtti1Dt)
|
||||||
return new ImageBaseOffset32DataType(dataTypeManager);
|
: new PointerDataType(rtti1Dt, dataTypeManager);
|
||||||
}
|
|
||||||
|
|
||||||
return new PointerDataType(rtti1Dt, dataTypeManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -162,11 +159,8 @@ public class Rtti2Model extends AbstractCreateRttiDataModel {
|
|||||||
|
|
||||||
DataTypeManager dataTypeManager = program.getDataTypeManager();
|
DataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
|
|
||||||
if (MSDataTypeUtils.is64Bit(program)) {
|
return MSDataTypeUtils.is64Bit(program) ? IBO32DataType.dataType
|
||||||
return new ImageBaseOffset32DataType(dataTypeManager);
|
: new PointerDataType(dataTypeManager);
|
||||||
}
|
|
||||||
|
|
||||||
return new PointerDataType(dataTypeManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+7
-8
@@ -15,9 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.rtti;
|
package ghidra.app.cmd.data.rtti;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAlignedPack4Structure;
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getReferencedAddress;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
import ghidra.app.cmd.data.EHDataTypeUtilities;
|
||||||
@@ -147,8 +144,8 @@ public class Rtti3Model extends AbstractCreateRttiDataModel {
|
|||||||
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
boolean is64Bit = MSDataTypeUtils.is64Bit(program);
|
||||||
Structure rtti3Struct = (Structure) DataTypeUtils.getBaseDataType(rtti3Dt);
|
Structure rtti3Struct = (Structure) DataTypeUtils.getBaseDataType(rtti3Dt);
|
||||||
DataType individualRtti2EntryDt = Rtti2Model.getIndividualEntryDataType(program, rtti1Dt);
|
DataType individualRtti2EntryDt = Rtti2Model.getIndividualEntryDataType(program, rtti1Dt);
|
||||||
DataType rtti2RefDt = is64Bit ? new ImageBaseOffset32DataType(dataTypeManager)
|
DataType rtti2RefDt = is64Bit ? IBO32DataType.createIBO32PointerTypedef(individualRtti2EntryDt)
|
||||||
: new PointerDataType(individualRtti2EntryDt);
|
: new PointerDataType(individualRtti2EntryDt, dataTypeManager);
|
||||||
rtti3Struct.replace(BASE_ARRAY_PTR_ORDINAL, rtti2RefDt, rtti2RefDt.getLength(),
|
rtti3Struct.replace(BASE_ARRAY_PTR_ORDINAL, rtti2RefDt, rtti2RefDt.getLength(),
|
||||||
"pBaseClassArray", "ref to BaseClassArray (RTTI 2)");
|
"pBaseClassArray", "ref to BaseClassArray (RTTI 2)");
|
||||||
}
|
}
|
||||||
@@ -165,7 +162,7 @@ public class Rtti3Model extends AbstractCreateRttiDataModel {
|
|||||||
|
|
||||||
CategoryPath categoryPath = new CategoryPath(CATEGORY_PATH);
|
CategoryPath categoryPath = new CategoryPath(CATEGORY_PATH);
|
||||||
StructureDataType struct =
|
StructureDataType struct =
|
||||||
getAlignedPack4Structure(dataTypeManager, categoryPath, STRUCTURE_NAME);
|
MSDataTypeUtils.getAlignedPack4Structure(dataTypeManager, categoryPath, STRUCTURE_NAME);
|
||||||
|
|
||||||
// Add the components.
|
// Add the components.
|
||||||
DWordDataType dWordDataType = new DWordDataType(dataTypeManager);
|
DWordDataType dWordDataType = new DWordDataType(dataTypeManager);
|
||||||
@@ -174,8 +171,10 @@ public class Rtti3Model extends AbstractCreateRttiDataModel {
|
|||||||
struct.add(dWordDataType, "numBaseClasses", "number of base classes (i.e. rtti1Count)");
|
struct.add(dWordDataType, "numBaseClasses", "number of base classes (i.e. rtti1Count)");
|
||||||
|
|
||||||
DataType rtti2Dt = Rtti2Model.getSimpleIndividualEntryDataType(program);
|
DataType rtti2Dt = Rtti2Model.getSimpleIndividualEntryDataType(program);
|
||||||
|
// FIXME! I don't think we should be making a pointer-to-pointer
|
||||||
DataType rtti2RefDt =
|
DataType rtti2RefDt =
|
||||||
is64Bit ? new ImageBaseOffset32DataType(dataTypeManager) : new PointerDataType(rtti2Dt);
|
is64Bit ? IBO32DataType.createIBO32PointerTypedef(rtti2Dt)
|
||||||
|
: new PointerDataType(rtti2Dt, dataTypeManager);
|
||||||
struct.add(rtti2RefDt, "pBaseClassArray", "ref to BaseClassArray (RTTI 2)");
|
struct.add(rtti2RefDt, "pBaseClassArray", "ref to BaseClassArray (RTTI 2)");
|
||||||
|
|
||||||
return new TypedefDataType(categoryPath, DATA_TYPE_NAME, struct, dataTypeManager);
|
return new TypedefDataType(categoryPath, DATA_TYPE_NAME, struct, dataTypeManager);
|
||||||
@@ -264,7 +263,7 @@ public class Rtti3Model extends AbstractCreateRttiDataModel {
|
|||||||
Memory memory = program.getMemory();
|
Memory memory = program.getMemory();
|
||||||
|
|
||||||
Address rtti2CompAddress = rtti3Address.add(BASE_ARRAY_PTR_OFFSET);
|
Address rtti2CompAddress = rtti3Address.add(BASE_ARRAY_PTR_OFFSET);
|
||||||
Address pointedToAddress = getReferencedAddress(program, rtti2CompAddress);
|
Address pointedToAddress = MSDataTypeUtils.getReferencedAddress(program, rtti2CompAddress);
|
||||||
if (pointedToAddress == null || !memory.contains(pointedToAddress)) {
|
if (pointedToAddress == null || !memory.contains(pointedToAddress)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-6
@@ -15,9 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.cmd.data.rtti;
|
package ghidra.app.cmd.data.rtti;
|
||||||
|
|
||||||
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.getAbsoluteAddress;
|
import static ghidra.app.util.datatype.microsoft.MSDataTypeUtils.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModelTest;
|
import ghidra.app.cmd.data.AbstractCreateDataTypeModelTest;
|
||||||
import ghidra.app.cmd.data.TypeDescriptorModel;
|
import ghidra.app.cmd.data.TypeDescriptorModel;
|
||||||
@@ -591,10 +590,10 @@ class AbstractRttiTest extends AbstractCreateDataTypeModelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void checkRtti2Data(ProgramDB program, long address, int numEntries) {
|
protected void checkRtti2Data(ProgramDB program, long address, int numEntries) {
|
||||||
|
DataType rtti1Dt = Rtti1Model.getDataType(program);
|
||||||
DataType expectedDataType =
|
DataType expectedDataType =
|
||||||
MSDataTypeUtils.is64Bit(program) ? new ImageBaseOffset32DataType()
|
MSDataTypeUtils.is64Bit(program) ? IBO32DataType.createIBO32PointerTypedef(rtti1Dt)
|
||||||
: new PointerDataType(Rtti1Model.getDataType(program),
|
: new PointerDataType(rtti1Dt, program.getDataTypeManager());
|
||||||
program.getDataTypeManager());
|
|
||||||
checkArrayData(program, address, expectedDataType, numEntries);
|
checkArrayData(program, address, expectedDataType, numEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -679,11 +679,16 @@ public class DBHandle {
|
|||||||
* @param outFile buffer file open for writing
|
* @param outFile buffer file open for writing
|
||||||
* @param newDatabaseId database ID to be forced for new database or null to generate
|
* @param newDatabaseId database ID to be forced for new database or null to generate
|
||||||
* new database ID
|
* new database ID
|
||||||
|
* @param associateWithNewFile if true the outFile will be associated with this DBHandle as the
|
||||||
|
* current source file, if false no change will be made to this DBHandle's state and the outFile
|
||||||
|
* will be written and set as read-only. The caller is responsbile for disposing the outFile if
|
||||||
|
* this parameter is false.
|
||||||
* @param monitor progress monitor
|
* @param monitor progress monitor
|
||||||
* @throws IOException if IO error occurs
|
* @throws IOException if IO error occurs
|
||||||
* @throws CancelledException if monitor cancels operation
|
* @throws CancelledException if monitor cancels operation
|
||||||
*/
|
*/
|
||||||
protected synchronized void saveAs(BufferFile outFile, Long newDatabaseId, TaskMonitor monitor)
|
protected synchronized void saveAs(BufferFile outFile, Long newDatabaseId,
|
||||||
|
boolean associateWithNewFile, TaskMonitor monitor)
|
||||||
throws IOException, CancelledException {
|
throws IOException, CancelledException {
|
||||||
|
|
||||||
if (txStarted) {
|
if (txStarted) {
|
||||||
@@ -704,7 +709,7 @@ public class DBHandle {
|
|||||||
endTransaction(txId, true); // saved file may be corrupt on IOException
|
endTransaction(txId, true); // saved file may be corrupt on IOException
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferMgr.saveAs(outFile, true, monitor);
|
bufferMgr.saveAs(outFile, associateWithNewFile, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ import java.util.Random;
|
|||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
import db.buffers.BufferFileManager;
|
import db.buffers.*;
|
||||||
import db.buffers.DummyBufferFileMgr;
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -803,6 +804,30 @@ public class DBTestUtils {
|
|||||||
static BufferFileManager getBufferFileManager(File dir, String dbName) {
|
static BufferFileManager getBufferFileManager(File dir, String dbName) {
|
||||||
return new DummyBufferFileMgr(dir, dbName, false, false);
|
return new DummyBufferFileMgr(dir, dbName, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone a DBHandle backed by a new temporary source buffer file.
|
||||||
|
* The specified dbh will remain associated with its original source buffer file.
|
||||||
|
* @param dbh DBHandle to clone
|
||||||
|
* @return new DBhandle
|
||||||
|
* @throws IOException if a file IO error occurs
|
||||||
|
*/
|
||||||
|
public static DBHandle cloneDbHandle(DBHandle dbh) throws IOException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
File tmpFile = File.createTempFile("tmp", ".db");
|
||||||
|
tmpFile.delete();
|
||||||
|
|
||||||
|
LocalBufferFile bf = new LocalBufferFile(tmpFile, dbh.getBufferSize());
|
||||||
|
dbh.saveAs(bf, dbh.getDatabaseId(), false, TaskMonitor.DUMMY);
|
||||||
|
tmpFile.deleteOnExit();
|
||||||
|
|
||||||
|
return new DBHandle(bf);
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
throw new IOException(e); // unexpected
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DuplicateKeyException extends Exception {
|
class DuplicateKeyException extends Exception {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user