mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-06-01 06:25:26 +08:00
Merge branch 'GP-5586_ghidra1_StackEditorIssues'
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -511,7 +511,7 @@ def on_breakpoint_hit(*args) -> None:
|
||||
@log_errors
|
||||
def on_exception(*args) -> None:
|
||||
# print("ON_EXCEPTION: args={}".format(args))
|
||||
return DbgEng.DEBUG_STATUS_BREAK
|
||||
return DbgEng.DEBUG_STATUS_NO_CHANGE
|
||||
|
||||
|
||||
@util.dbg.eng_thread
|
||||
|
||||
+1
-5
@@ -419,11 +419,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
|
||||
if (program == null) {
|
||||
return state;
|
||||
}
|
||||
SaveState pstate = plugin.readProgramLaunchConfig(program, getConfigName(), forPrompt);
|
||||
if (!pstate.isEmpty()) {
|
||||
state = pstate;
|
||||
}
|
||||
return state;
|
||||
return plugin.readProgramLaunchConfig(program, getConfigName(), forPrompt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+108
-123
@@ -248,17 +248,17 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeInstance validateComponentDataType(int rowIndex, String dtString)
|
||||
throws UsrException {
|
||||
dtString = DataTypeHelper.stripWhiteSpace(dtString);
|
||||
if ((dtString == null) || (dtString.length() < 1)) {
|
||||
if (rowIndex == getNumComponents()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.validateComponentDataType(rowIndex, dtString);
|
||||
}
|
||||
// @Override
|
||||
// public DataTypeInstance validateComponentDataType(int rowIndex, String dtString)
|
||||
// throws UsrException {
|
||||
// dtString = DataTypeHelper.stripWhiteSpace(dtString);
|
||||
// if ((dtString == null) || (dtString.length() < 1)) {
|
||||
// if (rowIndex == getNumComponents()) {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// return super.validateComponentDataType(rowIndex, dtString);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean isAddAllowed(DataType dataType) {
|
||||
@@ -894,18 +894,18 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
protected abstract void replaceOriginalComponents();
|
||||
|
||||
@Override
|
||||
protected void checkIsAllowableDataType(DataType datatype) throws InvalidDataTypeException {
|
||||
protected void checkIsAllowableDataType(DataType dataType) throws InvalidDataTypeException {
|
||||
|
||||
super.checkIsAllowableDataType(datatype);
|
||||
super.checkIsAllowableDataType(dataType);
|
||||
|
||||
// Verify that we aren't adding this structure or anything that it is
|
||||
// part of to this editable structure.
|
||||
if (datatype.equals(viewComposite)) {
|
||||
String msg = "Data type \"" + datatype.getDisplayName() + "\" can't contain itself.";
|
||||
if (dataType.equals(viewComposite)) {
|
||||
String msg = "Data type \"" + dataType.getDisplayName() + "\" can't contain itself.";
|
||||
throw new InvalidDataTypeException(msg);
|
||||
}
|
||||
else if (DataTypeUtilities.isSecondPartOfFirst(datatype, viewComposite)) {
|
||||
String msg = "Data type \"" + datatype.getDisplayName() + "\" has \"" +
|
||||
else if (DataTypeUtilities.isSecondPartOfFirst(dataType, viewComposite)) {
|
||||
String msg = "Data type \"" + dataType.getDisplayName() + "\" has \"" +
|
||||
viewComposite.getDisplayName() + "\" within it.";
|
||||
throw new InvalidDataTypeException(msg);
|
||||
}
|
||||
@@ -1314,25 +1314,25 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
return;
|
||||
}
|
||||
|
||||
DataType dataType = viewDTM.getDataType(path.getCategoryPath(), path.getDataTypeName());
|
||||
DataType dataType = viewDTM.getDataType(path);
|
||||
if (dataType == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!path.equals(originalDataTypePath)) {
|
||||
DataType dt = viewDTM.getDataType(path);
|
||||
if (dt != null) {
|
||||
if (hasSubDt(viewComposite, path)) {
|
||||
String msg = "Removed sub-component data type \"" + path;
|
||||
setStatus(msg, true);
|
||||
}
|
||||
viewDTM.withTransaction("Removed Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
viewDTM.remove(dt, TaskMonitor.DUMMY);
|
||||
});
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
if (!viewDTM.isViewDataTypeFromOriginalDTM(dataType)) {
|
||||
return;
|
||||
}
|
||||
if (hasSubDt(viewComposite, path)) {
|
||||
String msg = "Removed sub-component data type \"" + path;
|
||||
setStatus(msg, true);
|
||||
}
|
||||
viewDTM.withTransaction("Removed Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
viewDTM.remove(dataType, TaskMonitor.DUMMY);
|
||||
});
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1366,56 +1366,7 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
|
||||
@Override
|
||||
public void dataTypeRenamed(DataTypeManager dtm, DataTypePath oldPath, DataTypePath newPath) {
|
||||
|
||||
if (dtm != originalDTM) {
|
||||
throw new AssertException("Listener only supports original DTM");
|
||||
}
|
||||
|
||||
if (!isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldPath.getDataTypeName().equals(newPath.getDataTypeName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String newName = newPath.getDataTypeName();
|
||||
String oldName = oldPath.getDataTypeName();
|
||||
|
||||
// Does the old name match our original name.
|
||||
// Check originalCompositeId to ensure original type is managed
|
||||
if (originalCompositeId != DataTypeManager.NULL_DATATYPE_ID &&
|
||||
oldPath.equals(originalDataTypePath)) {
|
||||
originalDataTypePath = newPath;
|
||||
try {
|
||||
if (viewComposite.getName().equals(oldName)) {
|
||||
setName(newName);
|
||||
}
|
||||
}
|
||||
catch (InvalidNameException | DuplicateNameException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for managed datatype changing
|
||||
DataType dt = viewDTM.getDataType(oldPath);
|
||||
if (dt == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
viewDTM.withTransaction("Renamed Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
try {
|
||||
dt.setName(newPath.getDataTypeName());
|
||||
}
|
||||
catch (InvalidNameException | DuplicateNameException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
dataTypeMoved(dtm, oldPath, newPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1429,31 +1380,64 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
return;
|
||||
}
|
||||
|
||||
DataType dt = viewDTM.getDataType(oldPath);
|
||||
if (dt == null) {
|
||||
if (oldPath.equals(newPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
viewDTM.withTransaction("Moved " + oldPath, () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
Category newDtCat = viewDTM.createCategory(newPath.getCategoryPath());
|
||||
newDtCat.moveDataType(dt, null);
|
||||
});
|
||||
}
|
||||
catch (DataTypeDependencyException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
String newName = newPath.getDataTypeName();
|
||||
String oldName = oldPath.getDataTypeName();
|
||||
|
||||
if (originalDataTypePath.getDataTypeName().equals(newPath.getDataTypeName()) &&
|
||||
originalDataTypePath.getCategoryPath().equals(oldPath.getCategoryPath())) {
|
||||
originalDataTypePath = newPath;
|
||||
CategoryPath newCategoryPath = newPath.getCategoryPath();
|
||||
CategoryPath oldCategoryPath = oldPath.getCategoryPath();
|
||||
|
||||
// Does the old name match our original name.
|
||||
// Check originalCompositeId to ensure original type is managed
|
||||
if (originalCompositeId != DataTypeManager.NULL_DATATYPE_ID &&
|
||||
oldPath.equals(originalDataTypePath)) {
|
||||
|
||||
viewDTM.withTransaction("Name Changed", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
originalDataTypePath = newPath;
|
||||
try {
|
||||
if (viewComposite.getName().equals(oldName)) {
|
||||
setName(newName);
|
||||
}
|
||||
if (!newCategoryPath.equals(oldCategoryPath)) {
|
||||
viewComposite.setCategoryPath(newCategoryPath);
|
||||
}
|
||||
}
|
||||
catch (InvalidNameException | DuplicateNameException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
compositeInfoChanged();
|
||||
}
|
||||
else {
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
// Check for managed datatype changing
|
||||
DataType originalDt = originalDTM.getDataType(newPath);
|
||||
if (!(originalDt instanceof DatabaseObject)) {
|
||||
return;
|
||||
}
|
||||
DataType dt = viewDTM.findMyDataTypeFromOriginalID(originalDTM.getID(originalDt));
|
||||
if (dt == null) {
|
||||
return;
|
||||
}
|
||||
viewDTM.withTransaction("Renamed Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
try {
|
||||
dt.setName(newName);
|
||||
if (!newCategoryPath.equals(oldCategoryPath)) {
|
||||
dt.setCategoryPath(newCategoryPath);
|
||||
}
|
||||
}
|
||||
catch (InvalidNameException | DuplicateNameException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1517,11 +1501,10 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
// potentially many types getting changed by one change.
|
||||
DataType changedDt = originalDTM.getDataType(path);
|
||||
if (!(changedDt instanceof DatabaseObject)) {
|
||||
// NOTE: viewDTM only maps view-to-original IDs for DataTypeDB
|
||||
return;
|
||||
}
|
||||
long originalId = originalDTM.getID(changedDt);
|
||||
DataType viewDt = viewDTM.findMyDataTypeFromOriginalID(originalId);
|
||||
DataType viewDt =
|
||||
viewDTM.findMyDataTypeFromOriginalID(originalDTM.getID(changedDt));
|
||||
if (viewDt == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1562,30 +1545,32 @@ public abstract class CompEditorModel<T extends Composite> extends CompositeEdit
|
||||
if (!oldPath.equals(originalDataTypePath)) {
|
||||
// Check for type which may be referenced by viewComposite
|
||||
DataType dt = viewDTM.getDataType(oldPath);
|
||||
if (dt != null) {
|
||||
if (hasSubDt(viewComposite, oldPath)) {
|
||||
String msg = "Replaced data type \"" + oldPath +
|
||||
"\", which is a sub-component of \"" + getOriginalDataTypeName() + "\".";
|
||||
setStatus(msg, true);
|
||||
}
|
||||
// NOTE: depending upon event sequence and handling a
|
||||
// re-load may have occurred and replacement may be unnecessary
|
||||
try {
|
||||
viewDTM.withTransaction("Replaced Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
viewDTM.replaceDataType(dt, newDataType, true);
|
||||
});
|
||||
}
|
||||
catch (DataTypeDependencyException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
|
||||
// Clear undo/redo stack to avoid inconsistency with originalDTM
|
||||
viewDTM.clearUndo();
|
||||
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
if (dt == null || !viewDTM.isViewDataTypeFromOriginalDTM(dt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasSubDt(viewComposite, oldPath)) {
|
||||
String msg = "Replaced data type \"" + oldPath +
|
||||
"\", which is a sub-component of \"" + getOriginalDataTypeName() + "\".";
|
||||
setStatus(msg, true);
|
||||
}
|
||||
// NOTE: depending upon event sequence and handling a
|
||||
// re-load may have occurred and replacement may be unnecessary
|
||||
try {
|
||||
viewDTM.withTransaction("Replaced Dependency", () -> {
|
||||
viewDTM.clearUndoOnChange();
|
||||
viewDTM.replaceDataType(dt, newDataType, true);
|
||||
});
|
||||
}
|
||||
catch (DataTypeDependencyException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
|
||||
// Clear undo/redo stack to avoid inconsistency with originalDTM
|
||||
viewDTM.clearUndo();
|
||||
|
||||
fireTableDataChanged();
|
||||
componentDataChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+60
-60
@@ -157,7 +157,7 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
originalDataTypePath = originalComposite.getDataTypePath();
|
||||
currentName = dataType.getName();
|
||||
|
||||
createViewCompositeFromOriginalComposite(originalComposite);
|
||||
createViewCompositeFromOriginalComposite();
|
||||
|
||||
// Listen so we can update editor if name changes for this structure.
|
||||
originalDTM.addDataTypeManagerListener(this);
|
||||
@@ -204,12 +204,10 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
}
|
||||
|
||||
/**
|
||||
* Create {@code viewComposite} and associated view datatype manager ({@code viewDTM}) and
|
||||
* changes listener(s) if required.
|
||||
*
|
||||
* @param original original composite being loaded
|
||||
* Create {@code viewComposite} and {@link CompositeViewerDataTypeManager viewDTM} for this
|
||||
* editor and the {@code originalComposite}.
|
||||
*/
|
||||
protected void createViewCompositeFromOriginalComposite(T original) {
|
||||
protected void createViewCompositeFromOriginalComposite() {
|
||||
|
||||
if (viewDTM != null) {
|
||||
viewDTM.close();
|
||||
@@ -217,8 +215,9 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
}
|
||||
|
||||
// Use temporary standalone view datatype manager
|
||||
viewDTM = new CompositeViewerDataTypeManager<>(original.getDataTypeManager().getName(),
|
||||
original, this::componentEdited, this::restoreEditor);
|
||||
viewDTM =
|
||||
new CompositeViewerDataTypeManager<>(originalComposite.getDataTypeManager().getName(),
|
||||
originalComposite, this::componentEdited, this::restoreEditor);
|
||||
|
||||
viewComposite = viewDTM.getResolvedViewComposite();
|
||||
|
||||
@@ -230,7 +229,7 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
// underlying datatype default setting value being presented when adjusting component
|
||||
// default settings.
|
||||
viewDTM.withTransaction("Load Settings",
|
||||
() -> cloneAllComponentSettings(original, viewComposite));
|
||||
() -> cloneAllComponentSettings(originalComposite, viewComposite));
|
||||
viewDTM.clearUndo();
|
||||
}
|
||||
|
||||
@@ -317,7 +316,6 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
throw new InvalidDataTypeException("Data types of size 0 are not allowed.");
|
||||
}
|
||||
|
||||
// TODO: Need to handle proper placement for big-endian within a larger component (i.e., right-justified)
|
||||
return DataTypeInstance.getDataTypeInstance(resultDt, resultLen,
|
||||
viewComposite.isPackingEnabled());
|
||||
}
|
||||
@@ -481,13 +479,13 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
dtName = previousDt.getDisplayName();
|
||||
}
|
||||
DataType newDt = null;
|
||||
int newLength = -1;
|
||||
int newLength;
|
||||
if (dataTypeObject instanceof DataTypeInstance dti) {
|
||||
newDt = resolve(dti.getDataType());
|
||||
newDt = dti.getDataType();
|
||||
newLength = dti.getLength();
|
||||
}
|
||||
else if (dataTypeObject instanceof DataType dt) {
|
||||
newDt = resolve(dt);
|
||||
newDt = dt;
|
||||
newLength = newDt.getLength();
|
||||
}
|
||||
else if (dataTypeObject instanceof String dtString) {
|
||||
@@ -506,6 +504,9 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
newLength = 0;
|
||||
}
|
||||
|
||||
DataType dataType = newDt.clone(originalDTM);
|
||||
newLength = newDt.getLength();
|
||||
|
||||
checkIsAllowableDataType(newDt);
|
||||
|
||||
if (newLength < 0) {
|
||||
@@ -535,8 +536,7 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
}
|
||||
|
||||
// Set component datatype and length on view composite
|
||||
DataType dataType = resolve(newDt); // probably already resolved
|
||||
setComponentDataTypeInstance(rowIndex, dataType, newLength);
|
||||
setComponentDataTypeInstance(rowIndex, newDt, newLength);
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -1434,51 +1434,51 @@ abstract public class CompositeEditorModel<T extends Composite> extends Composit
|
||||
* @return a valid data type instance or null if at blank line with no data type name.
|
||||
* @throws UsrException indicating that the data type is not valid.
|
||||
*/
|
||||
protected DataTypeInstance validateComponentDataType(int rowIndex, String dtString)
|
||||
throws UsrException {
|
||||
DataType dt = null;
|
||||
String dtName = "";
|
||||
dtString = DataTypeHelper.stripWhiteSpace(dtString);
|
||||
DataTypeComponent element = getComponent(rowIndex);
|
||||
if (element != null) {
|
||||
dt = element.getDataType();
|
||||
dtName = dt.getDisplayName();
|
||||
if (dtString.equals(dtName)) {
|
||||
return DataTypeInstance.getDataTypeInstance(element.getDataType(),
|
||||
element.getLength(), usesAlignedLengthComponents());
|
||||
}
|
||||
}
|
||||
|
||||
int newLength = 0;
|
||||
DataType newDt = DataTypeHelper.parseDataType(rowIndex, dtString, this, originalDTM,
|
||||
provider.dtmService);
|
||||
if (newDt == null) {
|
||||
if (dt != null) {
|
||||
throw new UsrException("No data type was specified.");
|
||||
}
|
||||
throw new AssertException("Can't set data type to null.");
|
||||
}
|
||||
|
||||
checkIsAllowableDataType(newDt);
|
||||
|
||||
newLength = newDt.getLength();
|
||||
if (newLength < 0) {
|
||||
DataTypeInstance sizedDataType = DataTypeHelper.getSizedDataType(provider, newDt,
|
||||
lastNumBytes, getMaxReplaceLength(rowIndex));
|
||||
newLength = sizedDataType.getLength();
|
||||
}
|
||||
|
||||
newDt = viewDTM.resolve(newDt, null);
|
||||
int maxLength = getMaxReplaceLength(rowIndex);
|
||||
if (newLength <= 0) {
|
||||
throw new UsrException("Can't currently add this data type.");
|
||||
}
|
||||
if (maxLength > 0 && newLength > maxLength) {
|
||||
throw new UsrException(newDt.getDisplayName() + " doesn't fit.");
|
||||
}
|
||||
return DataTypeInstance.getDataTypeInstance(newDt, newLength,
|
||||
usesAlignedLengthComponents());
|
||||
}
|
||||
// protected DataTypeInstance validateComponentDataType(int rowIndex, String dtString)
|
||||
// throws UsrException {
|
||||
// DataType dt = null;
|
||||
// String dtName = "";
|
||||
// dtString = DataTypeHelper.stripWhiteSpace(dtString);
|
||||
// DataTypeComponent element = getComponent(rowIndex);
|
||||
// if (element != null) {
|
||||
// dt = element.getDataType();
|
||||
// dtName = dt.getDisplayName();
|
||||
// if (dtString.equals(dtName)) {
|
||||
// return DataTypeInstance.getDataTypeInstance(element.getDataType(),
|
||||
// element.getLength(), usesAlignedLengthComponents());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// int newLength = 0;
|
||||
// DataType newDt = DataTypeHelper.parseDataType(rowIndex, dtString, this, originalDTM,
|
||||
// provider.dtmService);
|
||||
// if (newDt == null) {
|
||||
// if (dt != null) {
|
||||
// throw new UsrException("No data type was specified.");
|
||||
// }
|
||||
// throw new AssertException("Can't set data type to null.");
|
||||
// }
|
||||
//
|
||||
// checkIsAllowableDataType(newDt);
|
||||
//
|
||||
// newLength = newDt.getLength();
|
||||
// if (newLength < 0) {
|
||||
// DataTypeInstance sizedDataType = DataTypeHelper.getSizedDataType(provider, newDt,
|
||||
// lastNumBytes, getMaxReplaceLength(rowIndex));
|
||||
// newLength = sizedDataType.getLength();
|
||||
// }
|
||||
//
|
||||
// newDt = viewDTM.resolve(newDt, null);
|
||||
// int maxLength = getMaxReplaceLength(rowIndex);
|
||||
// if (newLength <= 0) {
|
||||
// throw new UsrException("Can't currently add this data type.");
|
||||
// }
|
||||
// if (maxLength > 0 && newLength > maxLength) {
|
||||
// throw new UsrException(newDt.getDisplayName() + " doesn't fit.");
|
||||
// }
|
||||
// return DataTypeInstance.getDataTypeInstance(newDt, newLength,
|
||||
// usesAlignedLengthComponents());
|
||||
// }
|
||||
|
||||
@SuppressWarnings("unused") // the exception is thrown by subclasses
|
||||
protected void validateComponentName(int rowIndex, String name) throws UsrException {
|
||||
|
||||
+6
-3
@@ -47,8 +47,7 @@ import utilities.util.reflection.ReflectionUtilities;
|
||||
* @param <M> Specific {@link CompositeEditorModel} implementation which supports editing T
|
||||
*/
|
||||
public abstract class CompositeEditorProvider<T extends Composite, M extends CompositeEditorModel<T>>
|
||||
extends ComponentProviderAdapter
|
||||
implements EditorProvider, EditorActionListener {
|
||||
extends ComponentProviderAdapter implements EditorProvider, EditorActionListener {
|
||||
|
||||
protected static final Icon EDITOR_ICON = new GIcon("icon.plugin.composite.editor.provider");
|
||||
|
||||
@@ -317,7 +316,7 @@ public abstract class CompositeEditorProvider<T extends Composite, M extends Com
|
||||
// Check for changes and prompt user to check if saving them.
|
||||
if (editorModel.isValidName() && editorModel.hasChanges()) {
|
||||
String question = "The " + editorModel.getTypeName() + " Editor is closing.\n" +
|
||||
"Save the changes to " + getDtPath() + "?";
|
||||
"Save the changes to " + getDisplayName() + "?";
|
||||
String title = "Save " + editorModel.getTypeName() + " Editor Changes?";
|
||||
int response;
|
||||
if (allowCancel) {
|
||||
@@ -337,6 +336,10 @@ public abstract class CompositeEditorProvider<T extends Composite, M extends Com
|
||||
return 2;
|
||||
}
|
||||
|
||||
protected String getDisplayName() {
|
||||
return getDtPath().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWindowSubMenuName() {
|
||||
return getName();
|
||||
|
||||
+66
-17
@@ -19,6 +19,8 @@ import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.help.UnsupportedOperationException;
|
||||
|
||||
import db.util.ErrorHandler;
|
||||
import ghidra.program.database.DatabaseObject;
|
||||
import ghidra.program.model.data.*;
|
||||
@@ -66,16 +68,15 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
private TreeSet<Long> orphanIds = new TreeSet<>();
|
||||
|
||||
/**
|
||||
* Creates a data type manager that the structure editor will use internally for managing
|
||||
* dependencies for an unmanaged structure being edited. A single transaction will be started
|
||||
* with this instantiation and held open until this instance is closed. Undo/redo is
|
||||
* not be supported.
|
||||
* Creates a data type manager that the composite editor will use internally for managing
|
||||
* dependencies without resolving the actual composite being edited. A single transaction
|
||||
* will be started with this instantiation and held open until this instance is closed.
|
||||
* Undo/redo and datatype pruning is not be supported.
|
||||
* @param rootName the root name for this data type manager (usually the program name).
|
||||
* @param originalDTM the original data type manager.
|
||||
*/
|
||||
public CompositeViewerDataTypeManager(String rootName, DataTypeManager originalDTM) {
|
||||
this(rootName, originalDTM, null, null, null);
|
||||
clearUndo();
|
||||
transactionId = startTransaction("Composite Edit");
|
||||
}
|
||||
|
||||
@@ -123,8 +124,7 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T resolveViewComposite() {
|
||||
return originalComposite != null ? (T) super.resolve(originalComposite, null)
|
||||
: null;
|
||||
return originalComposite != null ? (T) super.resolve(originalComposite, null) : null;
|
||||
}
|
||||
|
||||
private void initializeArchitecture() {
|
||||
@@ -158,12 +158,18 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
if (!isUndoRedoAllowed()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
dataTypeIDMap.invalidate();
|
||||
super.undo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void redo() {
|
||||
if (!isUndoRedoAllowed()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
dataTypeIDMap.invalidate();
|
||||
super.redo();
|
||||
}
|
||||
@@ -237,10 +243,12 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
public DataType replaceDataType(DataType existingViewDt, DataType replacementDt,
|
||||
boolean updateCategoryPath) throws DataTypeDependencyException {
|
||||
|
||||
long viewDtId = getID(existingViewDt);
|
||||
if (existingViewDt.getDataTypeManager() != this) {
|
||||
throw new IllegalArgumentException("datatype is not from this manager");
|
||||
}
|
||||
|
||||
if (existingViewDt instanceof DatabaseObject) {
|
||||
dataTypeIDMap.remove(viewDtId);
|
||||
dataTypeIDMap.remove(getID(existingViewDt));
|
||||
}
|
||||
|
||||
DataType newResolvedDt =
|
||||
@@ -259,10 +267,12 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
@Override
|
||||
public boolean remove(DataType existingViewDt, TaskMonitor monitor) {
|
||||
|
||||
long viewDtId = getID(existingViewDt);
|
||||
if (existingViewDt.getDataTypeManager() != this) {
|
||||
throw new IllegalArgumentException("datatype is not from this manager");
|
||||
}
|
||||
|
||||
if (existingViewDt instanceof DatabaseObject) {
|
||||
dataTypeIDMap.remove(viewDtId);
|
||||
dataTypeIDMap.remove(getID(existingViewDt));
|
||||
}
|
||||
|
||||
return super.remove(existingViewDt, monitor);
|
||||
@@ -373,7 +383,7 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
if (committed && dataTypeChanged && changeCallback != null) {
|
||||
Swing.runLater(() -> changeCallback.call());
|
||||
}
|
||||
|
||||
|
||||
if (getTransactionCount() == 0) {
|
||||
dataTypeChanged = false;
|
||||
}
|
||||
@@ -432,14 +442,53 @@ public class CompositeViewerDataTypeManager<T extends Composite> extends StandAl
|
||||
}
|
||||
}
|
||||
|
||||
public DataType findOriginalDataTypeFromMyID(long myId) {
|
||||
Long originalId = dataTypeIDMap.getOriginalIDFromViewID(myId);
|
||||
return originalId != null ? originalDTM.getDataType(originalId) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a resolved DB-datatype within this manager based upon its source datatype's ID
|
||||
* within the original datatype manager associated with this manager. This method is
|
||||
* useful when attempting to matchup a datatype within this manager to one which has changed
|
||||
* within the original datatype manager.
|
||||
*
|
||||
* @param originalId datatype ID within original datatype manager
|
||||
* @return matching DB-datatype or null if not found
|
||||
*/
|
||||
public DataType findMyDataTypeFromOriginalID(long originalId) {
|
||||
Long myId = dataTypeIDMap.getViewIDFromOriginalID(originalId);
|
||||
return myId != null ? getDataType(myId) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a resolved DB-datatype within the original datatype manager based upon a resolved
|
||||
* datatype's ID within this manager. This method is useful when attempting to matchup a
|
||||
* datatype within this manager to one which has possibly changed within the original
|
||||
* datatype manager.
|
||||
*
|
||||
* @param myId resolved datatype ID within this datatype manager
|
||||
* @return matching DB-datatype or null if not found
|
||||
*/
|
||||
public DataType findOriginalDataTypeFromMyID(long myId) {
|
||||
Long originalId = dataTypeIDMap.getOriginalIDFromViewID(myId);
|
||||
return originalId != null ? originalDTM.getDataType(originalId) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the specified datatype which has previsouly been resolved to this datatype
|
||||
* manager originated from original composite's source (e.g., program).
|
||||
* <P>
|
||||
* NOTE: Non-DB datatypes will always return false.
|
||||
*
|
||||
* @param existingViewDt existing datatype which has previously been resolved to this
|
||||
* datatype manager.
|
||||
* @return true if specified datatype originated from this manager's associated original
|
||||
* datatype manager.
|
||||
*/
|
||||
public boolean isViewDataTypeFromOriginalDTM(DataType existingViewDt) {
|
||||
if (existingViewDt.getDataTypeManager() != this) {
|
||||
throw new IllegalArgumentException("datatype is not from this manager");
|
||||
}
|
||||
if (!(existingViewDt instanceof DatabaseObject)) {
|
||||
return false;
|
||||
}
|
||||
return dataTypeIDMap.getOriginalIDFromViewID(getID(existingViewDt)) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+29
-29
@@ -199,35 +199,35 @@ abstract class CompositeViewerModel<T extends Composite> extends AbstractTableMo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the data type against the indicated data type manager using the specified
|
||||
* conflictHandler. In general, a transaction should have already been initiated prior to
|
||||
* calling this method so that the true nature of the transaction may be established for
|
||||
* use with undo/redo (e.g., Set Datatype).
|
||||
*
|
||||
* @param dataType the data type to be resolved
|
||||
* @param resolveDtm the data type manager to resolve the data type against
|
||||
* @param conflictHandler the handler to be used for any conflicts encountered while resolving
|
||||
* @return the resolved data type
|
||||
*/
|
||||
protected final DataType resolveDataType(DataType dataType, DataTypeManager resolveDtm,
|
||||
DataTypeConflictHandler conflictHandler) {
|
||||
if (resolveDtm == null || dataType == DataType.DEFAULT) {
|
||||
return DataType.DEFAULT;
|
||||
}
|
||||
return resolveDtm.withTransaction("Resolve " + dataType.getPathName(), () -> {
|
||||
return resolveDtm.resolve(dataType, conflictHandler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the indicated data type against the working copy in the viewer's data type manager.
|
||||
* @param dataType the data type
|
||||
* @return the working copy of the data type.
|
||||
*/
|
||||
public DataType resolve(DataType dataType) {
|
||||
return resolveDataType(dataType, viewDTM, null);
|
||||
}
|
||||
// /**
|
||||
// * Resolves the data type against the indicated data type manager using the specified
|
||||
// * conflictHandler. In general, a transaction should have already been initiated prior to
|
||||
// * calling this method so that the true nature of the transaction may be established for
|
||||
// * use with undo/redo (e.g., Set Datatype).
|
||||
// *
|
||||
// * @param dataType the data type to be resolved
|
||||
// * @param resolveDtm the data type manager to resolve the data type against
|
||||
// * @param conflictHandler the handler to be used for any conflicts encountered while resolving
|
||||
// * @return the resolved data type
|
||||
// */
|
||||
// protected final DataType resolveDataType(DataType dataType, DataTypeManager resolveDtm,
|
||||
// DataTypeConflictHandler conflictHandler) {
|
||||
// if (resolveDtm == null || dataType == DataType.DEFAULT) {
|
||||
// return DataType.DEFAULT;
|
||||
// }
|
||||
// return resolveDtm.withTransaction("Resolve " + dataType.getPathName(), () -> {
|
||||
// return resolveDtm.resolve(dataType, conflictHandler);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Resolves the indicated data type against the working copy in the viewer's data type manager.
|
||||
// * @param dataType the data type
|
||||
// * @return the working copy of the data type.
|
||||
// */
|
||||
// public DataType resolve(DataType dataType) {
|
||||
// return resolveDataType(dataType, viewDTM, null);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Gets the current row
|
||||
|
||||
-726
File diff suppressed because it is too large
Load Diff
-44
@@ -1,44 +0,0 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.stackeditor;
|
||||
|
||||
import ghidra.program.model.data.*;
|
||||
|
||||
public interface BiDirectionStructure extends Structure {
|
||||
|
||||
/**
|
||||
* Get the length of this DataType in the negative direction.
|
||||
* @return the length of this DataType in the negative direction.
|
||||
*/
|
||||
public abstract int getNegativeLength();
|
||||
|
||||
/**
|
||||
* Get the length of this DataType in the positive direction.
|
||||
* @return the length of this DataType in the positive direction.
|
||||
*/
|
||||
public abstract int getPositiveLength();
|
||||
|
||||
/**
|
||||
* Get the component offset which represents the division point
|
||||
* between the positive and negative halves of the structure.
|
||||
* @return split offset
|
||||
*/
|
||||
public abstract int getSplitOffset();
|
||||
|
||||
public DataTypeComponent addNegative(DataType dataType, int length, String name, String comment);
|
||||
|
||||
public DataTypeComponent addPositive(DataType dataType, int length, String name, String comment);
|
||||
}
|
||||
+226
-267
File diff suppressed because it is too large
Load Diff
+63
-60
@@ -23,16 +23,13 @@ import ghidra.app.plugin.core.compositeeditor.*;
|
||||
import ghidra.framework.model.*;
|
||||
import ghidra.framework.plugintool.Plugin;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.CategoryPath;
|
||||
import ghidra.program.model.data.DataTypePath;
|
||||
import ghidra.program.model.listing.Function;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
import ghidra.program.model.symbol.SymbolType;
|
||||
import ghidra.program.util.ProgramChangeRecord;
|
||||
import ghidra.program.util.ProgramEvent;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.task.SwingUpdateManager;
|
||||
|
||||
/**
|
||||
* Editor for a Function Stack.
|
||||
@@ -45,6 +42,31 @@ public class StackEditorProvider
|
||||
private Function function;
|
||||
private StackEditorModel stackModel;
|
||||
|
||||
boolean scheduleRefreshName = false;
|
||||
boolean scheduleReload = false;
|
||||
|
||||
/**
|
||||
* Delay model update caused by Program change events.
|
||||
*/
|
||||
SwingUpdateManager delayedUpdateMgr = new SwingUpdateManager(200, 200, () -> {
|
||||
try {
|
||||
if (function.isDeleted()) {
|
||||
stackModel.functionChanged(false);
|
||||
return;
|
||||
}
|
||||
if (scheduleRefreshName) {
|
||||
updateTitle();
|
||||
}
|
||||
if (scheduleReload) {
|
||||
stackModel.functionChanged(false);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
scheduleRefreshName = false;
|
||||
scheduleReload = false;
|
||||
}
|
||||
});
|
||||
|
||||
public StackEditorProvider(Plugin plugin, Function function) {
|
||||
super(plugin);
|
||||
this.program = function.getProgram();
|
||||
@@ -56,15 +78,22 @@ public class StackEditorProvider
|
||||
|
||||
initializeActions();
|
||||
editorPanel = new StackEditorPanel(program, stackModel, this);
|
||||
setTitle(getName() + " - " + getProviderSubTitle(function));
|
||||
updateTitle();
|
||||
plugin.getTool().addComponentProvider(this, true);
|
||||
|
||||
addActionsToTool();
|
||||
editorPanel.getTable().requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateTitle() {
|
||||
setTabText(function.getName());
|
||||
setTitle(getName() + " - " + getProviderSubTitle(function));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
delayedUpdateMgr.dispose();
|
||||
program.removeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
@@ -84,6 +113,11 @@ public class StackEditorProvider
|
||||
return "Stack Editor";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDisplayName() {
|
||||
return "stack frame: " + function.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpName() {
|
||||
return "Stack_Editor";
|
||||
@@ -147,32 +181,6 @@ public class StackEditorProvider
|
||||
return actionMgr.getAllActions();
|
||||
}
|
||||
|
||||
private void refreshName() {
|
||||
StackFrameDataType origDt = stackModel.getOriginalComposite();
|
||||
StackFrameDataType viewDt = stackModel.getEditorStack();
|
||||
String oldName = origDt.getName();
|
||||
String newName = function.getName();
|
||||
if (oldName.equals(newName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTitle("Stack Editor: " + newName);
|
||||
try {
|
||||
origDt.setName(newName);
|
||||
if (viewDt.getName().equals(oldName)) {
|
||||
viewDt.setName(newName);
|
||||
}
|
||||
}
|
||||
catch (InvalidNameException e) {
|
||||
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
CategoryPath oldCategoryPath = origDt.getCategoryPath();
|
||||
DataTypePath oldDtPath = new DataTypePath(oldCategoryPath, oldName);
|
||||
DataTypePath newDtPath = new DataTypePath(oldCategoryPath, newName);
|
||||
stackModel.dataTypeRenamed(stackModel.getOriginalDataTypeManager(), oldDtPath, newDtPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void domainObjectChanged(DomainObjectChangedEvent event) {
|
||||
if (!isVisible()) {
|
||||
@@ -181,35 +189,40 @@ public class StackEditorProvider
|
||||
|
||||
int recordCount = event.numRecords();
|
||||
for (int i = 0; i < recordCount; i++) {
|
||||
|
||||
DomainObjectChangeRecord rec = event.getChangeRecord(i);
|
||||
EventType eventType = rec.getEventType();
|
||||
if (eventType == DomainObjectEvent.RESTORED) {
|
||||
refreshName();
|
||||
// NOTE: editorPanel should be notified of restored datatype manager via the
|
||||
// CompositeViewerModel's DataTypeManagerChangeListener restored method
|
||||
return;
|
||||
|
||||
// NOTE: RESTORED event can be ignored here since the model will be notified
|
||||
// of restored datatype manager via the CompositeViewerModel's
|
||||
// DataTypeManagerChangeListener restored method.
|
||||
|
||||
if (eventType == DomainObjectEvent.FILE_CHANGED) {
|
||||
scheduleRefreshName = true;
|
||||
delayedUpdateMgr.updateLater();
|
||||
continue;
|
||||
}
|
||||
if (eventType instanceof ProgramEvent type) {
|
||||
switch (type) {
|
||||
case FUNCTION_REMOVED:
|
||||
Function func = (Function) ((ProgramChangeRecord) rec).getObject();
|
||||
if (func == function) {
|
||||
this.dispose();
|
||||
// Close the Editor.
|
||||
tool.setStatusInfo("Stack Editor was closed for " + getName());
|
||||
dispose();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
case SYMBOL_RENAMED:
|
||||
case SYMBOL_DATA_CHANGED:
|
||||
Symbol sym = (Symbol) ((ProgramChangeRecord) rec).getObject();
|
||||
SymbolType symType = sym.getSymbolType();
|
||||
if (symType == SymbolType.LABEL) {
|
||||
if (sym.isPrimary() &&
|
||||
sym.getAddress().equals(function.getEntryPoint())) {
|
||||
refreshName();
|
||||
}
|
||||
if (sym.isPrimary() && sym.getAddress().equals(function.getEntryPoint())) {
|
||||
scheduleRefreshName = true;
|
||||
delayedUpdateMgr.updateLater();
|
||||
}
|
||||
else if (inCurrentFunction(rec)) {
|
||||
reloadFunction();
|
||||
scheduleReload = true;
|
||||
delayedUpdateMgr.updateLater();
|
||||
}
|
||||
break;
|
||||
case FUNCTION_CHANGED:
|
||||
@@ -217,15 +230,15 @@ public class StackEditorProvider
|
||||
case SYMBOL_REMOVED:
|
||||
case SYMBOL_ADDRESS_CHANGED:
|
||||
if (inCurrentFunction(rec)) {
|
||||
reloadFunction();
|
||||
scheduleReload = true;
|
||||
delayedUpdateMgr.updateLater();
|
||||
}
|
||||
break;
|
||||
case SYMBOL_PRIMARY_STATE_CHANGED:
|
||||
sym = (Symbol) ((ProgramChangeRecord) rec).getNewValue();
|
||||
symType = sym.getSymbolType();
|
||||
if (symType == SymbolType.LABEL &&
|
||||
sym.getAddress().equals(function.getEntryPoint())) {
|
||||
refreshName();
|
||||
if (sym.getAddress().equals(function.getEntryPoint())) {
|
||||
scheduleRefreshName = true;
|
||||
delayedUpdateMgr.updateLater();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -234,16 +247,6 @@ public class StackEditorProvider
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadFunction() {
|
||||
if (!stackModel.hasChanges()) {
|
||||
stackModel.load(function);
|
||||
}
|
||||
else {
|
||||
stackModel.stackChangedExternally(true);
|
||||
editorPanel.setStatus("Stack may have been changed externally--data may be stale.");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean inCurrentFunction(DomainObjectChangeRecord record) {
|
||||
if (!(record instanceof ProgramChangeRecord)) {
|
||||
return false;
|
||||
|
||||
+1293
-454
File diff suppressed because it is too large
Load Diff
-131
@@ -1,131 +0,0 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.stackeditor;
|
||||
|
||||
import ghidra.docking.settings.Settings;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.Variable;
|
||||
import ghidra.program.model.listing.VariableStorage;
|
||||
import ghidra.program.model.mem.MemBuffer;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.util.InvalidNameException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
public class StackPieceDataType extends DataTypeImpl {
|
||||
|
||||
private final Variable variable;
|
||||
|
||||
StackPieceDataType(Variable var, DataTypeManager dataMgr) {
|
||||
super(CategoryPath.ROOT, getPieceName(var), dataMgr);
|
||||
variable = var;
|
||||
}
|
||||
|
||||
private static String getPieceName(Variable var) {
|
||||
VariableStorage storage = var.getVariableStorage();
|
||||
Varnode stackVarnode = storage.getLastVarnode();
|
||||
int pieceLen = stackVarnode.getSize();
|
||||
return var.getDataType().getName() + ":" + pieceLen + " (piece)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType clone(DataTypeManager dtm) {
|
||||
if (dtm == getDataTypeManager()) {
|
||||
return this;
|
||||
}
|
||||
throw new IllegalArgumentException("May not be cloned with new DataTypeManager");
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType copy(DataTypeManager dtm) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCategoryPath(CategoryPath path) throws DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) throws InvalidNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNameAndCategory(CategoryPath path, String name)
|
||||
throws InvalidNameException, DuplicateNameException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMnemonic(Settings settings) {
|
||||
DataType dt = variable.getDataType();
|
||||
return dt.getMnemonic(settings) + ":" + getLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
VariableStorage storage = variable.getVariableStorage();
|
||||
Varnode stackVarnode = storage.getLastVarnode();
|
||||
return stackVarnode.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
// We could provide a description if needed
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepresentation(MemBuffer buf, Settings settings, int length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalent(DataType dt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeSizeChanged(DataType dt) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeDeleted(DataType dt) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeReplaced(DataType oldDt, DataType newDt) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataTypeNameChanged(DataType dt, String oldName) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dependsOn(DataType dt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-3
@@ -44,8 +44,6 @@ public abstract class AbstractStackEditorProviderTest extends AbstractStackEdito
|
||||
env.showTool();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================================================================================================
|
||||
// Private Methods
|
||||
//==================================================================================================
|
||||
@@ -140,7 +138,7 @@ public abstract class AbstractStackEditorProviderTest extends AbstractStackEdito
|
||||
Parameter parameter = function.getParameter(parameterIndex);
|
||||
SetVariableNameCmd cmd =
|
||||
new SetVariableNameCmd(parameter, newName, SourceType.USER_DEFINED);
|
||||
applyCmd(program, cmd);
|
||||
program.withTransaction("Rename Parameter", () -> cmd.applyTo(program)); // avoid blocking
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
||||
+21
-3
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -384,11 +384,29 @@ public class StackEditorCellEditTest extends AbstractStackEditorTest {
|
||||
typeInCellEditor("testName1\n");
|
||||
assertTrue(applyAction.isEnabled());
|
||||
|
||||
// Change name back and apply disables
|
||||
// Attempt use of another default name
|
||||
clickTableCell(getTable(), 0, colNum, 2);
|
||||
assertIsEditingField(0, colNum);
|
||||
selectAllInCellEditor();
|
||||
typeInCellEditor("local_8\n");
|
||||
assertStatus("Cannot set a stack variable name to a default value");
|
||||
assertCellString("testName1", 0, colNum);
|
||||
assertTrue(applyAction.isEnabled());
|
||||
|
||||
// Change name back to original and apply disables
|
||||
clickTableCell(getTable(), 0, colNum, 2);
|
||||
assertIsEditingField(0, colNum);
|
||||
selectAllInCellEditor();
|
||||
typeInCellEditor("local_10\n");
|
||||
assertCellString("local_10", 0, colNum);
|
||||
assertTrue(!applyAction.isEnabled());
|
||||
|
||||
// Change name back to original and apply disables
|
||||
clickTableCell(getTable(), 0, colNum, 2);
|
||||
assertIsEditingField(0, colNum);
|
||||
selectAllInCellEditor();
|
||||
typeInCellEditor("\b\n"); // clear entry
|
||||
assertCellString("local_10", 0, colNum);
|
||||
assertTrue(!applyAction.isEnabled());
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -200,7 +200,7 @@ public class StackEditorEnablementTest extends AbstractStackEditorTest {
|
||||
public void testCentralComponentSelectedEnablement() throws Exception {
|
||||
init(SIMPLE_STACK);
|
||||
|
||||
// Check enablement on central component selected.
|
||||
// Check enablement on central defined-component selected which has undefined datatype
|
||||
|
||||
runSwing(() -> model.setSelection(new int[] { 1 }));
|
||||
int numBytes = getModel().getMaxReplaceLength(1);
|
||||
|
||||
+12
-2
@@ -19,8 +19,7 @@ import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -324,6 +323,8 @@ public class StackEditorProvider1Test extends AbstractStackEditorProviderTest {
|
||||
int parameterIndex = 0;
|
||||
Parameter parameter = renameParameterInListing(parameterIndex, "listing.test.name");
|
||||
|
||||
waitForSwing();
|
||||
|
||||
// Verify the provider's name for that parameter is updated
|
||||
String modelParameterName = getParameterNameFromModel(parameterIndex);
|
||||
assertEquals(parameter.getName(), modelParameterName);
|
||||
@@ -342,6 +343,9 @@ public class StackEditorProvider1Test extends AbstractStackEditorProviderTest {
|
||||
// Change the name of a parameter in the Listing
|
||||
renameParameterInListing(parameterIndex, "listing.test.name");
|
||||
|
||||
JDialog reloadDialog = waitForJDialog("Reload Stack Editor?");
|
||||
pressButton(reloadDialog, "No");
|
||||
|
||||
// Verify the name of the parameter in the provider is not changed from the original edit
|
||||
String currentModelName = getParameterNameFromModel(parameterIndex);
|
||||
assertEquals(newModelName, currentModelName);
|
||||
@@ -360,6 +364,9 @@ public class StackEditorProvider1Test extends AbstractStackEditorProviderTest {
|
||||
// Change the name of a parameter in the Listing
|
||||
renameParameterInListing(parameterIndex, "listing.test.name");
|
||||
|
||||
JDialog reloadDialog = waitForJDialog("Reload Stack Editor?");
|
||||
pressButton(reloadDialog, "No");
|
||||
|
||||
// Press Apply
|
||||
apply();
|
||||
|
||||
@@ -386,6 +393,9 @@ public class StackEditorProvider1Test extends AbstractStackEditorProviderTest {
|
||||
String newListingText = "listing.test.name";
|
||||
renameParameterInListing(parameterIndex, newListingText);
|
||||
|
||||
JDialog reloadDialog = waitForJDialog("Reload Stack Editor?");
|
||||
pressButton(reloadDialog, "No");
|
||||
|
||||
// Press Apply
|
||||
apply();
|
||||
|
||||
|
||||
+13
-8
@@ -108,6 +108,7 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
||||
*/
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
|
||||
if (blockKeyInput(event)) {
|
||||
return true; // let NO events through!
|
||||
}
|
||||
@@ -143,10 +144,19 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
||||
// actions registered on the focused component are allowed to process the event before our
|
||||
// action system. This allows clients to perform custom event processing without the action
|
||||
// system interfering.
|
||||
if (processComponentKeyListeners(event) || processInputAndActionMaps(event)) {
|
||||
if (processComponentKeyListeners(event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there is a registered Java action, let the normal Java event flow process the event.
|
||||
// (This will only work as expected if the Java action is registered for key pressed events.
|
||||
// If it is registered for released events, and we have a valid and enabled docking action,
|
||||
// then the docking action will take precedence, since docking actions are always registered
|
||||
// for key pressed events.)
|
||||
if (hasJavaAction(event)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!executableAction.isValid()) {
|
||||
// The action is not currently valid for the given focus owner. Let all key strokes go
|
||||
// to Java when we have no valid context. This allows keys like Escape to work on Java
|
||||
@@ -380,7 +390,7 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
||||
//
|
||||
// returns true if there is a focused component that has an action for the given event
|
||||
// and it processes that action.
|
||||
private boolean processInputAndActionMaps(KeyEvent event) {
|
||||
private boolean hasJavaAction(KeyEvent event) {
|
||||
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(event);
|
||||
Component focusOwner = focusProvider.getFocusOwner();
|
||||
@@ -390,12 +400,7 @@ public class KeyBindingOverrideKeyEventDispatcher implements KeyEventDispatcher
|
||||
|
||||
JComponent jComponent = (JComponent) focusOwner;
|
||||
Action action = getJavaActionForComponent(jComponent, keyStroke);
|
||||
if (action != null) {
|
||||
Object source = event.getSource();
|
||||
int modifiers = event.getModifiersEx();
|
||||
return SwingUtilities.notifyAction(action, keyStroke, event, source, modifiers);
|
||||
}
|
||||
return false;
|
||||
return action != null && action.isEnabled();
|
||||
}
|
||||
|
||||
private Action getJavaActionForComponent(JComponent jComponent, KeyStroke keyStroke) {
|
||||
|
||||
@@ -147,7 +147,6 @@ public interface Span<N, S extends Span<N, S>> extends Comparable<S> {
|
||||
* Render the given span as a string
|
||||
*
|
||||
* @param s the span
|
||||
* @param nToString a function to convert n to a string
|
||||
* @return the string
|
||||
*/
|
||||
default String toString(S s) {
|
||||
|
||||
+15
-6
@@ -36,8 +36,7 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
private final ComponentDBAdapter adapter;
|
||||
private final DBRecord record; // null record -> immutable component
|
||||
private final CompositeDB parent;
|
||||
|
||||
private DataType cachedDataType; // required for bit-fields during packing process
|
||||
private final DataType cachedDataType; // used by immutable defined component (no record)
|
||||
|
||||
private int ordinal;
|
||||
private int offset;
|
||||
@@ -56,9 +55,15 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
*/
|
||||
DataTypeComponentDB(DataTypeManagerDB dataMgr, CompositeDB parent, int ordinal, int offset,
|
||||
DataType datatype, int length) {
|
||||
this(dataMgr, parent, ordinal, offset);
|
||||
this.dataMgr = dataMgr;
|
||||
this.parent = parent;
|
||||
this.cachedDataType = datatype;
|
||||
|
||||
this.ordinal = ordinal;
|
||||
this.offset = offset;
|
||||
this.length = length;
|
||||
this.record = null;
|
||||
this.adapter = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,6 +78,8 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
this.dataMgr = dataMgr;
|
||||
this.parent = parent;
|
||||
this.ordinal = ordinal;
|
||||
this.cachedDataType = null;
|
||||
|
||||
this.offset = offset;
|
||||
this.length = 1;
|
||||
this.record = null;
|
||||
@@ -90,11 +97,13 @@ class DataTypeComponentDB implements InternalDataTypeComponent {
|
||||
DBRecord record) {
|
||||
this.dataMgr = dataMgr;
|
||||
this.adapter = adapter;
|
||||
this.cachedDataType = null;
|
||||
this.record = record;
|
||||
|
||||
this.parent = parent;
|
||||
ordinal = record.getIntValue(ComponentDBAdapter.COMPONENT_ORDINAL_COL);
|
||||
offset = record.getIntValue(ComponentDBAdapter.COMPONENT_OFFSET_COL);
|
||||
length = record.getIntValue(ComponentDBAdapter.COMPONENT_SIZE_COL);
|
||||
this.ordinal = record.getIntValue(ComponentDBAdapter.COMPONENT_ORDINAL_COL);
|
||||
this.offset = record.getIntValue(ComponentDBAdapter.COMPONENT_OFFSET_COL);
|
||||
this.length = record.getIntValue(ComponentDBAdapter.COMPONENT_SIZE_COL);
|
||||
if (isZeroBitFieldComponent()) {
|
||||
length = 0; // previously stored as 1, force to 0
|
||||
}
|
||||
|
||||
+6
-3
@@ -1378,11 +1378,13 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
* @param componentName name of component replacement (may be null)
|
||||
* @param comment comment for component replacement (may be null)
|
||||
* @return new/updated component (may be null if replacement is not a defined component)
|
||||
* @throws IllegalArgumentException if unable to identify/make sufficient space
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
private DataTypeComponent doComponentReplacement(
|
||||
LinkedList<DataTypeComponentDB> replacedComponents, int offset, DataType dataType,
|
||||
int length, String componentName, String comment) throws IOException {
|
||||
int length, String componentName, String comment)
|
||||
throws IllegalArgumentException, IOException {
|
||||
|
||||
// Attempt quick update of a single defined component if possible.
|
||||
// A quick update requires that component characteristics including length, offset,
|
||||
@@ -1416,13 +1418,14 @@ class StructureDB extends CompositeDB implements StructureInternal {
|
||||
|
||||
@Override
|
||||
public final DataTypeComponent replace(int ordinal, DataType dataType, int length)
|
||||
throws IllegalArgumentException {
|
||||
throws IllegalArgumentException, IndexOutOfBoundsException {
|
||||
return replace(ordinal, dataType, length, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataTypeComponent replace(int ordinal, DataType dataType, int length,
|
||||
String componentName, String comment) {
|
||||
String componentName, String comment)
|
||||
throws IllegalArgumentException, IndexOutOfBoundsException {
|
||||
lock.acquire();
|
||||
try {
|
||||
checkDeleted();
|
||||
|
||||
+8
-6
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -277,16 +277,18 @@ class FunctionStackFrame implements StackFrame {
|
||||
function.setLocalSize(size);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see ghidra.program.model.listing.StackFrame#getParameterSize()
|
||||
*/
|
||||
@Override
|
||||
public int getParameterSize() {
|
||||
function.manager.lock.acquire();
|
||||
try {
|
||||
checkIsValid();
|
||||
|
||||
// NOTE: This logic is sensitive to the existance of Local variables at the incorrect
|
||||
// stack offset placed before parameters. This can occur when adjustments are made to
|
||||
// the prototype model's stack pentry specification. Unfortunately, the distinction
|
||||
// between a parameter and a local is locked-in at the time of creation due to the
|
||||
// use of distinct symbol types.
|
||||
|
||||
int baseOffset = 0;
|
||||
Integer base = VariableUtilities.getBaseStackParamOffset(function);
|
||||
if (base != null) {
|
||||
|
||||
+3
-2
@@ -44,7 +44,8 @@ public interface Structure extends Composite {
|
||||
public DataTypeComponent getComponent(int ordinal) throws IndexOutOfBoundsException;
|
||||
|
||||
/**
|
||||
* Gets the first defined component located at or after the specified offset.
|
||||
* Gets the first defined component located at or after the specified offset. If a
|
||||
* component contains the specified offset that component will be returned.
|
||||
* Note: The returned component may be a zero-length component.
|
||||
*
|
||||
* @param offset the byte offset into this structure
|
||||
@@ -436,7 +437,7 @@ public interface Structure extends Composite {
|
||||
* @throws IllegalArgumentException if amount < 0
|
||||
*/
|
||||
public void growStructure(int amount);
|
||||
|
||||
|
||||
/**
|
||||
* Set the size of the structure to the specified byte-length. If the length is shortened defined
|
||||
* components will be cleared and removed as required.
|
||||
|
||||
-7
@@ -107,13 +107,6 @@ public interface StackFrame {
|
||||
*/
|
||||
public int getParameterOffset();
|
||||
|
||||
// /**
|
||||
// * Set the offset on the stack of the parameters.
|
||||
// *
|
||||
// * @param offset the start offset of parameters on the stack
|
||||
// */
|
||||
// public void setParameterOffset(int offset) throws InvalidInputException;
|
||||
|
||||
/**
|
||||
* Returns true if specified offset could correspond to a parameter
|
||||
* @param offset
|
||||
|
||||
Reference in New Issue
Block a user