mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-04 18:29:37 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
fb5ab7569d
20 changed files with 524 additions and 762 deletions
|
@ -204,7 +204,7 @@ public class BitFieldEditorPanel extends JPanel {
|
|||
private JComponent createDataTypeChoiceEditor() {
|
||||
|
||||
dtChoiceEditor =
|
||||
new DataTypeSelectionEditor(dtmService, -1, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||
new DataTypeSelectionEditor(dtmService, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
||||
dtChoiceEditor.setTabCommitsEdit(true);
|
||||
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
||||
|
@ -539,7 +539,7 @@ public class BitFieldEditorPanel extends JPanel {
|
|||
dtChoiceEditor.getDropDownTextField().setText("");
|
||||
fieldNameTextField.setText(null);
|
||||
fieldCommentTextField.setText(null);
|
||||
;
|
||||
|
||||
bitOffsetModel.setValue(0L);
|
||||
bitSizeModel.setValue(1L);
|
||||
}
|
||||
|
|
|
@ -1255,7 +1255,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
|
||||
Plugin plugin = provider.getPlugin();
|
||||
final PluginTool tool = plugin.getTool();
|
||||
editor = new DataTypeSelectionEditor(tool, maxLength,
|
||||
editor = new DataTypeSelectionEditor(tool,
|
||||
bitfieldAllowed ? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
||||
: AllowedDataTypes.SIZABLE_DYNAMIC);
|
||||
editor.setTabCommitsEdit(true);
|
||||
|
@ -1287,12 +1287,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
|||
}
|
||||
};
|
||||
|
||||
dataTypeChooserButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Swing.runLater(() -> stopEdit(tool));
|
||||
}
|
||||
});
|
||||
dataTypeChooserButton.addActionListener(e -> Swing.runLater(() -> stopEdit(tool)));
|
||||
|
||||
textField.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
|
|
|
@ -24,12 +24,8 @@ import docking.action.*;
|
|||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.util.datatype.DataTypeSelectionDialog;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.util.*;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||
|
||||
/**
|
||||
|
@ -58,121 +54,21 @@ public class ChooseDataTypeAction extends DockingAction {
|
|||
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
ListingActionContext programActionContext =
|
||||
(ListingActionContext) context.getContextObject();
|
||||
int maxSize = Integer.MAX_VALUE;
|
||||
Program program = programActionContext.getProgram();
|
||||
ProgramLocation loc = programActionContext.getLocation();
|
||||
ProgramSelection sel = programActionContext.getSelection();
|
||||
if (sel != null && !sel.isEmpty()) {
|
||||
InteriorSelection interiorSel = sel.getInteriorSelection();
|
||||
if (interiorSel != null) {
|
||||
maxSize = getSizeInsideStructure(program, interiorSel);
|
||||
}
|
||||
else {
|
||||
maxSize = getSizeForSelection(program, sel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] compPath = loc.getComponentPath();
|
||||
if (compPath != null && compPath.length > 0) {
|
||||
maxSize = getSizeInsideStructure(program, loc);
|
||||
}
|
||||
else {
|
||||
maxSize = getSizeForAddress(program, loc);
|
||||
}
|
||||
}
|
||||
|
||||
// unable to create data types at the current location
|
||||
if (maxSize < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pointer pointer = program.getDataTypeManager().getPointer(null);
|
||||
DataType dataType = getDataType(programActionContext, maxSize, pointer.getLength());
|
||||
ListingActionContext listingContext = (ListingActionContext) context.getContextObject();
|
||||
DataType dataType = getDataType(listingContext);
|
||||
if (dataType != null) {
|
||||
plugin.doCreateData(program, loc, sel, dataType, false);
|
||||
plugin.createData(dataType, listingContext, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int getSizeInsideStructure(Program program, InteriorSelection selection) {
|
||||
ProgramLocation location = selection.getFrom();
|
||||
Data dataComponent = getParentDataType(program, location);
|
||||
if (dataComponent == null) {
|
||||
return -1;
|
||||
}
|
||||
return selection.getByteLength();
|
||||
}
|
||||
|
||||
private int getSizeInsideStructure(Program program, ProgramLocation location) {
|
||||
Data dataComponent = getParentDataType(program, location);
|
||||
if (dataComponent == null) {
|
||||
return -1;
|
||||
}
|
||||
return getMaxSizeInStructure((Structure) dataComponent.getParent().getBaseDataType(),
|
||||
dataComponent.getComponentIndex());
|
||||
}
|
||||
|
||||
private int getSizeForAddress(Program program, ProgramLocation location) {
|
||||
|
||||
Address address = location.getAddress();
|
||||
Data data = program.getListing().getDataAt(address);
|
||||
if (data == null) {
|
||||
plugin.getTool().setStatusInfo("Create Data Failed! No data at " + address);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return getMaxSize(program, address);
|
||||
}
|
||||
|
||||
private Data getParentDataType(Program program, ProgramLocation location) {
|
||||
|
||||
int[] path = location.getComponentPath();
|
||||
Address address = location.getAddress();
|
||||
Data data = program.getListing().getDataContaining(address);
|
||||
Data dataComponent = null;
|
||||
if (data != null) {
|
||||
dataComponent = data.getComponent(path);
|
||||
}
|
||||
|
||||
if (dataComponent == null) {
|
||||
plugin.getTool().setStatusInfo("Create data type failed! No data at " + address);
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType parentDataType = dataComponent.getParent().getBaseDataType();
|
||||
|
||||
if (!(parentDataType instanceof Structure)) {
|
||||
plugin.getTool().setStatusInfo("Cannot set data type here.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return dataComponent;
|
||||
}
|
||||
|
||||
private int getSizeForSelection(Program program, ProgramSelection selection) {
|
||||
|
||||
PluginTool tool = plugin.getTool();
|
||||
|
||||
AddressRange range = selection.getFirstRange();
|
||||
Address address = selection.getMinAddress();
|
||||
Data data = program.getListing().getDataAt(address);
|
||||
if (data == null) {
|
||||
tool.setStatusInfo("Cannot set data type! No data at " + address);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int) range.getLength();
|
||||
}
|
||||
|
||||
private DataType getDataType(ListingActionContext context, int maxElements,
|
||||
int defaultPointerSize) {
|
||||
private DataType getDataType(ListingActionContext context) {
|
||||
PluginTool tool = plugin.getTool();
|
||||
Data data = plugin.getDataUnit(context);
|
||||
int noSizeRestriction = -1;
|
||||
DataTypeSelectionDialog selectionDialog = new DataTypeSelectionDialog(tool,
|
||||
data.getProgram().getDataTypeManager(), maxElements, AllowedDataTypes.ALL);
|
||||
DataType currentDataType = data.getBaseDataType();
|
||||
selectionDialog.setInitialDataType(currentDataType);
|
||||
data.getProgram().getDataTypeManager(), noSizeRestriction, AllowedDataTypes.ALL);
|
||||
DataType initialType = data.getBaseDataType();
|
||||
selectionDialog.setInitialDataType(initialType);
|
||||
tool.showDialog(selectionDialog);
|
||||
return selectionDialog.getUserChosenDataType();
|
||||
}
|
||||
|
@ -185,47 +81,4 @@ public class ChooseDataTypeAction extends DockingAction {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getMaxSizeInStructure(Structure struct, int index) {
|
||||
int n = struct.getNumComponents();
|
||||
DataTypeComponent dtc = struct.getComponent(index++);
|
||||
int length = dtc.getLength();
|
||||
while (index < n) {
|
||||
dtc = struct.getComponent(index++);
|
||||
DataType dataType = dtc.getDataType();
|
||||
if (dataType != DataType.DEFAULT) {
|
||||
break;
|
||||
}
|
||||
length += dtc.getLength();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
private int getMaxSize(Program program, Address addr) {
|
||||
|
||||
// can't go past the end of a block to start with
|
||||
Address maxAddr = program.getMemory().getBlock(addr).getEnd();
|
||||
|
||||
// get the next non undefined element in memory
|
||||
Instruction instr = program.getListing().getInstructionAfter(addr);
|
||||
if (instr != null) {
|
||||
Address instrAddr = instr.getMinAddress();
|
||||
if (instrAddr.compareTo(maxAddr) < 0) {
|
||||
maxAddr = instrAddr.subtract(1);
|
||||
}
|
||||
}
|
||||
|
||||
Data data = DataUtilities.getNextNonUndefinedDataAfter(program, addr, maxAddr);
|
||||
if (data != null) {
|
||||
Address dataAddr = data.getMinAddress();
|
||||
if (dataAddr.compareTo(maxAddr) < 0) {
|
||||
maxAddr = dataAddr.subtract(1);
|
||||
}
|
||||
}
|
||||
|
||||
long length = maxAddr.subtract(addr) + 1;
|
||||
SystemUtilities.assertTrue(length > 0,
|
||||
"Subtraction an address from the max address in its block should never be negative");
|
||||
return length > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,31 +238,13 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
dtmService.addDataTypeManagerChangeListener(adapter);
|
||||
}
|
||||
|
||||
boolean isEditDataTypeAllowed(ListingActionContext context) {
|
||||
Data data = getDataUnit(context);
|
||||
if (data == null || dtmService == null) {
|
||||
return false;
|
||||
}
|
||||
if (dtmService.isEditable(data.getBaseDataType())) {
|
||||
return true;
|
||||
}
|
||||
Data pdata = data.getParent();
|
||||
if (pdata != null) {
|
||||
if (dtmService.isEditable(pdata.getBaseDataType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DataType getEditableDataTypeFromContext(ListingActionContext context) {
|
||||
ProgramSelection currentSelection = context.getSelection();
|
||||
Program currentProgram = context.getProgram();
|
||||
DataType editableDataType = null;
|
||||
ProgramSelection selection = context.getSelection();
|
||||
Program program = context.getProgram();
|
||||
Data data = null;
|
||||
if (currentSelection != null && !currentSelection.isEmpty()) {
|
||||
Listing listing = currentProgram.getListing();
|
||||
boolean isDataOnly = !listing.getInstructions(currentSelection, true).hasNext();
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
Listing listing = program.getListing();
|
||||
boolean isDataOnly = !listing.getInstructions(selection, true).hasNext();
|
||||
if (isDataOnly) {
|
||||
data = getDataUnit(context);
|
||||
}
|
||||
|
@ -270,30 +252,30 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
else {
|
||||
data = getDataUnit(context);
|
||||
}
|
||||
if (data != null) {
|
||||
if (dtmService != null) {
|
||||
|
||||
return getEditableDataType(data);
|
||||
}
|
||||
|
||||
private DataType getEditableDataType(Data data) {
|
||||
if (data == null || dtmService == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType baseDt = data.getBaseDataType();
|
||||
if (dtmService.isEditable(baseDt)) {
|
||||
editableDataType = baseDt;
|
||||
return baseDt;
|
||||
}
|
||||
else {
|
||||
|
||||
Data pdata = data.getParent();
|
||||
if (pdata != null) {
|
||||
baseDt = pdata.getBaseDataType();
|
||||
if (dtmService.isEditable(baseDt)) {
|
||||
editableDataType = baseDt;
|
||||
return baseDt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return editableDataType;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.services.DataService#createData(ghidra.program.model.data.DataType,
|
||||
* ghidra.app.context.ListingActionContext, boolean)
|
||||
*/
|
||||
@Override
|
||||
public boolean createData(DataType dt, ListingActionContext context,
|
||||
boolean enableConflictHandling) {
|
||||
|
@ -307,8 +289,7 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
}
|
||||
|
||||
/*
|
||||
* This version uses the ProgramActionContext and does not depend on any
|
||||
* plugin's currentProgram
|
||||
* This version uses the ListingActionContext and does not depend on any plugin's currentProgram
|
||||
*/
|
||||
boolean doCreateData(ListingActionContext context, DataType dt) {
|
||||
ProgramSelection selection = context.getSelection();
|
||||
|
@ -316,7 +297,7 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
Program program = context.getProgram();
|
||||
|
||||
dt = dt.clone(program.getDataTypeManager());
|
||||
boolean didCreateData = true;
|
||||
boolean didCreateData = false;
|
||||
if (selection != null && !selection.isEmpty()) {
|
||||
didCreateData = createDataForSelection(program, dt, selection);
|
||||
}
|
||||
|
@ -375,7 +356,7 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
Listing listing = program.getListing();
|
||||
Data data = listing.getDataAt(start);
|
||||
if (data == null) {
|
||||
tool.setStatusInfo("Invalid data location");
|
||||
tool.setStatusInfo("Invalid data location. Cannot create data at " + start + '.');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -393,10 +374,13 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
end = start.addNoWrap(newSize - 1);
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
tool.setStatusInfo("Invalid data location. Not enough space at " + start + " for " +
|
||||
newSize + " bytes.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (intstrutionExists(listing, dataType, start, end)) {
|
||||
tool.setStatusInfo("Invalid data location. Instruction exists at " + start + '.');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -415,7 +399,7 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
Data definedData =
|
||||
DataUtilities.getNextNonUndefinedDataAfter(program, start, blockMaxAddress);
|
||||
if (dataExists(program, dataType, definedData, start, end)) {
|
||||
return false;
|
||||
return false; // status updated in 'dataExists()' call
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -516,58 +500,6 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
return dataTypeInstance.getLength();
|
||||
}
|
||||
|
||||
boolean doCreateData(Program program, ProgramLocation loc, ProgramSelection sel, DataType dt) {
|
||||
return doCreateData(program, loc, sel, dt, true);
|
||||
}
|
||||
|
||||
boolean doCreateData(Program program, ProgramLocation loc, ProgramSelection sel, DataType dt,
|
||||
boolean convertPointers) {
|
||||
|
||||
// Handle selection case
|
||||
boolean rc = true;
|
||||
if (sel != null && !sel.isEmpty()) {
|
||||
BackgroundCommand cmd;
|
||||
Address start = sel.getMinAddress();
|
||||
InteriorSelection interSel = sel.getInteriorSelection();
|
||||
if (interSel != null) {
|
||||
int[] startPath = interSel.getFrom().getComponentPath();
|
||||
int length = (int) sel.getNumAddresses(); // interior selections can't be that big
|
||||
cmd = new CreateDataInStructureBackgroundCmd(start, startPath, length, dt,
|
||||
convertPointers);
|
||||
}
|
||||
else {
|
||||
cmd = new CreateDataBackgroundCmd(sel, dt, convertPointers);
|
||||
}
|
||||
if (sel.getNumAddresses() < DataPlugin.BACKGROUND_SELECTION_THRESHOLD) {
|
||||
rc = tool.execute(cmd, program);
|
||||
}
|
||||
else {
|
||||
getPluginTool().executeBackgroundCommand(cmd, program);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle single location case
|
||||
else if (loc != null) {
|
||||
|
||||
Address start = loc.getAddress();
|
||||
int[] startPath = loc.getComponentPath();
|
||||
Command cmd;
|
||||
if (startPath != null && startPath.length != 0) {
|
||||
cmd = new CreateDataInStructureCmd(start, startPath, dt, convertPointers);
|
||||
}
|
||||
else {
|
||||
if (!checkEnoughSpace(program, start, dt, convertPointers)) {
|
||||
return false;
|
||||
}
|
||||
cmd = new CreateDataCmd(start, dt, false, convertPointers);
|
||||
}
|
||||
rc = getPluginTool().execute(cmd, program);
|
||||
}
|
||||
|
||||
updateRecentlyUsed(dt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
PluginTool getPluginTool() {
|
||||
return tool;
|
||||
}
|
||||
|
@ -741,9 +673,6 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.framework.plugintool.Plugin#dispose()
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
favoritesUpdateManager.dispose();
|
||||
|
@ -756,10 +685,6 @@ public class DataPlugin extends Plugin implements DataService {
|
|||
createStructureAction.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ghidra.app.plugin.ProgramPlugin#locationChanged(ghidra.program.util.ProgramLocation)
|
||||
* @see ghidra.app.plugin.ProgramPlugin#selectionChanged(ghidra.program.util.ProgramSelection)
|
||||
*/
|
||||
Data getDataUnit(ListingActionContext context) {
|
||||
ProgramLocation location = context.getLocation();
|
||||
ProgramSelection selection = context.getSelection();
|
||||
|
|
|
@ -69,7 +69,7 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
|||
|
||||
// data type info
|
||||
dataTypeEditor =
|
||||
new DataTypeSelectionEditor(plugin.getTool(), Integer.MAX_VALUE, AllowedDataTypes.ALL);
|
||||
new DataTypeSelectionEditor(plugin.getTool(), AllowedDataTypes.ALL);
|
||||
panel.add(new GLabel("Data type:"));
|
||||
panel.add(dataTypeEditor.getEditorComponent());
|
||||
|
||||
|
|
|
@ -374,6 +374,7 @@ public class FunctionPlugin extends Plugin implements DataService {
|
|||
* Get an iterator over all functions overlapping the current selection.
|
||||
* If there is no selection any functions overlapping the current location.
|
||||
*
|
||||
* @param context the context
|
||||
* @return Iterator over functions
|
||||
*/
|
||||
public Iterator<Function> getFunctions(ListingActionContext context) {
|
||||
|
@ -470,11 +471,10 @@ public class FunctionPlugin extends Plugin implements DataService {
|
|||
* Lay down the specified dataType on a function return, parameter or local variable
|
||||
* based upon the programActionContext. Pointer conversion will be handled
|
||||
* by merging the existing dataType with the specified dataType.
|
||||
* @param dataType The DataType to create.
|
||||
* @param dt The DataType to create.
|
||||
* @param programActionContext action context
|
||||
* @param promptForConflictRemoval if true and specified dataType results in a storage conflict,
|
||||
* @param enableConflictHandling if true and specified dataType results in a storage conflict,
|
||||
* user may be prompted for removal of conflicting variables (not applicable for return type)
|
||||
* @return True if the DataType could be created at the given location.
|
||||
*/
|
||||
@Override
|
||||
public boolean createData(DataType dt, ListingActionContext programActionContext,
|
||||
|
@ -483,11 +483,12 @@ public class FunctionPlugin extends Plugin implements DataService {
|
|||
}
|
||||
|
||||
/**
|
||||
* This method is the same as {@link #createData(DataType, ProgramLocation)}, except that this
|
||||
* method will use the given value of <tt>convertPointers</tt> to determine if the new
|
||||
* DataType should be made into a pointer if the existing DataType is a pointer.
|
||||
* @param dataType The DataType to create.
|
||||
* @param location The location at which to create the DataType.
|
||||
* This method is the same as {@link #createData(DataType, ListingActionContext, boolean)},
|
||||
* except that this method will use the given value of <tt>convertPointers</tt> to determine
|
||||
* if the new DataType should be made into a pointer if the existing DataType is a pointer.
|
||||
*
|
||||
* @param dataType the DataType to create
|
||||
* @param context the context containing the location at which to create the DataType
|
||||
* @param convertPointers True signals to convert the given DataType to a pointer if there is
|
||||
* an existing pointer at the specified location.
|
||||
* @param promptForConflictRemoval if true and specified dataType results in a storage conflict,
|
||||
|
@ -609,23 +610,12 @@ public class FunctionPlugin extends Plugin implements DataService {
|
|||
return null;
|
||||
}
|
||||
|
||||
// private boolean checkStackVarToFit(Function fun, StackVariable var, DataType dt) {
|
||||
// if (var.getDataType() instanceof Pointer) {
|
||||
// return true;
|
||||
// }
|
||||
// int startOffset = var.getLength();
|
||||
// if (startOffset < 0) startOffset = 1;
|
||||
// int size = getMaxStackVariableSize(fun, var);
|
||||
// if (size < 0) return true;
|
||||
// return size >= dt.getLength();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the maximum data type length permitted
|
||||
* for the specified local variable. A -1 returned
|
||||
* value indicates no limit imposed.
|
||||
* @param fun
|
||||
* @param var
|
||||
* Return the maximum data type length permitted for the specified local variable. A -1
|
||||
* returned value indicates no limit imposed.
|
||||
*
|
||||
* @param fun the function
|
||||
* @param var the variable
|
||||
* @return maximum data type length permitted for var
|
||||
*/
|
||||
int getMaxStackVariableSize(Function fun, Variable var) {
|
||||
|
|
|
@ -61,7 +61,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel
|
|||
}
|
||||
|
||||
private void init() {
|
||||
editor = new DataTypeSelectionEditor(service, -1, DataTypeParser.AllowedDataTypes.ALL);
|
||||
editor = new DataTypeSelectionEditor(service, DataTypeParser.AllowedDataTypes.ALL);
|
||||
editor.setTabCommitsEdit(true);
|
||||
editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses
|
||||
|
||||
|
@ -88,13 +88,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel
|
|||
}
|
||||
};
|
||||
|
||||
dataTypeChooserButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dataTypeChooserButton.addActionListener(e -> SwingUtilities.invokeLater(() -> {
|
||||
DataType dataType = service.getDataType((String) null);
|
||||
if (dataType != null) {
|
||||
editor.setCellEditorValue(dataType);
|
||||
|
@ -103,10 +97,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel
|
|||
else {
|
||||
editor.cancelCellEditing();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
FocusAdapter focusListener = new FocusAdapter() {
|
||||
@Override
|
||||
|
|
|
@ -20,13 +20,9 @@ import ghidra.framework.plugintool.ServiceInfo;
|
|||
import ghidra.program.model.data.DataType;
|
||||
|
||||
/**
|
||||
* Data Creation service.
|
||||
*
|
||||
* NOTE: This version is dependant on the currentProgram of the implementing
|
||||
* plugin class. If you want a version that is not dependant on it, please use
|
||||
* DataCreationService
|
||||
* Service for creating data
|
||||
*/
|
||||
@ServiceInfo(description = "Data creation service.")
|
||||
@ServiceInfo(description = "Data creation service")
|
||||
public interface DataService {
|
||||
|
||||
/**
|
||||
|
@ -42,13 +38,12 @@ public interface DataService {
|
|||
/**
|
||||
* Apply the given data type at a location.
|
||||
*
|
||||
* @param dt
|
||||
* dataType to create at the location
|
||||
* @param context
|
||||
* the context containing program, location, and selection information
|
||||
* @param enableConflictHandling
|
||||
* if true, the service may prompt the user to resolve data conflicts
|
||||
* @param dt data type to create at the location
|
||||
* @param context the context containing program, location, and selection information
|
||||
* @param enableConflictHandling if true, the service may prompt the user to resolve data
|
||||
* conflicts
|
||||
* @return true if the data could be created at the current location
|
||||
*/
|
||||
public boolean createData(DataType dt, ListingActionContext context, boolean enableConflictHandling);
|
||||
public boolean createData(DataType dt, ListingActionContext context,
|
||||
boolean enableConflictHandling);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class DataTypeSelectionDialog extends DialogComponentProvider {
|
|||
private void buildEditor() {
|
||||
removeWorkPanel();
|
||||
|
||||
editor = new DataTypeSelectionEditor(pluginTool, maxSize, allowedTypes);
|
||||
editor = new DataTypeSelectionEditor(pluginTool, allowedTypes);
|
||||
editor.setPreferredDataTypeManager(dtm);
|
||||
editor.setConsumeEnterKeyPress(false); // we want to handle Enter key presses
|
||||
editor.addCellEditorListener(new CellEditorListener() {
|
||||
|
@ -171,6 +171,7 @@ public class DataTypeSelectionDialog extends DialogComponentProvider {
|
|||
* This method is useful for widgets that have embedded editors that launch this dialog. For
|
||||
* these editors, like tables, it is nice to be able to tab through various editors. This
|
||||
* method allows these editors to keep this functionality, even though a new dialog was shown.
|
||||
* @param doesCommit true commits edits on Tab press
|
||||
*/
|
||||
public void setTabCommitsEdit(boolean doesCommit) {
|
||||
editor.setTabCommitsEdit(doesCommit);
|
||||
|
|
|
@ -59,7 +59,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
private DropDownSelectionTextField<DataType> selectionField;
|
||||
private JButton browseButton;
|
||||
private DataTypeManagerService dataTypeManagerService;
|
||||
private int maxSize = -1;
|
||||
private DataTypeManager dataTypeManager;
|
||||
private DataTypeParser.AllowedDataTypes allowedDataTypes;
|
||||
|
||||
|
@ -69,12 +68,12 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
// optional path to initially select in the data type chooser tree
|
||||
private TreePath initiallySelectedTreePath;
|
||||
|
||||
public DataTypeSelectionEditor(ServiceProvider serviceProvider, int maxSize,
|
||||
public DataTypeSelectionEditor(ServiceProvider serviceProvider,
|
||||
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
||||
this(serviceProvider.getService(DataTypeManagerService.class), maxSize, allowedDataTypes);
|
||||
this(serviceProvider.getService(DataTypeManagerService.class), allowedDataTypes);
|
||||
}
|
||||
|
||||
public DataTypeSelectionEditor(DataTypeManagerService service, int maxSize,
|
||||
public DataTypeSelectionEditor(DataTypeManagerService service,
|
||||
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
||||
|
||||
if (service == null) {
|
||||
|
@ -82,7 +81,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
}
|
||||
|
||||
this.dataTypeManagerService = service;
|
||||
this.maxSize = maxSize;
|
||||
this.allowedDataTypes = allowedDataTypes;
|
||||
|
||||
init();
|
||||
|
@ -102,7 +100,10 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets whether this editor should consumer Enter key presses
|
||||
* @see DropDownSelectionTextField#setConsumeEnterKeyPress(boolean)
|
||||
*
|
||||
* @param consume true to consume
|
||||
*/
|
||||
public void setConsumeEnterKeyPress(boolean consume) {
|
||||
selectionField.setConsumeEnterKeyPress(consume);
|
||||
|
@ -276,6 +277,7 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
/**
|
||||
* Returns the direction of the user triggered navigation; null if the user did not trigger
|
||||
* navigation out of this component.
|
||||
* @return the direction
|
||||
*/
|
||||
public NavigationDirection getNavigationDirection() {
|
||||
return navigationDirection;
|
||||
|
@ -362,10 +364,8 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
|||
catch (CancelledException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newDataType != null) {
|
||||
if (maxSize >= 0 && newDataType.getLength() > newDataType.getLength()) {
|
||||
throw new InvalidDataTypeException("data-type larger than " + maxSize + " bytes");
|
||||
}
|
||||
selectionField.setSelectedValue(newDataType);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -95,8 +95,8 @@ public class DataTypeParser {
|
|||
* the source data type manager, this means that all data type managers will be used when
|
||||
* resolving data types.
|
||||
*
|
||||
* @param dataTypeManagerService
|
||||
* @param allowedTypes
|
||||
* @param dataTypeManagerService data-type manager tool service, or null
|
||||
* @param allowedTypes constrains which data-types may be parsed
|
||||
*/
|
||||
public DataTypeParser(DataTypeQueryService dataTypeManagerService,
|
||||
AllowedDataTypes allowedTypes) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package ghidra.app.plugin.core.data;
|
||||
|
||||
import static org.hamcrest.core.StringContains.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.swing.*;
|
||||
|
@ -22,9 +23,9 @@ import javax.swing.*;
|
|||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.*;
|
||||
|
||||
import docking.DialogComponentProvider;
|
||||
import docking.DockingDialog;
|
||||
import docking.*;
|
||||
import docking.action.DockingActionIf;
|
||||
import generic.test.TestUtils;
|
||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||
import ghidra.app.plugin.core.codebrowser.*;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
|
@ -50,7 +51,6 @@ import ghidra.test.TestEnv;
|
|||
|
||||
public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
private static final String PROGRAM_FILENAME = "WallaceSrc";
|
||||
private static final int TASK_TIMEOUT = 2000;
|
||||
private static final String CYCLE_BYTE_WORD_DWORD_QWORD = "Cycle: byte,word,dword,qword";
|
||||
|
||||
private TestEnv env;
|
||||
|
@ -63,6 +63,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
private DataTypeArchiveGTree tree;
|
||||
private ArchiveRootNode archiveRootNode;
|
||||
private ArchiveNode programNode;
|
||||
private CodeViewerProvider codeViewerProvider;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
@ -94,6 +95,9 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
assertNotNull("Did not successfully wait for the program node to load", programNode);
|
||||
|
||||
tool.showComponentProvider(provider, true);
|
||||
|
||||
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
||||
codeViewerProvider = codeBrowserPlugin.getProvider();
|
||||
}
|
||||
|
||||
private ProgramDB buildWallaceSrcProgram() throws Exception {
|
||||
|
@ -121,24 +125,19 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
executeOnSwingWithoutBlocking(() -> {
|
||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||
pm.closeProgram();
|
||||
|
||||
});
|
||||
|
||||
// this handles the save changes dialog and potential analysis dialogs
|
||||
closeAllWindowsAndFrames();
|
||||
closeAllWindows();
|
||||
|
||||
env.release(program);
|
||||
env.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseDataTypeOnDefaultDts() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
showDataTypeChooser();
|
||||
|
||||
chooseInDialog("_person");
|
||||
|
||||
|
@ -152,12 +151,9 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testChooseDataTypeOnUndefinedDts() throws Exception {
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
showDataTypeChooser();
|
||||
|
||||
chooseInDialog("_person");
|
||||
|
||||
|
@ -170,80 +166,67 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
@Test
|
||||
public void testChooseDataTypeOnDefinedDts() throws Exception {
|
||||
|
||||
//
|
||||
// Test that apply data on an existing type will offer to clear that type
|
||||
//
|
||||
|
||||
createData("004027d1", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
showDataTypeChooser();
|
||||
|
||||
DialogComponentProvider dialog =
|
||||
chooseInDialog("_person", "_person doesn't fit within 1 bytes, need 41 bytes");
|
||||
chooseInDialog("_person");
|
||||
|
||||
pressConflictingDataDialog("Yes");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
||||
|
||||
pressButtonByText(dialog, "Cancel");
|
||||
waitForSwing();
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
assertEquals(dataType, data.getDataType());
|
||||
assertEquals(addr("004027f8"), data.getMaxAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseDataTypeOnDefinedAndUndefinedDts() throws Exception {
|
||||
createData("004027d1", new ByteDataType());
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
|
||||
DialogComponentProvider dialog =
|
||||
chooseInDialog("_person", "_person doesn't fit within 1 bytes, need 41 bytes");
|
||||
showDataTypeChooser();
|
||||
chooseInDialog("_person");
|
||||
pressConflictingDataDialog("No");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
||||
|
||||
pressButtonByText(dialog, "Cancel");
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChooseDataTypeWhereDoesNotFit() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027e0");
|
||||
waitForSwing();
|
||||
goTo("004027e0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
showDataTypeChooser();
|
||||
|
||||
DialogComponentProvider dialog =
|
||||
chooseInDialog("_person", "_person doesn't fit within 32 bytes, need 41 bytes");
|
||||
showDataTypeChooser();
|
||||
chooseInDialog("_person");
|
||||
|
||||
assertToolStatus("Not enough room in memory block containing address");
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
||||
|
||||
pressButtonByText(dialog, "Cancel");
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateArrayOnDefaultDts() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
JTextField tf = findComponent(dialog, JTextField.class);
|
||||
triggerText(tf, "48");
|
||||
waitForSwing();
|
||||
|
@ -261,8 +244,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testCreateArrayOnUndefinedDts() throws Exception {
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -270,8 +252,8 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
|
||||
JTextField tf = findComponent(dialog, JTextField.class);
|
||||
triggerText(tf, "48");
|
||||
|
||||
|
@ -288,8 +270,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testCreateArrayFailureOnDefinedDts() throws Exception {
|
||||
createData("004027d4", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -297,8 +278,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
|
||||
checkStatus((DockingDialog) dialog, "Entering more than 4 will overwrite existing data");
|
||||
|
||||
|
@ -326,8 +306,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
createCode("004027d4", 1);
|
||||
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -335,8 +314,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
|
||||
checkStatus((DockingDialog) dialog, " ");
|
||||
|
||||
|
@ -364,8 +342,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
createCode("004027d4", 1);
|
||||
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -373,8 +350,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
|
||||
checkStatus((DockingDialog) dialog, " ");
|
||||
|
||||
|
@ -396,8 +372,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testCreateArrayOverwriteOnDefinedDts() throws Exception {
|
||||
createData("004027d4", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -405,8 +380,8 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
||||
assertNotNull(dialog);
|
||||
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||
|
||||
JTextField tf = findComponent(dialog, JTextField.class);
|
||||
triggerText(tf, "48");
|
||||
waitForSwing();
|
||||
|
@ -417,8 +392,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
pressButtonByText(dialog, "OK");
|
||||
waitForSwing();
|
||||
|
||||
dialog = waitForJDialog(tool.getToolFrame(), "Overwrite Existing Data?", 2000);
|
||||
assertNotNull(dialog);
|
||||
dialog = waitForJDialog("Overwrite Existing Data?");
|
||||
|
||||
pressButtonByText(dialog, "Yes");
|
||||
waitForSwing();
|
||||
|
@ -434,8 +408,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
plugin.setRecentlyUsed(dataType);
|
||||
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -455,8 +428,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
plugin.setRecentlyUsed(dataType);
|
||||
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
|
@ -476,20 +448,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
plugin.setRecentlyUsed(dataType);
|
||||
|
||||
createData("004027d1", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "Yes");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("Yes");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(dataType, data.getDataType());
|
||||
|
@ -503,20 +467,13 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
plugin.setRecentlyUsed(dataType);
|
||||
|
||||
createData("004027d1", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "No");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("No");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
|
@ -525,21 +482,18 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
@Test
|
||||
public void testFavoriteOnDefaultDts() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite
|
||||
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||
waitForSwing();
|
||||
|
||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite.
|
||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
||||
waitForSwing();
|
||||
|
||||
// Choose favorite.
|
||||
// Choose favorite
|
||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||
assertNotNull(favoriteAction);
|
||||
performAction(favoriteAction, codeViewerProvider, true);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
|
@ -550,21 +504,18 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testFavoriteOnUndefinedDts() throws Exception {
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite.
|
||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
||||
// Set _person as a favorite
|
||||
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||
waitForSwing();
|
||||
|
||||
// Choose favorite.
|
||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||
assertNotNull(favoriteAction);
|
||||
performAction(favoriteAction, codeViewerProvider, true);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
|
@ -575,28 +526,20 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testFavoriteOnDefinedDtsAnswerYes() throws Exception {
|
||||
createData("004027d1", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite
|
||||
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||
waitForSwing();
|
||||
|
||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite.
|
||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
||||
waitForSwing();
|
||||
|
||||
// Choose favorite.
|
||||
// Choose favorite
|
||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||
assertNotNull(favoriteAction);
|
||||
performAction(favoriteAction, codeViewerProvider, false);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "Yes");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("Yes");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(dataType, data.getDataType());
|
||||
|
@ -606,28 +549,20 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testFavoriteOnDefinedDtsAnswerNo() throws Exception {
|
||||
createData("004027d1", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
// Set _person as a favorite.
|
||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
||||
// Set _person as a favorite
|
||||
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||
waitForSwing();
|
||||
|
||||
// Choose favorite.
|
||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||
assertNotNull(favoriteAction);
|
||||
performAction(favoriteAction, codeViewerProvider, false);
|
||||
|
||||
waitForSwing();
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "No");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("No");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
|
@ -636,12 +571,9 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
@Test
|
||||
public void testCycleOnDefaultDts() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
assertNotNull(chooseDataTypeAction);
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
showDataTypeChooser();
|
||||
|
||||
chooseInDialog("_person");
|
||||
|
||||
|
@ -655,8 +587,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testCycleOnUndefinedDts() throws Exception {
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
|
@ -689,8 +620,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testCycleOnDefinedDts() throws Exception {
|
||||
createData("004027d3", new ByteDataType());
|
||||
positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
|
@ -722,13 +652,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
@Test
|
||||
public void testDragNDropOnDefaultDts() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
||||
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(dataType, data.getDataType());
|
||||
|
@ -738,13 +667,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testDragNDropOnUndefinedDts() throws Exception {
|
||||
createData("004027d2", new Undefined4DataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
||||
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(dataType, data.getDataType());
|
||||
|
@ -754,19 +682,14 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testDragNDropYesOnDefinedDts() throws Exception {
|
||||
createData("004027d3", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
||||
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "Yes");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("Yes");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(dataType, data.getDataType());
|
||||
|
@ -776,19 +699,14 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
@Test
|
||||
public void testDragNDropNoOnDefinedDts() throws Exception {
|
||||
createData("004027d3", new ByteDataType());
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
||||
waitForSwing();
|
||||
goTo("004027d0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
||||
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||
|
||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
||||
assertNotNull(dialog);
|
||||
|
||||
pressButtonByText(dialog, "No");
|
||||
waitForSwing();
|
||||
pressConflictingDataDialog("No");
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
|
@ -797,13 +715,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
|
||||
@Test
|
||||
public void testDragNDropWhereDoesNotFit() throws Exception {
|
||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027e0");
|
||||
waitForSwing();
|
||||
goTo("004027e0");
|
||||
|
||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||
|
||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
||||
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||
|
||||
Data data = program.getListing().getDataAt(addr("004027e0"));
|
||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||
|
@ -814,24 +731,36 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
// Private Helper Methods
|
||||
//==================================================================================================
|
||||
|
||||
private DialogComponentProvider chooseInDialog(String typeName) {
|
||||
private void assertToolStatus(String expectedMessage) {
|
||||
|
||||
waitForSwing();
|
||||
PluginTool pluginTool = plugin.getTool();
|
||||
DockingWindowManager windowManager = pluginTool.getWindowManager();
|
||||
Object rootNode = TestUtils.invokeInstanceMethod("getRootNode", windowManager);
|
||||
StatusBar statusBar = (StatusBar) TestUtils.getInstanceField("statusBar", rootNode);
|
||||
String actualMessage = runSwing(() -> statusBar.getStatusText());
|
||||
assertThat("The tool's status text was not set", actualMessage,
|
||||
containsString(expectedMessage));
|
||||
}
|
||||
|
||||
private void showDataTypeChooser() {
|
||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||
}
|
||||
|
||||
private void pressConflictingDataDialog(String button) {
|
||||
DialogComponentProvider dialog = waitForDialogComponent("Data Conflict");
|
||||
pressButtonByText(dialog, button);
|
||||
waitForTasks();
|
||||
}
|
||||
|
||||
private DialogComponentProvider chooseInDialog(String typeName) {
|
||||
return chooseInDialog(typeName, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the Data Type Chooser dialog to appear. Then, enters the given text to
|
||||
* select that type. Finally, OK is pressed. The dialog may or may not go away,
|
||||
* depending upon the state of the dialog.
|
||||
*
|
||||
* @param typeName the name of the dt
|
||||
* @param errorStatus the expected status after pressing OK
|
||||
*/
|
||||
private DialogComponentProvider chooseInDialog(String typeName, String errorStatus) {
|
||||
|
||||
DataTypeSelectionDialog dialog = waitForDialogComponent(DataTypeSelectionDialog.class);
|
||||
|
||||
assertNotNull(dialog);
|
||||
JTextField tf = findComponent(dialog, JTextField.class);
|
||||
triggerText(tf, "_person");
|
||||
waitForSwing();
|
||||
|
@ -862,7 +791,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
}
|
||||
|
||||
private void dragNDropDataTypeToCurrentBrowserLocation(
|
||||
final CodeViewerProvider codeViewerProvider, final DataType dataType) {
|
||||
final DataType dataType) {
|
||||
executeOnSwingWithoutBlocking(() -> {
|
||||
// Simulate the drag-n-drop of the data type onto the location.
|
||||
ProgramLocation programLocation = codeViewerProvider.getLocation();
|
||||
|
@ -880,12 +809,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
}
|
||||
|
||||
private void doAction(Plugin pluginForAction, String name, boolean waitForCompletion) {
|
||||
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
||||
assertNotNull(codeBrowserPlugin);
|
||||
CodeViewerProvider connectedProvider =
|
||||
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowserPlugin);
|
||||
assertNotNull(connectedProvider);
|
||||
CodeViewerActionContext codeViewerContext = new CodeViewerActionContext(connectedProvider);
|
||||
CodeViewerActionContext codeViewerContext = new CodeViewerActionContext(codeViewerProvider);
|
||||
|
||||
DockingActionIf action = getAction(pluginForAction, name);
|
||||
assertNotNull("Action was not found: " + name, action);
|
||||
|
@ -894,28 +818,26 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
}
|
||||
|
||||
try {
|
||||
performAction(action, connectedProvider, waitForCompletion);
|
||||
performAction(action, codeViewerProvider, waitForCompletion);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
Assert.fail("Action '" + name + "' failed: " + t.toString());
|
||||
failWithException("Action '" + name + "' failed: ", t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private CodeViewerProvider positionListingCursorAtAddress(String addressString) {
|
||||
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
||||
assertNotNull(codeBrowserPlugin);
|
||||
private void goTo(String addressString) {
|
||||
CodeBrowserPlugin codeBrowser = env.getPlugin(CodeBrowserPlugin.class);
|
||||
Address address = program.getAddressFactory().getAddress(addressString);
|
||||
codeBrowserPlugin.goToField(address, "Address", 0, 0);
|
||||
assertEquals(addressString, codeBrowserPlugin.getCurrentAddress().toString());
|
||||
codeBrowser.goToField(address, "Address", 0, 0);
|
||||
assertEquals(addressString, codeBrowser.getCurrentAddress().toString());
|
||||
CodeViewerProvider connectedProvider =
|
||||
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowserPlugin);
|
||||
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowser);
|
||||
assertNotNull(connectedProvider);
|
||||
ListingPanel listingPanel =
|
||||
(ListingPanel) getInstanceField("listingPanel", connectedProvider);
|
||||
assertNotNull(listingPanel);
|
||||
return connectedProvider;
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
private void createData(String addressString, DataType dataType) throws Exception {
|
||||
|
@ -928,7 +850,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
finally {
|
||||
program.endTransaction(transactionID, success);
|
||||
}
|
||||
waitForProgram();
|
||||
waitForProgram(program);
|
||||
}
|
||||
|
||||
private void createCode(String addressString, int len) throws Exception {
|
||||
|
@ -945,7 +867,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
finally {
|
||||
program.endTransaction(transactionID, success);
|
||||
}
|
||||
waitForProgram();
|
||||
waitForProgram(program);
|
||||
}
|
||||
|
||||
private Address addr(String addressString) {
|
||||
|
@ -955,10 +877,4 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
|||
private void waitForTree() {
|
||||
waitForTree(tree);
|
||||
}
|
||||
|
||||
private void waitForProgram() throws Exception {
|
||||
program.flushEvents();
|
||||
waitForTasks();
|
||||
waitForSwing();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ import generic.test.AbstractGTest;
|
|||
import generic.util.WindowUtilities;
|
||||
import generic.util.image.ImageUtils;
|
||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||
import ghidra.app.plugin.core.datamgr.archive.*;
|
||||
import ghidra.app.plugin.core.datamgr.archive.Archive;
|
||||
import ghidra.app.plugin.core.datamgr.archive.DataTypeManagerHandler;
|
||||
import ghidra.app.plugin.core.datamgr.tree.DataTypeArchiveGTree;
|
||||
import ghidra.app.plugin.core.datamgr.tree.DataTypeNode;
|
||||
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
||||
|
@ -1175,7 +1176,7 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
|||
|
||||
JPanel editorPanel = new JPanel(new BorderLayout());
|
||||
DataTypeSelectionEditor editor =
|
||||
new DataTypeSelectionEditor(tool, -1, AllowedDataTypes.ALL);
|
||||
new DataTypeSelectionEditor(tool, AllowedDataTypes.ALL);
|
||||
editor.setPreferredDataTypeManager(program.getDataTypeManager());
|
||||
|
||||
editorPanel.add(panelUpdateField, BorderLayout.SOUTH);
|
||||
|
|
|
@ -45,14 +45,6 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
|||
private Listing listing;
|
||||
private ProgramBuilder builder;
|
||||
|
||||
/**
|
||||
* Constructor for CreateDataCmdTest.
|
||||
* @param arg0
|
||||
*/
|
||||
public CreateDataCmdTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
program = buildProgram();
|
||||
|
@ -637,7 +629,8 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
|||
cmd.applyTo(program);
|
||||
|
||||
// Add external reference from pointer
|
||||
program.getReferenceManager().addExternalReference(addr, "OtherFile", "ExtLabel", null,
|
||||
program.getReferenceManager()
|
||||
.addExternalReference(addr, "OtherFile", "ExtLabel", null,
|
||||
SourceType.USER_DEFINED, 0, RefType.DATA);
|
||||
|
||||
// Undefined* becomes Byte*
|
||||
|
@ -724,7 +717,8 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
|||
assertEquals(10, dt.getLength());
|
||||
|
||||
// Byte[] becomes Byte
|
||||
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
|
||||
CreateDataCmd cmd =
|
||||
new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
|
||||
cmd.applyTo(program);
|
||||
|
||||
d = listing.getDataAt(addr);
|
||||
|
@ -792,7 +786,8 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
|||
assertEquals(10, dt.getLength());
|
||||
|
||||
// struct becomes Byte
|
||||
CreateDataCmd cmd = new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
|
||||
CreateDataCmd cmd =
|
||||
new CreateDataCmd(addr, new ByteDataType(), false, ClearDataMode.CLEAR_SINGLE_DATA);
|
||||
cmd.applyTo(program);
|
||||
|
||||
d = listing.getDataAt(addr);
|
||||
|
|
|
@ -557,8 +557,7 @@ class DetachedWindowNode extends WindowNode {
|
|||
*/
|
||||
public void setStatusText(String text) {
|
||||
if (statusBar != null) {
|
||||
boolean isActive = window == null ? false : window.isActive();
|
||||
statusBar.setStatusText(text, isActive);
|
||||
statusBar.setStatusText(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -576,7 +576,7 @@ class RootNode extends WindowNode {
|
|||
return;
|
||||
}
|
||||
|
||||
statusBar.setStatusText(text, getMainWindow().isActive());
|
||||
statusBar.setStatusText(text);
|
||||
|
||||
Iterator<DetachedWindowNode> iter = detachedWindows.iterator();
|
||||
while (iter.hasNext()) {
|
||||
|
|
|
@ -24,6 +24,7 @@ import javax.swing.*;
|
|||
import javax.swing.Timer;
|
||||
import javax.swing.border.Border;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jdesktop.animation.timing.Animator;
|
||||
|
||||
import docking.util.AnimationUtils;
|
||||
|
@ -153,14 +154,40 @@ public class StatusBar extends JPanel {
|
|||
statusAreaPanel.remove(c.getParent());
|
||||
}
|
||||
|
||||
public void setStatusText(String text, boolean isActiveWindow) {
|
||||
SystemUtilities.runIfSwingOrPostSwingLater(() -> doSetStatusText(text, isActiveWindow));
|
||||
/**
|
||||
* Returns the current text in this status bar
|
||||
* @return the text
|
||||
*/
|
||||
public String getStatusText() {
|
||||
return statusLabel.getText();
|
||||
}
|
||||
|
||||
private void doSetStatusText(String text, boolean isActiveWindow) {
|
||||
/**
|
||||
* Deprecated. Call {@link #setStatusText(String)} instead.
|
||||
*
|
||||
* @param text the text
|
||||
* @param isActiveWindow this parameter is ignored
|
||||
* @deprecated Call {@link #setStatusText(String)} instead. Remove after 9.3
|
||||
*/
|
||||
@Deprecated
|
||||
public void setStatusText(String text, boolean isActiveWindow) {
|
||||
setStatusText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status text
|
||||
* @param text the text
|
||||
*/
|
||||
public void setStatusText(String text) {
|
||||
// Run this later in case we are in the midst of a Java focus transition, such as when a
|
||||
// dialog is closing. If we don't let the focus transition finish, then we will not
|
||||
// correctly locate the active window.
|
||||
Swing.runLater(() -> doSetStatusText(text));
|
||||
}
|
||||
|
||||
private void doSetStatusText(String text) {
|
||||
if (text == null) {
|
||||
// not sure what do do here, do nothing for now so that the previous message
|
||||
// stays around
|
||||
// do nothing for now so that the previous message stays around
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -171,11 +198,12 @@ public class StatusBar extends JPanel {
|
|||
statusLabel.setToolTipText(getToolTipText());
|
||||
statusLabel.setForeground(Color.BLACK);
|
||||
|
||||
if (!isActiveWindow) {
|
||||
if (StringUtils.isBlank(updatedText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updatedText.trim().isEmpty()) {
|
||||
Window window = WindowUtilities.windowForComponent(statusLabel);
|
||||
if (!window.isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -496,6 +496,13 @@ public class AnimationUtils {
|
|||
}
|
||||
|
||||
Rectangle startBounds = component.getBounds();
|
||||
Container parent = component.getParent();
|
||||
if (parent == null) {
|
||||
// the given component is a Window; make it be the root
|
||||
startBounds.x = 0;
|
||||
startBounds.y = 0;
|
||||
}
|
||||
|
||||
Point relativeStartCenter =
|
||||
new Point((int) startBounds.getCenterX(), (int) startBounds.getCenterY());
|
||||
return SwingUtilities.convertPoint(component.getParent(), relativeStartCenter,
|
||||
|
@ -556,11 +563,20 @@ public class AnimationUtils {
|
|||
int scaledWidth = (int) (defaultBounds.width * percentComplete);
|
||||
int scaledHeight = (int) (defaultBounds.height * percentComplete);
|
||||
|
||||
// gains opacity as it gets closer to the end; capped at the given percentage
|
||||
float opacity = (float) Math.min(.65, percentComplete);
|
||||
Composite originalComposite = g2d.getComposite();
|
||||
AlphaComposite alphaComposite = AlphaComposite.getInstance(
|
||||
AlphaComposite.SrcOver.getRule(), opacity);
|
||||
g2d.setComposite(alphaComposite);
|
||||
|
||||
//
|
||||
// Calculate the position of the image. At 100% we want to be in the center of
|
||||
// the display; at 0% we want to be at our default location
|
||||
//
|
||||
g2d.drawImage(image, (int) currentX, (int) currentY, scaledWidth, scaledHeight, null);
|
||||
|
||||
g2d.setComposite(originalComposite);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package docking;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
@ -38,15 +38,6 @@ public class StatusBarTest extends AbstractDockingTest {
|
|||
private StatusBar statusBar;
|
||||
private JFrame testFrame;
|
||||
|
||||
/**
|
||||
* Constructor to run the test passed as a parameter.
|
||||
*
|
||||
* @param testName The name of the test to run
|
||||
*/
|
||||
public StatusBarTest() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
|
@ -113,59 +104,37 @@ public class StatusBarTest extends AbstractDockingTest {
|
|||
final JLabel label2 = new GDLabel("Test Label 2");
|
||||
|
||||
// normal add/remove operations
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
statusBar.addStatusItem(label1, true, true);
|
||||
statusBar.addStatusItem(label2, true, true);
|
||||
}
|
||||
});
|
||||
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
statusBar.removeStatusItem(label1);
|
||||
statusBar.removeStatusItem(label2);
|
||||
}
|
||||
});
|
||||
|
||||
// method call variations
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
statusBar.addStatusItem(label1, false, true);
|
||||
statusBar.addStatusItem(label2, true, false);
|
||||
}
|
||||
});
|
||||
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
statusBar.removeStatusItem(label1);
|
||||
statusBar.removeStatusItem(label2);
|
||||
}
|
||||
});
|
||||
|
||||
// repeat adding
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
statusBar.addStatusItem(label1, true, true);
|
||||
statusBar.addStatusItem(label1, true, true);
|
||||
}
|
||||
});
|
||||
|
||||
// removing non-existent elements
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
statusBar.removeStatusItem(label2);
|
||||
}
|
||||
});
|
||||
runSwing(() -> statusBar.removeStatusItem(label2));
|
||||
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runSwing(() -> {
|
||||
try {
|
||||
statusBar.removeStatusItem(new GLabel("Test Label 3"));
|
||||
|
||||
|
@ -174,17 +143,11 @@ public class StatusBarTest extends AbstractDockingTest {
|
|||
catch (NullPointerException npe) {
|
||||
// expected, caused by a null parent
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setStatusText(final String text) {
|
||||
runSwing(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
statusBar.setStatusText(text, true);
|
||||
}
|
||||
});
|
||||
waitForPostedSwingRunnables();
|
||||
runSwing(() -> statusBar.setStatusText(text));
|
||||
waitForSwing();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,8 @@ import ghidra.util.exception.InvalidInputException;
|
|||
|
||||
public final class DataUtilities {
|
||||
|
||||
//private final static Set<Character> VALID_DATA_TYPE_NAME_SET = SystemUtilities.makeSet(FileSystem.DASH_CHAR, '_',' ', '.');
|
||||
|
||||
private DataUtilities() {
|
||||
// utilities class
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,95 +87,58 @@ public final class DataUtilities {
|
|||
|
||||
/**
|
||||
* Create data where existing data may already exist.
|
||||
* @param program
|
||||
* @param program the program
|
||||
* @param addr data address (offcut data address only allowed if clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA)
|
||||
* @param newDataType new data-type being applied
|
||||
* @param newType new data-type being applied
|
||||
* @param length data length (used only for Dynamic newDataType which has canSpecifyLength()==true)
|
||||
* @param stackPointers see {@link #reconcileAppliedDataType(DataType, DataType, boolean)}
|
||||
* @param clearMode see CreateDataMode
|
||||
* @return new data created
|
||||
* @throws CodeUnitInsertionException if data creation failed
|
||||
*/
|
||||
public static Data createData(Program program, Address addr, DataType newDataType, int length,
|
||||
public static Data createData(Program program, Address addr, DataType newType, int length,
|
||||
boolean stackPointers, ClearDataMode clearMode) throws CodeUnitInsertionException {
|
||||
|
||||
Listing listing = program.getListing();
|
||||
ReferenceManager refMgr = program.getReferenceManager();
|
||||
|
||||
Data data = listing.getDataAt(addr);
|
||||
DataType existingDT = null;
|
||||
Data data = getData(addr, clearMode, listing);
|
||||
int existingLength = addr.getAddressSpace().getAddressableUnitSize();
|
||||
DataType existingType = data.getDataType();
|
||||
Reference extRef = null;
|
||||
int existingDataLen = addr.getAddressSpace().getAddressableUnitSize();
|
||||
if (data == null) {
|
||||
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
||||
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) {
|
||||
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
||||
data = listing.getDataContaining(addr);
|
||||
if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||
!Undefined.isUndefined(data.getDataType())) {
|
||||
data = null; // force error
|
||||
}
|
||||
}
|
||||
if (data == null) {
|
||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
existingDataLen = data.getLength();
|
||||
existingDT = data.getDataType();
|
||||
if (!isParentData(data, addr)) {
|
||||
|
||||
if (data.isDefined() && newDataType.isEquivalent(existingDT)) {
|
||||
existingLength = data.getLength();
|
||||
if (data.isDefined() && newType.isEquivalent(existingType)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
if (!stackPointers && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||
!Undefined.isUndefined(existingDT)) {
|
||||
!Undefined.isUndefined(existingType)) {
|
||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||
}
|
||||
|
||||
// Check for external reference on pointer
|
||||
if ((stackPointers || newDataType instanceof Pointer) &&
|
||||
existingDT instanceof Pointer) {
|
||||
// TODO: This can probably be eliminated
|
||||
Reference[] refs = refMgr.getReferencesFrom(addr);
|
||||
for (Reference ref : refs) {
|
||||
if (ref.getOperandIndex() == 0 && ref.isExternalReference()) {
|
||||
extRef = ref;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for external reference on pointer
|
||||
extRef =
|
||||
getExternalPointerReference(addr, newType, stackPointers, refMgr, existingType);
|
||||
}
|
||||
|
||||
newDataType = newDataType.clone(program.getDataTypeManager());
|
||||
newDataType = reconcileAppliedDataType(existingDT, newDataType, stackPointers);
|
||||
newType = newType.clone(program.getDataTypeManager());
|
||||
newType = reconcileAppliedDataType(existingType, newType, stackPointers);
|
||||
|
||||
DataType realType = newDataType;
|
||||
if (newDataType instanceof TypeDef) {
|
||||
realType = ((TypeDef) newDataType).getBaseDataType();
|
||||
DataType realType = newType;
|
||||
if (newType instanceof TypeDef) {
|
||||
realType = ((TypeDef) newType).getBaseDataType();
|
||||
}
|
||||
|
||||
// is the datatype already there?
|
||||
if (!(realType instanceof Dynamic) && !(realType instanceof FactoryDataType) &&
|
||||
newDataType.equals(existingDT)) {
|
||||
if (isExistingNonDynamicType(realType, newType, existingType)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
MemBuffer memBuf = new DumbMemBufferImpl(program.getMemory(), addr);
|
||||
DataTypeInstance dti;
|
||||
if (length > 0 && (realType instanceof Dynamic) &&
|
||||
((Dynamic) realType).canSpecifyLength()) {
|
||||
dti = DataTypeInstance.getDataTypeInstance(newDataType, memBuf, length);
|
||||
}
|
||||
else {
|
||||
dti = DataTypeInstance.getDataTypeInstance(newDataType, memBuf);
|
||||
}
|
||||
if (dti == null) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Could not create DataType " + newDataType.getDisplayName());
|
||||
}
|
||||
|
||||
if (stackPointers && existingDT instanceof Pointer && newDataType instanceof Pointer) {
|
||||
DataTypeInstance dti = getDtInstance(program, addr, newType, length, realType);
|
||||
if (stackPointers && existingType instanceof Pointer && newType instanceof Pointer) {
|
||||
listing.clearCodeUnits(addr, addr, false);
|
||||
}
|
||||
|
||||
|
@ -190,56 +152,175 @@ public final class DataUtilities {
|
|||
listing.clearCodeUnits(addr, addr, false);
|
||||
}
|
||||
else {
|
||||
checkEnoughSpace(program, addr, existingDataLen, dti, clearMode);
|
||||
checkEnoughSpace(program, addr, existingLength, dti, clearMode);
|
||||
}
|
||||
newData = listing.createData(addr, dti.getDataType(), dti.getLength());
|
||||
}
|
||||
|
||||
restoreReference(newType, refMgr, extRef);
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
private static boolean isParentData(Data data, Address addr) {
|
||||
return !data.getAddress().equals(addr);
|
||||
}
|
||||
|
||||
private static Data getData(Address addr, ClearDataMode clearMode, Listing listing)
|
||||
throws CodeUnitInsertionException {
|
||||
|
||||
Data data = listing.getDataAt(addr);
|
||||
if (data != null) {
|
||||
return data; // existing data; it us possible to create data
|
||||
}
|
||||
|
||||
// null data; see if we are in a composite
|
||||
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
||||
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) {
|
||||
|
||||
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
||||
data = listing.getDataContaining(addr);
|
||||
if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||
!Undefined.isUndefined(data.getDataType())) {
|
||||
data = null; // force error
|
||||
}
|
||||
}
|
||||
|
||||
// null data implies that we cannot create data at this address
|
||||
if (data == null) {
|
||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private static DataTypeInstance getDtInstance(Program program, Address addr, DataType newType,
|
||||
int length, DataType realType) throws CodeUnitInsertionException {
|
||||
|
||||
MemBuffer memBuf = new DumbMemBufferImpl(program.getMemory(), addr);
|
||||
DataTypeInstance dti;
|
||||
if (length > 0 && (realType instanceof Dynamic) &&
|
||||
((Dynamic) realType).canSpecifyLength()) {
|
||||
dti = DataTypeInstance.getDataTypeInstance(newType, memBuf, length);
|
||||
}
|
||||
else {
|
||||
dti = DataTypeInstance.getDataTypeInstance(newType, memBuf);
|
||||
}
|
||||
|
||||
if (dti == null) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Could not create DataType " + newType.getDisplayName());
|
||||
}
|
||||
|
||||
return dti;
|
||||
}
|
||||
|
||||
private static boolean isExistingNonDynamicType(DataType realType, DataType newType,
|
||||
DataType existingType) {
|
||||
|
||||
if (realType instanceof Dynamic || realType instanceof FactoryDataType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// not dynamic or factory--does it exist?
|
||||
return newType.equals(existingType);
|
||||
}
|
||||
|
||||
private static void restoreReference(DataType newType, ReferenceManager refMgr,
|
||||
Reference ref) {
|
||||
|
||||
if (ref == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(newType instanceof Pointer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if this was a pointer and had an external reference, put it back!
|
||||
if ((newDataType instanceof Pointer) && extRef != null) {
|
||||
ExternalLocation extLoc = ((ExternalReference) extRef).getExternalLocation();
|
||||
ExternalLocation extLoc = ((ExternalReference) ref).getExternalLocation();
|
||||
Address fromAddress = ref.getFromAddress();
|
||||
SourceType source = ref.getSource();
|
||||
RefType type = ref.getReferenceType();
|
||||
try {
|
||||
refMgr.addExternalReference(extRef.getFromAddress(), 0, extLoc, extRef.getSource(),
|
||||
extRef.getReferenceType());
|
||||
refMgr.addExternalReference(fromAddress, 0, extLoc, source, type);
|
||||
}
|
||||
catch (InvalidInputException e) {
|
||||
throw new AssertException(e);
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
|
||||
private static Reference getExternalPointerReference(Address addr, DataType newType,
|
||||
boolean stackPointers,
|
||||
ReferenceManager refMgr, DataType existingType) {
|
||||
Reference extRef = null;
|
||||
if ((stackPointers || newType instanceof Pointer) &&
|
||||
existingType instanceof Pointer) {
|
||||
Reference[] refs = refMgr.getReferencesFrom(addr);
|
||||
for (Reference ref : refs) {
|
||||
if (ref.getOperandIndex() == 0 && ref.isExternalReference()) {
|
||||
extRef = ref;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return extRef;
|
||||
}
|
||||
|
||||
private static void validateCanCreateData(Address addr, ClearDataMode clearMode,
|
||||
Listing listing, Data data) throws CodeUnitInsertionException {
|
||||
|
||||
if (data != null) {
|
||||
return; // existing data; it us possible to create data
|
||||
}
|
||||
|
||||
if (clearMode == ClearDataMode.CLEAR_ALL_CONFLICT_DATA ||
|
||||
clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA) {
|
||||
|
||||
// allow offcut addr if CLEAR_ALL_CONFLICT_DATA
|
||||
data = listing.getDataContaining(addr);
|
||||
if (data != null && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||
!Undefined.isUndefined(data.getDataType())) {
|
||||
data = null; // force error
|
||||
}
|
||||
}
|
||||
|
||||
// null data implies that we cannot create data at this address
|
||||
if (data == null) {
|
||||
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
|
||||
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
|
||||
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
|
||||
Listing listing = program.getListing();
|
||||
Address end = null;
|
||||
Address newEnd = null;
|
||||
try {
|
||||
Address end = addr.addNoWrap(existingDataLen - 1);
|
||||
Address newEnd = addr.addNoWrap(dti.getLength() - 1);
|
||||
end = addr.addNoWrap(existingDataLen - 1);
|
||||
newEnd = addr.addNoWrap(dti.getLength() - 1);
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Not enough space to create DataType " + dti.getDataType().getDisplayName());
|
||||
}
|
||||
|
||||
Instruction instr = listing.getInstructionAfter(end);
|
||||
if (instr != null && instr.getMinAddress().compareTo(newEnd) <= 0) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Not enough space to create DataType " + dti.getDataType().getDisplayName());
|
||||
}
|
||||
|
||||
Data definedData = listing.getDefinedDataAfter(end);
|
||||
if (definedData != null && definedData.getMinAddress().compareTo(newEnd) <= 0) {
|
||||
if (definedData == null || definedData.getMinAddress().compareTo(newEnd) > 0) {
|
||||
listing.clearCodeUnits(addr, addr, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||
Undefined.isUndefined(definedData.getDataType())) {
|
||||
// ignore all defined data which is considered Undefined and may be cleared
|
||||
end = definedData.getMaxAddress();
|
||||
while (end.compareTo(newEnd) <= 0) {
|
||||
definedData = listing.getDefinedDataAfter(end);
|
||||
if (definedData == null ||
|
||||
definedData.getMinAddress().compareTo(newEnd) > 0) {
|
||||
break;
|
||||
}
|
||||
if (!Undefined.isUndefined(definedData.getDataType())) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Not enough space to create DataType " +
|
||||
dti.getDataType().getDisplayName());
|
||||
}
|
||||
end = definedData.getMaxAddress();
|
||||
}
|
||||
checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress());
|
||||
}
|
||||
else if (mode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) {
|
||||
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
||||
|
@ -247,13 +328,23 @@ public final class DataUtilities {
|
|||
}
|
||||
listing.clearCodeUnits(addr, newEnd, false);
|
||||
}
|
||||
else {
|
||||
listing.clearCodeUnits(addr, addr, false);
|
||||
|
||||
private static void checkForDefinedData(DataTypeInstance dti, Listing listing, Address address,
|
||||
Address end) throws CodeUnitInsertionException {
|
||||
|
||||
// ignore all defined data which is considered Undefined and may be cleared
|
||||
while (end.compareTo(address) <= 0) {
|
||||
Data definedData = listing.getDefinedDataAfter(end);
|
||||
if (definedData == null ||
|
||||
definedData.getMinAddress().compareTo(address) > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Undefined.isUndefined(definedData.getDataType())) {
|
||||
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
||||
dti.getDataType().getDisplayName());
|
||||
}
|
||||
catch (AddressOverflowException e) {
|
||||
throw new CodeUnitInsertionException(
|
||||
"Not enough space to create DataType " + dti.getDataType().getDisplayName());
|
||||
end = definedData.getMaxAddress();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +446,10 @@ public final class DataUtilities {
|
|||
* Get the data for the given address.
|
||||
* <P>
|
||||
* This will return a Data if and only if there is data that starts at the given address.
|
||||
* @return the Data that starts at the given address or null if the address is code or offcut.
|
||||
*
|
||||
* @param program the program
|
||||
* @param address the data address
|
||||
* @return the Data that starts at the given address or null if the address is code or offcut
|
||||
*/
|
||||
public static Data getDataAtAddress(Program program, Address address) {
|
||||
if (address == null) {
|
||||
|
@ -417,9 +511,9 @@ public final class DataUtilities {
|
|||
* Determine if the specified addr corresponds to an undefined data location
|
||||
* where both undefined code units and defined data which has an Undefined
|
||||
* data type is considered to be undefined.
|
||||
* @param program
|
||||
* @param addr
|
||||
* @return
|
||||
* @param program the program
|
||||
* @param addr the data address
|
||||
* @return true if the data is undefined
|
||||
*/
|
||||
public static boolean isUndefinedData(Program program, Address addr) {
|
||||
Data data = program.getListing().getDataAt(addr);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue