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() {
|
private JComponent createDataTypeChoiceEditor() {
|
||||||
|
|
||||||
dtChoiceEditor =
|
dtChoiceEditor =
|
||||||
new DataTypeSelectionEditor(dtmService, -1, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
new DataTypeSelectionEditor(dtmService, AllowedDataTypes.BITFIELD_BASE_TYPE);
|
||||||
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
dtChoiceEditor.setConsumeEnterKeyPress(false);
|
||||||
dtChoiceEditor.setTabCommitsEdit(true);
|
dtChoiceEditor.setTabCommitsEdit(true);
|
||||||
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
//dtChoiceEditor.setPreferredDataTypeManager(composite.getDataTypeManager());
|
||||||
|
@ -539,7 +539,7 @@ public class BitFieldEditorPanel extends JPanel {
|
||||||
dtChoiceEditor.getDropDownTextField().setText("");
|
dtChoiceEditor.getDropDownTextField().setText("");
|
||||||
fieldNameTextField.setText(null);
|
fieldNameTextField.setText(null);
|
||||||
fieldCommentTextField.setText(null);
|
fieldCommentTextField.setText(null);
|
||||||
;
|
|
||||||
bitOffsetModel.setValue(0L);
|
bitOffsetModel.setValue(0L);
|
||||||
bitSizeModel.setValue(1L);
|
bitSizeModel.setValue(1L);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1255,7 +1255,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||||
|
|
||||||
Plugin plugin = provider.getPlugin();
|
Plugin plugin = provider.getPlugin();
|
||||||
final PluginTool tool = plugin.getTool();
|
final PluginTool tool = plugin.getTool();
|
||||||
editor = new DataTypeSelectionEditor(tool, maxLength,
|
editor = new DataTypeSelectionEditor(tool,
|
||||||
bitfieldAllowed ? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
bitfieldAllowed ? AllowedDataTypes.SIZABLE_DYNAMIC_AND_BITFIELD
|
||||||
: AllowedDataTypes.SIZABLE_DYNAMIC);
|
: AllowedDataTypes.SIZABLE_DYNAMIC);
|
||||||
editor.setTabCommitsEdit(true);
|
editor.setTabCommitsEdit(true);
|
||||||
|
@ -1287,12 +1287,7 @@ public abstract class CompositeEditorPanel extends JPanel
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dataTypeChooserButton.addActionListener(new ActionListener() {
|
dataTypeChooserButton.addActionListener(e -> Swing.runLater(() -> stopEdit(tool)));
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
Swing.runLater(() -> stopEdit(tool));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
textField.addFocusListener(new FocusAdapter() {
|
textField.addFocusListener(new FocusAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,12 +24,8 @@ import docking.action.*;
|
||||||
import ghidra.app.context.ListingActionContext;
|
import ghidra.app.context.ListingActionContext;
|
||||||
import ghidra.app.util.datatype.DataTypeSelectionDialog;
|
import ghidra.app.util.datatype.DataTypeSelectionDialog;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.address.AddressRange;
|
import ghidra.program.model.listing.Data;
|
||||||
import ghidra.program.model.data.*;
|
|
||||||
import ghidra.program.model.listing.*;
|
|
||||||
import ghidra.program.util.*;
|
|
||||||
import ghidra.util.SystemUtilities;
|
|
||||||
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
import ghidra.util.data.DataTypeParser.AllowedDataTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,121 +54,21 @@ public class ChooseDataTypeAction extends DockingAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
ListingActionContext programActionContext =
|
ListingActionContext listingContext = (ListingActionContext) context.getContextObject();
|
||||||
(ListingActionContext) context.getContextObject();
|
DataType dataType = getDataType(listingContext);
|
||||||
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());
|
|
||||||
if (dataType != null) {
|
if (dataType != null) {
|
||||||
plugin.doCreateData(program, loc, sel, dataType, false);
|
plugin.createData(dataType, listingContext, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getSizeInsideStructure(Program program, InteriorSelection selection) {
|
private DataType getDataType(ListingActionContext context) {
|
||||||
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) {
|
|
||||||
PluginTool tool = plugin.getTool();
|
PluginTool tool = plugin.getTool();
|
||||||
Data data = plugin.getDataUnit(context);
|
Data data = plugin.getDataUnit(context);
|
||||||
|
int noSizeRestriction = -1;
|
||||||
DataTypeSelectionDialog selectionDialog = new DataTypeSelectionDialog(tool,
|
DataTypeSelectionDialog selectionDialog = new DataTypeSelectionDialog(tool,
|
||||||
data.getProgram().getDataTypeManager(), maxElements, AllowedDataTypes.ALL);
|
data.getProgram().getDataTypeManager(), noSizeRestriction, AllowedDataTypes.ALL);
|
||||||
DataType currentDataType = data.getBaseDataType();
|
DataType initialType = data.getBaseDataType();
|
||||||
selectionDialog.setInitialDataType(currentDataType);
|
selectionDialog.setInitialDataType(initialType);
|
||||||
tool.showDialog(selectionDialog);
|
tool.showDialog(selectionDialog);
|
||||||
return selectionDialog.getUserChosenDataType();
|
return selectionDialog.getUserChosenDataType();
|
||||||
}
|
}
|
||||||
|
@ -185,47 +81,4 @@ public class ChooseDataTypeAction extends DockingAction {
|
||||||
}
|
}
|
||||||
return false;
|
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);
|
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) {
|
DataType getEditableDataTypeFromContext(ListingActionContext context) {
|
||||||
ProgramSelection currentSelection = context.getSelection();
|
ProgramSelection selection = context.getSelection();
|
||||||
Program currentProgram = context.getProgram();
|
Program program = context.getProgram();
|
||||||
DataType editableDataType = null;
|
|
||||||
Data data = null;
|
Data data = null;
|
||||||
if (currentSelection != null && !currentSelection.isEmpty()) {
|
if (selection != null && !selection.isEmpty()) {
|
||||||
Listing listing = currentProgram.getListing();
|
Listing listing = program.getListing();
|
||||||
boolean isDataOnly = !listing.getInstructions(currentSelection, true).hasNext();
|
boolean isDataOnly = !listing.getInstructions(selection, true).hasNext();
|
||||||
if (isDataOnly) {
|
if (isDataOnly) {
|
||||||
data = getDataUnit(context);
|
data = getDataUnit(context);
|
||||||
}
|
}
|
||||||
|
@ -270,30 +252,30 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
else {
|
else {
|
||||||
data = getDataUnit(context);
|
data = getDataUnit(context);
|
||||||
}
|
}
|
||||||
if (data != null) {
|
|
||||||
if (dtmService != null) {
|
return getEditableDataType(data);
|
||||||
DataType baseDt = data.getBaseDataType();
|
}
|
||||||
if (dtmService.isEditable(baseDt)) {
|
|
||||||
editableDataType = baseDt;
|
private DataType getEditableDataType(Data data) {
|
||||||
}
|
if (data == null || dtmService == null) {
|
||||||
else {
|
return null;
|
||||||
Data pdata = data.getParent();
|
}
|
||||||
if (pdata != null) {
|
|
||||||
baseDt = pdata.getBaseDataType();
|
DataType baseDt = data.getBaseDataType();
|
||||||
if (dtmService.isEditable(baseDt)) {
|
if (dtmService.isEditable(baseDt)) {
|
||||||
editableDataType = baseDt;
|
return baseDt;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
Data pdata = data.getParent();
|
||||||
}
|
if (pdata != null) {
|
||||||
}
|
baseDt = pdata.getBaseDataType();
|
||||||
return editableDataType;
|
if (dtmService.isEditable(baseDt)) {
|
||||||
|
return baseDt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.app.services.DataService#createData(ghidra.program.model.data.DataType,
|
|
||||||
* ghidra.app.context.ListingActionContext, boolean)
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean createData(DataType dt, ListingActionContext context,
|
public boolean createData(DataType dt, ListingActionContext context,
|
||||||
boolean enableConflictHandling) {
|
boolean enableConflictHandling) {
|
||||||
|
@ -307,8 +289,7 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This version uses the ProgramActionContext and does not depend on any
|
* This version uses the ListingActionContext and does not depend on any plugin's currentProgram
|
||||||
* plugin's currentProgram
|
|
||||||
*/
|
*/
|
||||||
boolean doCreateData(ListingActionContext context, DataType dt) {
|
boolean doCreateData(ListingActionContext context, DataType dt) {
|
||||||
ProgramSelection selection = context.getSelection();
|
ProgramSelection selection = context.getSelection();
|
||||||
|
@ -316,7 +297,7 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
Program program = context.getProgram();
|
Program program = context.getProgram();
|
||||||
|
|
||||||
dt = dt.clone(program.getDataTypeManager());
|
dt = dt.clone(program.getDataTypeManager());
|
||||||
boolean didCreateData = true;
|
boolean didCreateData = false;
|
||||||
if (selection != null && !selection.isEmpty()) {
|
if (selection != null && !selection.isEmpty()) {
|
||||||
didCreateData = createDataForSelection(program, dt, selection);
|
didCreateData = createDataForSelection(program, dt, selection);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +356,7 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
Data data = listing.getDataAt(start);
|
Data data = listing.getDataAt(start);
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
tool.setStatusInfo("Invalid data location");
|
tool.setStatusInfo("Invalid data location. Cannot create data at " + start + '.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,10 +374,13 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
end = start.addNoWrap(newSize - 1);
|
end = start.addNoWrap(newSize - 1);
|
||||||
}
|
}
|
||||||
catch (AddressOverflowException e) {
|
catch (AddressOverflowException e) {
|
||||||
|
tool.setStatusInfo("Invalid data location. Not enough space at " + start + " for " +
|
||||||
|
newSize + " bytes.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intstrutionExists(listing, dataType, start, end)) {
|
if (intstrutionExists(listing, dataType, start, end)) {
|
||||||
|
tool.setStatusInfo("Invalid data location. Instruction exists at " + start + '.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +399,7 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
Data definedData =
|
Data definedData =
|
||||||
DataUtilities.getNextNonUndefinedDataAfter(program, start, blockMaxAddress);
|
DataUtilities.getNextNonUndefinedDataAfter(program, start, blockMaxAddress);
|
||||||
if (dataExists(program, dataType, definedData, start, end)) {
|
if (dataExists(program, dataType, definedData, start, end)) {
|
||||||
return false;
|
return false; // status updated in 'dataExists()' call
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -516,58 +500,6 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
return dataTypeInstance.getLength();
|
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() {
|
PluginTool getPluginTool() {
|
||||||
return tool;
|
return tool;
|
||||||
}
|
}
|
||||||
|
@ -741,9 +673,6 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ghidra.framework.plugintool.Plugin#dispose()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
favoritesUpdateManager.dispose();
|
favoritesUpdateManager.dispose();
|
||||||
|
@ -756,10 +685,6 @@ public class DataPlugin extends Plugin implements DataService {
|
||||||
createStructureAction.dispose();
|
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) {
|
Data getDataUnit(ListingActionContext context) {
|
||||||
ProgramLocation location = context.getLocation();
|
ProgramLocation location = context.getLocation();
|
||||||
ProgramSelection selection = context.getSelection();
|
ProgramSelection selection = context.getSelection();
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class CreateTypeDefDialog extends DialogComponentProvider {
|
||||||
|
|
||||||
// data type info
|
// data type info
|
||||||
dataTypeEditor =
|
dataTypeEditor =
|
||||||
new DataTypeSelectionEditor(plugin.getTool(), Integer.MAX_VALUE, AllowedDataTypes.ALL);
|
new DataTypeSelectionEditor(plugin.getTool(), AllowedDataTypes.ALL);
|
||||||
panel.add(new GLabel("Data type:"));
|
panel.add(new GLabel("Data type:"));
|
||||||
panel.add(dataTypeEditor.getEditorComponent());
|
panel.add(dataTypeEditor.getEditorComponent());
|
||||||
|
|
||||||
|
|
|
@ -373,7 +373,8 @@ public class FunctionPlugin extends Plugin implements DataService {
|
||||||
/**
|
/**
|
||||||
* Get an iterator over all functions overlapping the current selection.
|
* Get an iterator over all functions overlapping the current selection.
|
||||||
* If there is no selection any functions overlapping the current location.
|
* If there is no selection any functions overlapping the current location.
|
||||||
*
|
*
|
||||||
|
* @param context the context
|
||||||
* @return Iterator over functions
|
* @return Iterator over functions
|
||||||
*/
|
*/
|
||||||
public Iterator<Function> getFunctions(ListingActionContext context) {
|
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
|
* Lay down the specified dataType on a function return, parameter or local variable
|
||||||
* based upon the programActionContext. Pointer conversion will be handled
|
* based upon the programActionContext. Pointer conversion will be handled
|
||||||
* by merging the existing dataType with the specified dataType.
|
* 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 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)
|
* 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
|
@Override
|
||||||
public boolean createData(DataType dt, ListingActionContext programActionContext,
|
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
|
* This method is the same as {@link #createData(DataType, ListingActionContext, boolean)},
|
||||||
* method will use the given value of <tt>convertPointers</tt> to determine if the new
|
* except that this method will use the given value of <tt>convertPointers</tt> to determine
|
||||||
* DataType should be made into a pointer if the existing DataType is a pointer.
|
* 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.
|
* @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
|
* @param convertPointers True signals to convert the given DataType to a pointer if there is
|
||||||
* an existing pointer at the specified location.
|
* an existing pointer at the specified location.
|
||||||
* @param promptForConflictRemoval if true and specified dataType results in a storage conflict,
|
* @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;
|
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
|
* Return the maximum data type length permitted for the specified local variable. A -1
|
||||||
* for the specified local variable. A -1 returned
|
* returned value indicates no limit imposed.
|
||||||
* value indicates no limit imposed.
|
*
|
||||||
* @param fun
|
* @param fun the function
|
||||||
* @param var
|
* @param var the variable
|
||||||
* @return maximum data type length permitted for var
|
* @return maximum data type length permitted for var
|
||||||
*/
|
*/
|
||||||
int getMaxStackVariableSize(Function fun, Variable var) {
|
int getMaxStackVariableSize(Function fun, Variable var) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
editor = new DataTypeSelectionEditor(service, -1, DataTypeParser.AllowedDataTypes.ALL);
|
editor = new DataTypeSelectionEditor(service, DataTypeParser.AllowedDataTypes.ALL);
|
||||||
editor.setTabCommitsEdit(true);
|
editor.setTabCommitsEdit(true);
|
||||||
editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses
|
editor.setConsumeEnterKeyPress(false); // we want the table to handle Enter key presses
|
||||||
|
|
||||||
|
@ -88,25 +88,16 @@ class ParameterDataTypeCellEditor extends AbstractCellEditor implements TableCel
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dataTypeChooserButton.addActionListener(new ActionListener() {
|
dataTypeChooserButton.addActionListener(e -> SwingUtilities.invokeLater(() -> {
|
||||||
@Override
|
DataType dataType = service.getDataType((String) null);
|
||||||
public void actionPerformed(ActionEvent e) {
|
if (dataType != null) {
|
||||||
|
editor.setCellEditorValue(dataType);
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
editor.stopCellEditing();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
DataType dataType = service.getDataType((String) null);
|
|
||||||
if (dataType != null) {
|
|
||||||
editor.setCellEditorValue(dataType);
|
|
||||||
editor.stopCellEditing();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
editor.cancelCellEditing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
else {
|
||||||
|
editor.cancelCellEditing();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
FocusAdapter focusListener = new FocusAdapter() {
|
FocusAdapter focusListener = new FocusAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -20,13 +20,9 @@ import ghidra.framework.plugintool.ServiceInfo;
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data Creation service.
|
* Service for creating data
|
||||||
*
|
|
||||||
* 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
|
|
||||||
*/
|
*/
|
||||||
@ServiceInfo(description = "Data creation service.")
|
@ServiceInfo(description = "Data creation service")
|
||||||
public interface DataService {
|
public interface DataService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,13 +38,12 @@ public interface DataService {
|
||||||
/**
|
/**
|
||||||
* Apply the given data type at a location.
|
* Apply the given data type at a location.
|
||||||
*
|
*
|
||||||
* @param dt
|
* @param dt data type to create at the location
|
||||||
* dataType to create at the location
|
* @param context the context containing program, location, and selection information
|
||||||
* @param context
|
* @param enableConflictHandling if true, the service may prompt the user to resolve data
|
||||||
* the context containing program, location, and selection information
|
* conflicts
|
||||||
* @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
|
* @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() {
|
private void buildEditor() {
|
||||||
removeWorkPanel();
|
removeWorkPanel();
|
||||||
|
|
||||||
editor = new DataTypeSelectionEditor(pluginTool, maxSize, allowedTypes);
|
editor = new DataTypeSelectionEditor(pluginTool, allowedTypes);
|
||||||
editor.setPreferredDataTypeManager(dtm);
|
editor.setPreferredDataTypeManager(dtm);
|
||||||
editor.setConsumeEnterKeyPress(false); // we want to handle Enter key presses
|
editor.setConsumeEnterKeyPress(false); // we want to handle Enter key presses
|
||||||
editor.addCellEditorListener(new CellEditorListener() {
|
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
|
* 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
|
* 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.
|
* 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) {
|
public void setTabCommitsEdit(boolean doesCommit) {
|
||||||
editor.setTabCommitsEdit(doesCommit);
|
editor.setTabCommitsEdit(doesCommit);
|
||||||
|
|
|
@ -59,7 +59,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
private DropDownSelectionTextField<DataType> selectionField;
|
private DropDownSelectionTextField<DataType> selectionField;
|
||||||
private JButton browseButton;
|
private JButton browseButton;
|
||||||
private DataTypeManagerService dataTypeManagerService;
|
private DataTypeManagerService dataTypeManagerService;
|
||||||
private int maxSize = -1;
|
|
||||||
private DataTypeManager dataTypeManager;
|
private DataTypeManager dataTypeManager;
|
||||||
private DataTypeParser.AllowedDataTypes allowedDataTypes;
|
private DataTypeParser.AllowedDataTypes allowedDataTypes;
|
||||||
|
|
||||||
|
@ -69,12 +68,12 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
// optional path to initially select in the data type chooser tree
|
// optional path to initially select in the data type chooser tree
|
||||||
private TreePath initiallySelectedTreePath;
|
private TreePath initiallySelectedTreePath;
|
||||||
|
|
||||||
public DataTypeSelectionEditor(ServiceProvider serviceProvider, int maxSize,
|
public DataTypeSelectionEditor(ServiceProvider serviceProvider,
|
||||||
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
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) {
|
DataTypeParser.AllowedDataTypes allowedDataTypes) {
|
||||||
|
|
||||||
if (service == null) {
|
if (service == null) {
|
||||||
|
@ -82,7 +81,6 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.dataTypeManagerService = service;
|
this.dataTypeManagerService = service;
|
||||||
this.maxSize = maxSize;
|
|
||||||
this.allowedDataTypes = allowedDataTypes;
|
this.allowedDataTypes = allowedDataTypes;
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
@ -102,7 +100,10 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets whether this editor should consumer Enter key presses
|
||||||
* @see DropDownSelectionTextField#setConsumeEnterKeyPress(boolean)
|
* @see DropDownSelectionTextField#setConsumeEnterKeyPress(boolean)
|
||||||
|
*
|
||||||
|
* @param consume true to consume
|
||||||
*/
|
*/
|
||||||
public void setConsumeEnterKeyPress(boolean consume) {
|
public void setConsumeEnterKeyPress(boolean consume) {
|
||||||
selectionField.setConsumeEnterKeyPress(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
|
* Returns the direction of the user triggered navigation; null if the user did not trigger
|
||||||
* navigation out of this component.
|
* navigation out of this component.
|
||||||
|
* @return the direction
|
||||||
*/
|
*/
|
||||||
public NavigationDirection getNavigationDirection() {
|
public NavigationDirection getNavigationDirection() {
|
||||||
return navigationDirection;
|
return navigationDirection;
|
||||||
|
@ -362,10 +364,8 @@ public class DataTypeSelectionEditor extends AbstractCellEditor {
|
||||||
catch (CancelledException e) {
|
catch (CancelledException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newDataType != null) {
|
if (newDataType != null) {
|
||||||
if (maxSize >= 0 && newDataType.getLength() > newDataType.getLength()) {
|
|
||||||
throw new InvalidDataTypeException("data-type larger than " + maxSize + " bytes");
|
|
||||||
}
|
|
||||||
selectionField.setSelectedValue(newDataType);
|
selectionField.setSelectedValue(newDataType);
|
||||||
return true;
|
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
|
* the source data type manager, this means that all data type managers will be used when
|
||||||
* resolving data types.
|
* resolving data types.
|
||||||
*
|
*
|
||||||
* @param dataTypeManagerService
|
* @param dataTypeManagerService data-type manager tool service, or null
|
||||||
* @param allowedTypes
|
* @param allowedTypes constrains which data-types may be parsed
|
||||||
*/
|
*/
|
||||||
public DataTypeParser(DataTypeQueryService dataTypeManagerService,
|
public DataTypeParser(DataTypeQueryService dataTypeManagerService,
|
||||||
AllowedDataTypes allowedTypes) {
|
AllowedDataTypes allowedTypes) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.data;
|
package ghidra.app.plugin.core.data;
|
||||||
|
|
||||||
|
import static org.hamcrest.core.StringContains.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -22,9 +23,9 @@ import javax.swing.*;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import docking.DialogComponentProvider;
|
import docking.*;
|
||||||
import docking.DockingDialog;
|
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
|
import generic.test.TestUtils;
|
||||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||||
import ghidra.app.plugin.core.codebrowser.*;
|
import ghidra.app.plugin.core.codebrowser.*;
|
||||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
||||||
|
@ -50,7 +51,6 @@ import ghidra.test.TestEnv;
|
||||||
|
|
||||||
public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationTest {
|
public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
private static final String PROGRAM_FILENAME = "WallaceSrc";
|
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 static final String CYCLE_BYTE_WORD_DWORD_QWORD = "Cycle: byte,word,dword,qword";
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
|
@ -63,6 +63,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
private DataTypeArchiveGTree tree;
|
private DataTypeArchiveGTree tree;
|
||||||
private ArchiveRootNode archiveRootNode;
|
private ArchiveRootNode archiveRootNode;
|
||||||
private ArchiveNode programNode;
|
private ArchiveNode programNode;
|
||||||
|
private CodeViewerProvider codeViewerProvider;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
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);
|
assertNotNull("Did not successfully wait for the program node to load", programNode);
|
||||||
|
|
||||||
tool.showComponentProvider(provider, true);
|
tool.showComponentProvider(provider, true);
|
||||||
|
|
||||||
|
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
||||||
|
codeViewerProvider = codeBrowserPlugin.getProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProgramDB buildWallaceSrcProgram() throws Exception {
|
private ProgramDB buildWallaceSrcProgram() throws Exception {
|
||||||
|
@ -121,24 +125,19 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
executeOnSwingWithoutBlocking(() -> {
|
executeOnSwingWithoutBlocking(() -> {
|
||||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||||
pm.closeProgram();
|
pm.closeProgram();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// this handles the save changes dialog and potential analysis dialogs
|
// this handles the save changes dialog and potential analysis dialogs
|
||||||
closeAllWindowsAndFrames();
|
closeAllWindows();
|
||||||
|
|
||||||
env.release(program);
|
|
||||||
env.dispose();
|
env.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChooseDataTypeOnDefaultDts() throws Exception {
|
public void testChooseDataTypeOnDefaultDts() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
|
||||||
|
|
||||||
chooseInDialog("_person");
|
chooseInDialog("_person");
|
||||||
|
|
||||||
|
@ -152,12 +151,9 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testChooseDataTypeOnUndefinedDts() throws Exception {
|
public void testChooseDataTypeOnUndefinedDts() throws Exception {
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
|
||||||
|
|
||||||
chooseInDialog("_person");
|
chooseInDialog("_person");
|
||||||
|
|
||||||
|
@ -170,80 +166,67 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChooseDataTypeOnDefinedDts() throws Exception {
|
public void testChooseDataTypeOnDefinedDts() throws Exception {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test that apply data on an existing type will offer to clear that type
|
||||||
|
//
|
||||||
|
|
||||||
createData("004027d1", new ByteDataType());
|
createData("004027d1", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
|
||||||
|
|
||||||
DialogComponentProvider dialog =
|
chooseInDialog("_person");
|
||||||
chooseInDialog("_person", "_person doesn't fit within 1 bytes, need 41 bytes");
|
|
||||||
|
pressConflictingDataDialog("Yes");
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
assertEquals(dataType, data.getDataType());
|
||||||
pressButtonByText(dialog, "Cancel");
|
assertEquals(addr("004027f8"), data.getMaxAddress());
|
||||||
waitForSwing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChooseDataTypeOnDefinedAndUndefinedDts() throws Exception {
|
public void testChooseDataTypeOnDefinedAndUndefinedDts() throws Exception {
|
||||||
createData("004027d1", new ByteDataType());
|
createData("004027d1", new ByteDataType());
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
chooseInDialog("_person");
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
pressConflictingDataDialog("No");
|
||||||
|
|
||||||
DialogComponentProvider dialog =
|
|
||||||
chooseInDialog("_person", "_person doesn't fit within 1 bytes, need 41 bytes");
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
assertEquals(addr("004027d0"), data.getMaxAddress());
|
||||||
|
|
||||||
pressButtonByText(dialog, "Cancel");
|
|
||||||
waitForSwing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChooseDataTypeWhereDoesNotFit() throws Exception {
|
public void testChooseDataTypeWhereDoesNotFit() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027e0");
|
goTo("004027e0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
|
||||||
|
|
||||||
DialogComponentProvider dialog =
|
showDataTypeChooser();
|
||||||
chooseInDialog("_person", "_person doesn't fit within 32 bytes, need 41 bytes");
|
chooseInDialog("_person");
|
||||||
|
|
||||||
|
assertToolStatus("Not enough room in memory block containing address");
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
assertEquals(addr("004027d0"), data.getMaxAddress());
|
assertEquals(addr("004027d0"), data.getMaxAddress());
|
||||||
|
|
||||||
pressButtonByText(dialog, "Cancel");
|
|
||||||
waitForSwing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateArrayOnDefaultDts() throws Exception {
|
public void testCreateArrayOnDefaultDts() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
JTextField tf = findComponent(dialog, JTextField.class);
|
JTextField tf = findComponent(dialog, JTextField.class);
|
||||||
triggerText(tf, "48");
|
triggerText(tf, "48");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
@ -261,8 +244,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testCreateArrayOnUndefinedDts() throws Exception {
|
public void testCreateArrayOnUndefinedDts() throws Exception {
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -270,8 +252,8 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
JTextField tf = findComponent(dialog, JTextField.class);
|
JTextField tf = findComponent(dialog, JTextField.class);
|
||||||
triggerText(tf, "48");
|
triggerText(tf, "48");
|
||||||
|
|
||||||
|
@ -288,8 +270,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testCreateArrayFailureOnDefinedDts() throws Exception {
|
public void testCreateArrayFailureOnDefinedDts() throws Exception {
|
||||||
createData("004027d4", new ByteDataType());
|
createData("004027d4", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -297,8 +278,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
checkStatus((DockingDialog) dialog, "Entering more than 4 will overwrite existing data");
|
checkStatus((DockingDialog) dialog, "Entering more than 4 will overwrite existing data");
|
||||||
|
|
||||||
|
@ -326,8 +306,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
createCode("004027d4", 1);
|
createCode("004027d4", 1);
|
||||||
|
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -335,8 +314,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
checkStatus((DockingDialog) dialog, " ");
|
checkStatus((DockingDialog) dialog, " ");
|
||||||
|
|
||||||
|
@ -364,8 +342,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
createCode("004027d4", 1);
|
createCode("004027d4", 1);
|
||||||
|
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -373,8 +350,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
checkStatus((DockingDialog) dialog, " ");
|
checkStatus((DockingDialog) dialog, " ");
|
||||||
|
|
||||||
|
@ -396,8 +372,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testCreateArrayOverwriteOnDefinedDts() throws Exception {
|
public void testCreateArrayOverwriteOnDefinedDts() throws Exception {
|
||||||
createData("004027d4", new ByteDataType());
|
createData("004027d4", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Define Array");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -405,8 +380,8 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Create undefined[]", 2000);
|
JDialog dialog = waitForJDialog("Create undefined[]");
|
||||||
assertNotNull(dialog);
|
|
||||||
JTextField tf = findComponent(dialog, JTextField.class);
|
JTextField tf = findComponent(dialog, JTextField.class);
|
||||||
triggerText(tf, "48");
|
triggerText(tf, "48");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
@ -417,8 +392,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
pressButtonByText(dialog, "OK");
|
pressButtonByText(dialog, "OK");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
dialog = waitForJDialog(tool.getToolFrame(), "Overwrite Existing Data?", 2000);
|
dialog = waitForJDialog("Overwrite Existing Data?");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "Yes");
|
pressButtonByText(dialog, "Yes");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
@ -434,8 +408,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
plugin.setRecentlyUsed(dataType);
|
plugin.setRecentlyUsed(dataType);
|
||||||
|
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -455,8 +428,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
plugin.setRecentlyUsed(dataType);
|
plugin.setRecentlyUsed(dataType);
|
||||||
|
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
|
@ -476,20 +448,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
plugin.setRecentlyUsed(dataType);
|
plugin.setRecentlyUsed(dataType);
|
||||||
|
|
||||||
createData("004027d1", new ByteDataType());
|
createData("004027d1", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||||
|
|
||||||
waitForSwing();
|
pressConflictingDataDialog("Yes");
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "Yes");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(dataType, data.getDataType());
|
assertEquals(dataType, data.getDataType());
|
||||||
|
@ -503,20 +467,13 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
plugin.setRecentlyUsed(dataType);
|
plugin.setRecentlyUsed(dataType);
|
||||||
|
|
||||||
createData("004027d1", new ByteDataType());
|
createData("004027d1", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Recently Used");
|
||||||
assertNotNull(chooseDataTypeAction);
|
assertNotNull(chooseDataTypeAction);
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
||||||
|
|
||||||
waitForSwing();
|
pressConflictingDataDialog("No");
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "No");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
|
@ -525,21 +482,18 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFavoriteOnDefaultDts() throws Exception {
|
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();
|
waitForSwing();
|
||||||
|
|
||||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
// Choose favorite
|
||||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
|
||||||
|
|
||||||
// Set _person as a favorite.
|
|
||||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
// Choose favorite.
|
|
||||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||||
assertNotNull(favoriteAction);
|
|
||||||
performAction(favoriteAction, codeViewerProvider, true);
|
performAction(favoriteAction, codeViewerProvider, true);
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
|
@ -550,21 +504,18 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testFavoriteOnUndefinedDts() throws Exception {
|
public void testFavoriteOnUndefinedDts() throws Exception {
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
// Set _person as a favorite.
|
// Set _person as a favorite
|
||||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
// Choose favorite.
|
// Choose favorite.
|
||||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||||
assertNotNull(favoriteAction);
|
|
||||||
performAction(favoriteAction, codeViewerProvider, true);
|
performAction(favoriteAction, codeViewerProvider, true);
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
|
@ -575,28 +526,20 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testFavoriteOnDefinedDtsAnswerYes() throws Exception {
|
public void testFavoriteOnDefinedDtsAnswerYes() throws Exception {
|
||||||
createData("004027d1", new ByteDataType());
|
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();
|
waitForSwing();
|
||||||
|
|
||||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
// Choose favorite
|
||||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
|
||||||
|
|
||||||
// Set _person as a favorite.
|
|
||||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
// Choose favorite.
|
|
||||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||||
assertNotNull(favoriteAction);
|
|
||||||
performAction(favoriteAction, codeViewerProvider, false);
|
performAction(favoriteAction, codeViewerProvider, false);
|
||||||
|
|
||||||
waitForSwing();
|
pressConflictingDataDialog("Yes");
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "Yes");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(dataType, data.getDataType());
|
assertEquals(dataType, data.getDataType());
|
||||||
|
@ -606,28 +549,20 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testFavoriteOnDefinedDtsAnswerNo() throws Exception {
|
public void testFavoriteOnDefinedDtsAnswerNo() throws Exception {
|
||||||
createData("004027d1", new ByteDataType());
|
createData("004027d1", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
final ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
final DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
// Set _person as a favorite.
|
// Set _person as a favorite
|
||||||
executeOnSwingWithoutBlocking(() -> dataTypeManager.setFavorite(dataType, true));
|
runSwing(() -> dataTypeManager.setFavorite(dataType, true), false);
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
// Choose favorite.
|
// Choose favorite.
|
||||||
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
DockingActionIf favoriteAction = getAction(dataPlugin, "Define _person");
|
||||||
assertNotNull(favoriteAction);
|
|
||||||
performAction(favoriteAction, codeViewerProvider, false);
|
performAction(favoriteAction, codeViewerProvider, false);
|
||||||
|
|
||||||
waitForSwing();
|
pressConflictingDataDialog("No");
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "No");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
|
@ -636,12 +571,9 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCycleOnDefaultDts() throws Exception {
|
public void testCycleOnDefaultDts() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
DockingActionIf chooseDataTypeAction = getAction(dataPlugin, "Choose Data Type");
|
showDataTypeChooser();
|
||||||
assertNotNull(chooseDataTypeAction);
|
|
||||||
performAction(chooseDataTypeAction, codeViewerProvider, false);
|
|
||||||
|
|
||||||
chooseInDialog("_person");
|
chooseInDialog("_person");
|
||||||
|
|
||||||
|
@ -655,8 +587,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testCycleOnUndefinedDts() throws Exception {
|
public void testCycleOnUndefinedDts() throws Exception {
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
|
@ -689,8 +620,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testCycleOnDefinedDts() throws Exception {
|
public void testCycleOnDefinedDts() throws Exception {
|
||||||
createData("004027d3", new ByteDataType());
|
createData("004027d3", new ByteDataType());
|
||||||
positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
|
@ -722,13 +652,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDragNDropOnDefaultDts() throws Exception {
|
public void testDragNDropOnDefaultDts() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(dataType, data.getDataType());
|
assertEquals(dataType, data.getDataType());
|
||||||
|
@ -738,13 +667,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testDragNDropOnUndefinedDts() throws Exception {
|
public void testDragNDropOnUndefinedDts() throws Exception {
|
||||||
createData("004027d2", new Undefined4DataType());
|
createData("004027d2", new Undefined4DataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(dataType, data.getDataType());
|
assertEquals(dataType, data.getDataType());
|
||||||
|
@ -754,19 +682,14 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testDragNDropYesOnDefinedDts() throws Exception {
|
public void testDragNDropYesOnDefinedDts() throws Exception {
|
||||||
createData("004027d3", new ByteDataType());
|
createData("004027d3", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
pressConflictingDataDialog("Yes");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "Yes");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(dataType, data.getDataType());
|
assertEquals(dataType, data.getDataType());
|
||||||
|
@ -776,19 +699,14 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
@Test
|
@Test
|
||||||
public void testDragNDropNoOnDefinedDts() throws Exception {
|
public void testDragNDropNoOnDefinedDts() throws Exception {
|
||||||
createData("004027d3", new ByteDataType());
|
createData("004027d3", new ByteDataType());
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027d0");
|
goTo("004027d0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||||
|
|
||||||
JDialog dialog = waitForJDialog(tool.getToolFrame(), "Data Conflict", 2000);
|
pressConflictingDataDialog("No");
|
||||||
assertNotNull(dialog);
|
|
||||||
|
|
||||||
pressButtonByText(dialog, "No");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027d0"));
|
Data data = program.getListing().getDataAt(addr("004027d0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
|
@ -797,13 +715,12 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDragNDropWhereDoesNotFit() throws Exception {
|
public void testDragNDropWhereDoesNotFit() throws Exception {
|
||||||
CodeViewerProvider codeViewerProvider = positionListingCursorAtAddress("004027e0");
|
goTo("004027e0");
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
ProgramDataTypeManager dataTypeManager = program.getDataTypeManager();
|
||||||
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
DataType dataType = dataTypeManager.getDataType(new CategoryPath("/"), "_person");
|
||||||
|
|
||||||
dragNDropDataTypeToCurrentBrowserLocation(codeViewerProvider, dataType);
|
dragNDropDataTypeToCurrentBrowserLocation(dataType);
|
||||||
|
|
||||||
Data data = program.getListing().getDataAt(addr("004027e0"));
|
Data data = program.getListing().getDataAt(addr("004027e0"));
|
||||||
assertEquals(DataType.DEFAULT, data.getDataType());
|
assertEquals(DataType.DEFAULT, data.getDataType());
|
||||||
|
@ -814,24 +731,36 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
// Private Helper Methods
|
// 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);
|
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) {
|
private DialogComponentProvider chooseInDialog(String typeName, String errorStatus) {
|
||||||
|
|
||||||
DataTypeSelectionDialog dialog = waitForDialogComponent(DataTypeSelectionDialog.class);
|
DataTypeSelectionDialog dialog = waitForDialogComponent(DataTypeSelectionDialog.class);
|
||||||
|
|
||||||
assertNotNull(dialog);
|
|
||||||
JTextField tf = findComponent(dialog, JTextField.class);
|
JTextField tf = findComponent(dialog, JTextField.class);
|
||||||
triggerText(tf, "_person");
|
triggerText(tf, "_person");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
@ -862,7 +791,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dragNDropDataTypeToCurrentBrowserLocation(
|
private void dragNDropDataTypeToCurrentBrowserLocation(
|
||||||
final CodeViewerProvider codeViewerProvider, final DataType dataType) {
|
final DataType dataType) {
|
||||||
executeOnSwingWithoutBlocking(() -> {
|
executeOnSwingWithoutBlocking(() -> {
|
||||||
// Simulate the drag-n-drop of the data type onto the location.
|
// Simulate the drag-n-drop of the data type onto the location.
|
||||||
ProgramLocation programLocation = codeViewerProvider.getLocation();
|
ProgramLocation programLocation = codeViewerProvider.getLocation();
|
||||||
|
@ -880,12 +809,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doAction(Plugin pluginForAction, String name, boolean waitForCompletion) {
|
private void doAction(Plugin pluginForAction, String name, boolean waitForCompletion) {
|
||||||
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
CodeViewerActionContext codeViewerContext = new CodeViewerActionContext(codeViewerProvider);
|
||||||
assertNotNull(codeBrowserPlugin);
|
|
||||||
CodeViewerProvider connectedProvider =
|
|
||||||
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowserPlugin);
|
|
||||||
assertNotNull(connectedProvider);
|
|
||||||
CodeViewerActionContext codeViewerContext = new CodeViewerActionContext(connectedProvider);
|
|
||||||
|
|
||||||
DockingActionIf action = getAction(pluginForAction, name);
|
DockingActionIf action = getAction(pluginForAction, name);
|
||||||
assertNotNull("Action was not found: " + name, action);
|
assertNotNull("Action was not found: " + name, action);
|
||||||
|
@ -894,28 +818,26 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
performAction(action, connectedProvider, waitForCompletion);
|
performAction(action, codeViewerProvider, waitForCompletion);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
t.printStackTrace();
|
failWithException("Action '" + name + "' failed: ", t);
|
||||||
Assert.fail("Action '" + name + "' failed: " + t.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodeViewerProvider positionListingCursorAtAddress(String addressString) {
|
private void goTo(String addressString) {
|
||||||
CodeBrowserPlugin codeBrowserPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
CodeBrowserPlugin codeBrowser = env.getPlugin(CodeBrowserPlugin.class);
|
||||||
assertNotNull(codeBrowserPlugin);
|
|
||||||
Address address = program.getAddressFactory().getAddress(addressString);
|
Address address = program.getAddressFactory().getAddress(addressString);
|
||||||
codeBrowserPlugin.goToField(address, "Address", 0, 0);
|
codeBrowser.goToField(address, "Address", 0, 0);
|
||||||
assertEquals(addressString, codeBrowserPlugin.getCurrentAddress().toString());
|
assertEquals(addressString, codeBrowser.getCurrentAddress().toString());
|
||||||
CodeViewerProvider connectedProvider =
|
CodeViewerProvider connectedProvider =
|
||||||
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowserPlugin);
|
(CodeViewerProvider) getInstanceField("connectedProvider", codeBrowser);
|
||||||
assertNotNull(connectedProvider);
|
assertNotNull(connectedProvider);
|
||||||
ListingPanel listingPanel =
|
ListingPanel listingPanel =
|
||||||
(ListingPanel) getInstanceField("listingPanel", connectedProvider);
|
(ListingPanel) getInstanceField("listingPanel", connectedProvider);
|
||||||
assertNotNull(listingPanel);
|
assertNotNull(listingPanel);
|
||||||
return connectedProvider;
|
waitForSwing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createData(String addressString, DataType dataType) throws Exception {
|
private void createData(String addressString, DataType dataType) throws Exception {
|
||||||
|
@ -928,7 +850,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, success);
|
program.endTransaction(transactionID, success);
|
||||||
}
|
}
|
||||||
waitForProgram();
|
waitForProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createCode(String addressString, int len) throws Exception {
|
private void createCode(String addressString, int len) throws Exception {
|
||||||
|
@ -945,7 +867,7 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
finally {
|
finally {
|
||||||
program.endTransaction(transactionID, success);
|
program.endTransaction(transactionID, success);
|
||||||
}
|
}
|
||||||
waitForProgram();
|
waitForProgram(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Address addr(String addressString) {
|
private Address addr(String addressString) {
|
||||||
|
@ -955,10 +877,4 @@ public class ApplyDataTypeToBrowserTest extends AbstractGhidraHeadedIntegrationT
|
||||||
private void waitForTree() {
|
private void waitForTree() {
|
||||||
waitForTree(tree);
|
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.WindowUtilities;
|
||||||
import generic.util.image.ImageUtils;
|
import generic.util.image.ImageUtils;
|
||||||
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
|
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.DataTypeArchiveGTree;
|
||||||
import ghidra.app.plugin.core.datamgr.tree.DataTypeNode;
|
import ghidra.app.plugin.core.datamgr.tree.DataTypeNode;
|
||||||
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
import ghidra.app.plugin.core.datamgr.util.DataTypeChooserDialog;
|
||||||
|
@ -1175,7 +1176,7 @@ public class DataTypeSelectionDialogTest extends AbstractGhidraHeadedIntegration
|
||||||
|
|
||||||
JPanel editorPanel = new JPanel(new BorderLayout());
|
JPanel editorPanel = new JPanel(new BorderLayout());
|
||||||
DataTypeSelectionEditor editor =
|
DataTypeSelectionEditor editor =
|
||||||
new DataTypeSelectionEditor(tool, -1, AllowedDataTypes.ALL);
|
new DataTypeSelectionEditor(tool, AllowedDataTypes.ALL);
|
||||||
editor.setPreferredDataTypeManager(program.getDataTypeManager());
|
editor.setPreferredDataTypeManager(program.getDataTypeManager());
|
||||||
|
|
||||||
editorPanel.add(panelUpdateField, BorderLayout.SOUTH);
|
editorPanel.add(panelUpdateField, BorderLayout.SOUTH);
|
||||||
|
|
|
@ -45,14 +45,6 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
||||||
private Listing listing;
|
private Listing listing;
|
||||||
private ProgramBuilder builder;
|
private ProgramBuilder builder;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for CreateDataCmdTest.
|
|
||||||
* @param arg0
|
|
||||||
*/
|
|
||||||
public CreateDataCmdTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
program = buildProgram();
|
program = buildProgram();
|
||||||
|
@ -637,8 +629,9 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
||||||
cmd.applyTo(program);
|
cmd.applyTo(program);
|
||||||
|
|
||||||
// Add external reference from pointer
|
// Add external reference from pointer
|
||||||
program.getReferenceManager().addExternalReference(addr, "OtherFile", "ExtLabel", null,
|
program.getReferenceManager()
|
||||||
SourceType.USER_DEFINED, 0, RefType.DATA);
|
.addExternalReference(addr, "OtherFile", "ExtLabel", null,
|
||||||
|
SourceType.USER_DEFINED, 0, RefType.DATA);
|
||||||
|
|
||||||
// Undefined* becomes Byte*
|
// Undefined* becomes Byte*
|
||||||
cmd = new CreateDataCmd(addr, false, true, new ByteDataType());
|
cmd = new CreateDataCmd(addr, false, true, new ByteDataType());
|
||||||
|
@ -724,7 +717,8 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
||||||
assertEquals(10, dt.getLength());
|
assertEquals(10, dt.getLength());
|
||||||
|
|
||||||
// Byte[] becomes Byte
|
// 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);
|
cmd.applyTo(program);
|
||||||
|
|
||||||
d = listing.getDataAt(addr);
|
d = listing.getDataAt(addr);
|
||||||
|
@ -792,7 +786,8 @@ public class CreateDataCmdTest extends AbstractGenericTest {
|
||||||
assertEquals(10, dt.getLength());
|
assertEquals(10, dt.getLength());
|
||||||
|
|
||||||
// struct becomes Byte
|
// 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);
|
cmd.applyTo(program);
|
||||||
|
|
||||||
d = listing.getDataAt(addr);
|
d = listing.getDataAt(addr);
|
||||||
|
|
|
@ -557,8 +557,7 @@ class DetachedWindowNode extends WindowNode {
|
||||||
*/
|
*/
|
||||||
public void setStatusText(String text) {
|
public void setStatusText(String text) {
|
||||||
if (statusBar != null) {
|
if (statusBar != null) {
|
||||||
boolean isActive = window == null ? false : window.isActive();
|
statusBar.setStatusText(text);
|
||||||
statusBar.setStatusText(text, isActive);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -576,7 +576,7 @@ class RootNode extends WindowNode {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
statusBar.setStatusText(text, getMainWindow().isActive());
|
statusBar.setStatusText(text);
|
||||||
|
|
||||||
Iterator<DetachedWindowNode> iter = detachedWindows.iterator();
|
Iterator<DetachedWindowNode> iter = detachedWindows.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.swing.*;
|
||||||
import javax.swing.Timer;
|
import javax.swing.Timer;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jdesktop.animation.timing.Animator;
|
import org.jdesktop.animation.timing.Animator;
|
||||||
|
|
||||||
import docking.util.AnimationUtils;
|
import docking.util.AnimationUtils;
|
||||||
|
@ -153,14 +154,40 @@ public class StatusBar extends JPanel {
|
||||||
statusAreaPanel.remove(c.getParent());
|
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) {
|
if (text == null) {
|
||||||
// not sure what do do here, do nothing for now so that the previous message
|
// do nothing for now so that the previous message stays around
|
||||||
// stays around
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,11 +198,12 @@ public class StatusBar extends JPanel {
|
||||||
statusLabel.setToolTipText(getToolTipText());
|
statusLabel.setToolTipText(getToolTipText());
|
||||||
statusLabel.setForeground(Color.BLACK);
|
statusLabel.setForeground(Color.BLACK);
|
||||||
|
|
||||||
if (!isActiveWindow) {
|
if (StringUtils.isBlank(updatedText)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updatedText.trim().isEmpty()) {
|
Window window = WindowUtilities.windowForComponent(statusLabel);
|
||||||
|
if (!window.isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,6 +496,13 @@ public class AnimationUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle startBounds = component.getBounds();
|
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 =
|
Point relativeStartCenter =
|
||||||
new Point((int) startBounds.getCenterX(), (int) startBounds.getCenterY());
|
new Point((int) startBounds.getCenterX(), (int) startBounds.getCenterY());
|
||||||
return SwingUtilities.convertPoint(component.getParent(), relativeStartCenter,
|
return SwingUtilities.convertPoint(component.getParent(), relativeStartCenter,
|
||||||
|
@ -556,11 +563,20 @@ public class AnimationUtils {
|
||||||
int scaledWidth = (int) (defaultBounds.width * percentComplete);
|
int scaledWidth = (int) (defaultBounds.width * percentComplete);
|
||||||
int scaledHeight = (int) (defaultBounds.height * 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
|
// 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
|
// the display; at 0% we want to be at our default location
|
||||||
//
|
//
|
||||||
g2d.drawImage(image, (int) currentX, (int) currentY, scaledWidth, scaledHeight, null);
|
g2d.drawImage(image, (int) currentX, (int) currentY, scaledWidth, scaledHeight, null);
|
||||||
|
|
||||||
|
g2d.setComposite(originalComposite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package docking;
|
package docking;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
@ -38,15 +38,6 @@ public class StatusBarTest extends AbstractDockingTest {
|
||||||
private StatusBar statusBar;
|
private StatusBar statusBar;
|
||||||
private JFrame testFrame;
|
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
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
@ -113,78 +104,50 @@ public class StatusBarTest extends AbstractDockingTest {
|
||||||
final JLabel label2 = new GDLabel("Test Label 2");
|
final JLabel label2 = new GDLabel("Test Label 2");
|
||||||
|
|
||||||
// normal add/remove operations
|
// normal add/remove operations
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> {
|
||||||
@Override
|
statusBar.addStatusItem(label1, true, true);
|
||||||
public void run() {
|
statusBar.addStatusItem(label2, true, true);
|
||||||
statusBar.addStatusItem(label1, true, true);
|
|
||||||
statusBar.addStatusItem(label2, true, true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> {
|
||||||
@Override
|
statusBar.removeStatusItem(label1);
|
||||||
public void run() {
|
statusBar.removeStatusItem(label2);
|
||||||
statusBar.removeStatusItem(label1);
|
|
||||||
statusBar.removeStatusItem(label2);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// method call variations
|
// method call variations
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> {
|
||||||
@Override
|
statusBar.addStatusItem(label1, false, true);
|
||||||
public void run() {
|
statusBar.addStatusItem(label2, true, false);
|
||||||
statusBar.addStatusItem(label1, false, true);
|
|
||||||
statusBar.addStatusItem(label2, true, false);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> {
|
||||||
@Override
|
statusBar.removeStatusItem(label1);
|
||||||
public void run() {
|
statusBar.removeStatusItem(label2);
|
||||||
statusBar.removeStatusItem(label1);
|
|
||||||
statusBar.removeStatusItem(label2);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// repeat adding
|
// repeat adding
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> {
|
||||||
@Override
|
statusBar.addStatusItem(label1, true, true);
|
||||||
public void run() {
|
statusBar.addStatusItem(label1, true, true);
|
||||||
statusBar.addStatusItem(label1, true, true);
|
|
||||||
statusBar.addStatusItem(label1, true, true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// removing non-existent elements
|
// removing non-existent elements
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> statusBar.removeStatusItem(label2));
|
||||||
@Override
|
|
||||||
public void run() {
|
runSwing(() -> {
|
||||||
statusBar.removeStatusItem(label2);
|
try {
|
||||||
|
statusBar.removeStatusItem(new GLabel("Test Label 3"));
|
||||||
|
|
||||||
|
Assert.fail("Did not receive an expected NullPointerException.");
|
||||||
}
|
}
|
||||||
});
|
catch (NullPointerException npe) {
|
||||||
|
// expected, caused by a null parent
|
||||||
runSwing(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
statusBar.removeStatusItem(new GLabel("Test Label 3"));
|
|
||||||
|
|
||||||
Assert.fail("Did not receive an expected NullPointerException.");
|
|
||||||
}
|
|
||||||
catch (NullPointerException npe) {
|
|
||||||
// expected, caused by a null parent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setStatusText(final String text) {
|
private void setStatusText(final String text) {
|
||||||
runSwing(new Runnable() {
|
runSwing(() -> statusBar.setStatusText(text));
|
||||||
@Override
|
waitForSwing();
|
||||||
public void run() {
|
|
||||||
statusBar.setStatusText(text, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,8 @@ import ghidra.util.exception.InvalidInputException;
|
||||||
|
|
||||||
public final class DataUtilities {
|
public final class DataUtilities {
|
||||||
|
|
||||||
//private final static Set<Character> VALID_DATA_TYPE_NAME_SET = SystemUtilities.makeSet(FileSystem.DASH_CHAR, '_',' ', '.');
|
|
||||||
|
|
||||||
private DataUtilities() {
|
private DataUtilities() {
|
||||||
|
// utilities class
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,95 +87,58 @@ public final class DataUtilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create data where existing data may already exist.
|
* 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 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 length data length (used only for Dynamic newDataType which has canSpecifyLength()==true)
|
||||||
* @param stackPointers see {@link #reconcileAppliedDataType(DataType, DataType, boolean)}
|
* @param stackPointers see {@link #reconcileAppliedDataType(DataType, DataType, boolean)}
|
||||||
* @param clearMode see CreateDataMode
|
* @param clearMode see CreateDataMode
|
||||||
* @return new data created
|
* @return new data created
|
||||||
* @throws CodeUnitInsertionException if data creation failed
|
* @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 {
|
boolean stackPointers, ClearDataMode clearMode) throws CodeUnitInsertionException {
|
||||||
|
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
ReferenceManager refMgr = program.getReferenceManager();
|
ReferenceManager refMgr = program.getReferenceManager();
|
||||||
|
|
||||||
Data data = listing.getDataAt(addr);
|
Data data = getData(addr, clearMode, listing);
|
||||||
DataType existingDT = null;
|
int existingLength = addr.getAddressSpace().getAddressableUnitSize();
|
||||||
|
DataType existingType = data.getDataType();
|
||||||
Reference extRef = null;
|
Reference extRef = null;
|
||||||
int existingDataLen = addr.getAddressSpace().getAddressableUnitSize();
|
if (!isParentData(data, addr)) {
|
||||||
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 (data.isDefined() && newDataType.isEquivalent(existingDT)) {
|
existingLength = data.getLength();
|
||||||
|
if (data.isDefined() && newType.isEquivalent(existingType)) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stackPointers && clearMode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_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);
|
throw new CodeUnitInsertionException("Could not create Data at address " + addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This can probably be eliminated
|
||||||
// Check for external reference on pointer
|
// Check for external reference on pointer
|
||||||
if ((stackPointers || newDataType instanceof Pointer) &&
|
extRef =
|
||||||
existingDT instanceof Pointer) {
|
getExternalPointerReference(addr, newType, stackPointers, refMgr, existingType);
|
||||||
// TODO: This can probably be eliminated
|
|
||||||
Reference[] refs = refMgr.getReferencesFrom(addr);
|
|
||||||
for (Reference ref : refs) {
|
|
||||||
if (ref.getOperandIndex() == 0 && ref.isExternalReference()) {
|
|
||||||
extRef = ref;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newDataType = newDataType.clone(program.getDataTypeManager());
|
newType = newType.clone(program.getDataTypeManager());
|
||||||
newDataType = reconcileAppliedDataType(existingDT, newDataType, stackPointers);
|
newType = reconcileAppliedDataType(existingType, newType, stackPointers);
|
||||||
|
|
||||||
DataType realType = newDataType;
|
DataType realType = newType;
|
||||||
if (newDataType instanceof TypeDef) {
|
if (newType instanceof TypeDef) {
|
||||||
realType = ((TypeDef) newDataType).getBaseDataType();
|
realType = ((TypeDef) newType).getBaseDataType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// is the datatype already there?
|
// is the datatype already there?
|
||||||
if (!(realType instanceof Dynamic) && !(realType instanceof FactoryDataType) &&
|
if (isExistingNonDynamicType(realType, newType, existingType)) {
|
||||||
newDataType.equals(existingDT)) {
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBuffer memBuf = new DumbMemBufferImpl(program.getMemory(), addr);
|
DataTypeInstance dti = getDtInstance(program, addr, newType, length, realType);
|
||||||
DataTypeInstance dti;
|
if (stackPointers && existingType instanceof Pointer && newType instanceof Pointer) {
|
||||||
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) {
|
|
||||||
listing.clearCodeUnits(addr, addr, false);
|
listing.clearCodeUnits(addr, addr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,71 +152,200 @@ public final class DataUtilities {
|
||||||
listing.clearCodeUnits(addr, addr, false);
|
listing.clearCodeUnits(addr, addr, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
checkEnoughSpace(program, addr, existingDataLen, dti, clearMode);
|
checkEnoughSpace(program, addr, existingLength, dti, clearMode);
|
||||||
}
|
}
|
||||||
newData = listing.createData(addr, dti.getDataType(), dti.getLength());
|
newData = listing.createData(addr, dti.getDataType(), dti.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this was a pointer and had an external reference, put it back!
|
restoreReference(newType, refMgr, extRef);
|
||||||
if ((newDataType instanceof Pointer) && extRef != null) {
|
|
||||||
ExternalLocation extLoc = ((ExternalReference) extRef).getExternalLocation();
|
return newData;
|
||||||
try {
|
}
|
||||||
refMgr.addExternalReference(extRef.getFromAddress(), 0, extLoc, extRef.getSource(),
|
|
||||||
extRef.getReferenceType());
|
private static boolean isParentData(Data data, Address addr) {
|
||||||
}
|
return !data.getAddress().equals(addr);
|
||||||
catch (InvalidInputException e) {
|
}
|
||||||
throw new AssertException(e);
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newData;
|
|
||||||
|
// 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!
|
||||||
|
ExternalLocation extLoc = ((ExternalReference) ref).getExternalLocation();
|
||||||
|
Address fromAddress = ref.getFromAddress();
|
||||||
|
SourceType source = ref.getSource();
|
||||||
|
RefType type = ref.getReferenceType();
|
||||||
|
try {
|
||||||
|
refMgr.addExternalReference(fromAddress, 0, extLoc, source, type);
|
||||||
|
}
|
||||||
|
catch (InvalidInputException e) {
|
||||||
|
throw new AssertException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
private static void checkEnoughSpace(Program program, Address addr, int existingDataLen,
|
||||||
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
|
DataTypeInstance dti, ClearDataMode mode) throws CodeUnitInsertionException {
|
||||||
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
|
// NOTE: method not invoked when clearMode == ClearDataMode.CLEAR_SINGLE_DATA
|
||||||
Listing listing = program.getListing();
|
Listing listing = program.getListing();
|
||||||
|
Address end = null;
|
||||||
|
Address newEnd = null;
|
||||||
try {
|
try {
|
||||||
Address end = addr.addNoWrap(existingDataLen - 1);
|
end = addr.addNoWrap(existingDataLen - 1);
|
||||||
Address newEnd = addr.addNoWrap(dti.getLength() - 1);
|
newEnd = addr.addNoWrap(dti.getLength() - 1);
|
||||||
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 (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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) {
|
|
||||||
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
|
||||||
dti.getDataType().getDisplayName());
|
|
||||||
}
|
|
||||||
listing.clearCodeUnits(addr, newEnd, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
listing.clearCodeUnits(addr, addr, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (AddressOverflowException e) {
|
catch (AddressOverflowException e) {
|
||||||
throw new CodeUnitInsertionException(
|
throw new CodeUnitInsertionException(
|
||||||
"Not enough space to create DataType " + dti.getDataType().getDisplayName());
|
"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) {
|
||||||
|
listing.clearCodeUnits(addr, addr, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == ClearDataMode.CLEAR_ALL_UNDEFINED_CONFLICT_DATA &&
|
||||||
|
Undefined.isUndefined(definedData.getDataType())) {
|
||||||
|
checkForDefinedData(dti, listing, newEnd, definedData.getMaxAddress());
|
||||||
|
}
|
||||||
|
else if (mode != ClearDataMode.CLEAR_ALL_CONFLICT_DATA) {
|
||||||
|
throw new CodeUnitInsertionException("Not enough space to create DataType " +
|
||||||
|
dti.getDataType().getDisplayName());
|
||||||
|
}
|
||||||
|
listing.clearCodeUnits(addr, newEnd, 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());
|
||||||
|
}
|
||||||
|
end = definedData.getMaxAddress();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DataType stackPointers(Pointer pointer, DataType dataType) {
|
private static DataType stackPointers(Pointer pointer, DataType dataType) {
|
||||||
|
@ -355,7 +446,10 @@ public final class DataUtilities {
|
||||||
* Get the data for the given address.
|
* Get the data for the given address.
|
||||||
* <P>
|
* <P>
|
||||||
* This will return a Data if and only if there is data that starts at the given address.
|
* 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) {
|
public static Data getDataAtAddress(Program program, Address address) {
|
||||||
if (address == null) {
|
if (address == null) {
|
||||||
|
@ -417,9 +511,9 @@ public final class DataUtilities {
|
||||||
* Determine if the specified addr corresponds to an undefined data location
|
* Determine if the specified addr corresponds to an undefined data location
|
||||||
* where both undefined code units and defined data which has an Undefined
|
* where both undefined code units and defined data which has an Undefined
|
||||||
* data type is considered to be undefined.
|
* data type is considered to be undefined.
|
||||||
* @param program
|
* @param program the program
|
||||||
* @param addr
|
* @param addr the data address
|
||||||
* @return
|
* @return true if the data is undefined
|
||||||
*/
|
*/
|
||||||
public static boolean isUndefinedData(Program program, Address addr) {
|
public static boolean isUndefinedData(Program program, Address addr) {
|
||||||
Data data = program.getListing().getDataAt(addr);
|
Data data = program.getListing().getDataAt(addr);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue