mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GT-2999: fixed how comparison action is set to SHARED
This commit is contained in:
parent
ec7773b464
commit
496408f2b7
23 changed files with 264 additions and 217 deletions
|
@ -15,7 +15,7 @@
|
||||||
functions in a simple side-by-side panel. </P>
|
functions in a simple side-by-side panel. </P>
|
||||||
|
|
||||||
<P>To begin, select a function (or multiple functions) from the listing or
|
<P>To begin, select a function (or multiple functions) from the listing or
|
||||||
the function table. Then right-click and select the <b>Compare Selected
|
the <A HREF="help/topics/FunctionWindowPlugin/function_window.htm">function table</a>. Then right-click and select the <b>Compare Selected
|
||||||
Functions</b> option.</P>
|
Functions</b> option.</P>
|
||||||
|
|
||||||
<P><A name="Dual_Listing"></A>A new function comparison window will appear (subsequent
|
<P><A name="Dual_Listing"></A>A new function comparison window will appear (subsequent
|
||||||
|
|
|
@ -142,6 +142,17 @@ class FunctionComparisonData {
|
||||||
return function != null;
|
return function != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this class holds no function, data or address set
|
||||||
|
* information
|
||||||
|
*
|
||||||
|
* @return true if this class holds no function, data or address set
|
||||||
|
* information
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return function == null && data == null && addressSet == null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets all fields in this model to a nominal state
|
* Resets all fields in this model to a nominal state
|
||||||
*/
|
*/
|
||||||
|
@ -151,4 +162,23 @@ class FunctionComparisonData {
|
||||||
this.addressSet = new AddressSet();
|
this.addressSet = new AddressSet();
|
||||||
this.program = null;
|
this.program = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
String str = "";
|
||||||
|
|
||||||
|
if (function != null) {
|
||||||
|
str = function.getName();
|
||||||
|
}
|
||||||
|
else if (data != null) {
|
||||||
|
str = data.getAddress().toString();
|
||||||
|
}
|
||||||
|
else if (addressSet != null) {
|
||||||
|
str = addressSet.toString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,21 +167,6 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the functions in the left/right panels if they are in the
|
|
||||||
* given set
|
|
||||||
*
|
|
||||||
* @param functions the functions to remove
|
|
||||||
*/
|
|
||||||
public void removeFunctions(Set<Function> functions) {
|
|
||||||
if (functions.contains(leftComparisonData.getFunction())) {
|
|
||||||
setLeftFunction(null);
|
|
||||||
}
|
|
||||||
if (functions.contains(rightComparisonData.getFunction())) {
|
|
||||||
setRightFunction(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actions for this FunctionComparisonPanel
|
* Get the actions for this FunctionComparisonPanel
|
||||||
*
|
*
|
||||||
|
@ -204,16 +189,16 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
Data rightData = rightComparisonData.getData();
|
Data rightData = rightComparisonData.getData();
|
||||||
|
|
||||||
if (leftFunc != null && rightFunc != null) {
|
if (leftFunc != null && rightFunc != null) {
|
||||||
return "Function comparison of " + leftFunc.getName(true) + " & " +
|
return leftFunc.getName(true) + " & " +
|
||||||
rightFunc.getName(true);
|
rightFunc.getName(true);
|
||||||
}
|
}
|
||||||
if (leftData != null && rightData != null) {
|
if (leftData != null && rightData != null) {
|
||||||
return "Function comparison of " + leftData.getDataType().getName() + " & " +
|
return leftData.getDataType().getName() + " & " +
|
||||||
rightData.getDataType().getName();
|
rightData.getDataType().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise give a simple description for address sets
|
// Otherwise give a simple description for address sets
|
||||||
return "Function comparison";
|
return "Nothing selected";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -233,20 +218,20 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the comparison window has no functions to display in
|
* Returns true if the comparison window has no information to display in
|
||||||
* either the left or right panel
|
* either the left or right panel
|
||||||
*
|
*
|
||||||
* @return true if the comparison window has no functions to display
|
* @return true if the comparison window has no information to display
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return getLeftFunction() == null || getRightFunction() == null;
|
return leftComparisonData.isEmpty() || rightComparisonData.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the ListingCodeComparisonPanel being displayed by this panel
|
* Gets the ListingCodeComparisonPanel being displayed by this panel
|
||||||
* if one exists
|
* if one exists
|
||||||
*
|
*
|
||||||
* @return the ListingCodeComparisonPanel or null
|
* @return the comparison panel or null
|
||||||
*/
|
*/
|
||||||
public ListingCodeComparisonPanel getDualListingPanel() {
|
public ListingCodeComparisonPanel getDualListingPanel() {
|
||||||
for (CodeComparisonPanel<? extends FieldPanelCoordinator> codeComparisonPanel : codeComparisonPanels) {
|
for (CodeComparisonPanel<? extends FieldPanelCoordinator> codeComparisonPanel : codeComparisonPanels) {
|
||||||
|
@ -258,9 +243,6 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked when a new tab on the panel has been selected
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void stateChanged(ChangeEvent e) {
|
public void stateChanged(ChangeEvent e) {
|
||||||
tabChanged();
|
tabChanged();
|
||||||
|
@ -388,6 +370,24 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the comparison data object for the left panel
|
||||||
|
*
|
||||||
|
* @return the comparison data object for the left panel
|
||||||
|
*/
|
||||||
|
public FunctionComparisonData getLeftComparisonData() {
|
||||||
|
return leftComparisonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the comparison data object for the right panel
|
||||||
|
*
|
||||||
|
* @return the comparison data object for the right panel
|
||||||
|
*/
|
||||||
|
public FunctionComparisonData getRightComparisonData() {
|
||||||
|
return rightComparisonData;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the function currently displayed in the left side of this panel
|
* Gets the function currently displayed in the left side of this panel
|
||||||
*
|
*
|
||||||
|
@ -634,25 +634,6 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
toggleScrollLockAction = new ToggleScrollLockAction();
|
toggleScrollLockAction = new ToggleScrollLockAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Comparator that lets CodeComparisonPanels be sorted based on their
|
|
||||||
* title names
|
|
||||||
*/
|
|
||||||
private class CodeComparisonPanelComparator
|
|
||||||
implements Comparator<CodeComparisonPanel<? extends FieldPanelCoordinator>> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compare(CodeComparisonPanel<? extends FieldPanelCoordinator> o1,
|
|
||||||
CodeComparisonPanel<? extends FieldPanelCoordinator> o2) {
|
|
||||||
if (o1 == o2) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
String title1 = o1.getTitle();
|
|
||||||
String title2 = o2.getTitle();
|
|
||||||
return title1.compareTo(title2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action that sets the scrolling state of the comparison panels
|
* Action that sets the scrolling state of the comparison panels
|
||||||
*/
|
*/
|
||||||
|
@ -716,10 +697,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the list of code comparison panels so they display in the same order
|
codeComparisonPanels.sort((p1, p2) -> p1.getTitle().compareTo(p2.getTitle()));
|
||||||
// each time for the user.
|
|
||||||
CodeComparisonPanelComparator comparator = new CodeComparisonPanelComparator();
|
|
||||||
codeComparisonPanels.sort(comparator);
|
|
||||||
}
|
}
|
||||||
return codeComparisonPanels;
|
return codeComparisonPanels;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,8 @@ public class FunctionComparisonPlugin extends ProgramPlugin
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init() {
|
protected void init() {
|
||||||
CompareFunctionsAction compareFunctionsAction = new CompareFunctionsFromListingAction(tool);
|
CompareFunctionsAction compareFunctionsAction =
|
||||||
|
new CompareFunctionsFromListingAction(tool, getName());
|
||||||
tool.addAction(compareFunctionsAction);
|
tool.addAction(compareFunctionsAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +133,12 @@ public class FunctionComparisonPlugin extends ProgramPlugin
|
||||||
functionComparisonManager.addProviderListener(listener);
|
functionComparisonManager.addProviderListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeFunctionComparisonProviderListener(
|
||||||
|
ComponentProviderActivationListener listener) {
|
||||||
|
functionComparisonManager.removeProviderListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeFunction(Function function) {
|
public void removeFunction(Function function) {
|
||||||
functionComparisonManager.removeFunction(function);
|
functionComparisonManager.removeFunction(function);
|
||||||
|
|
|
@ -125,7 +125,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter
|
||||||
public void modelChanged(List<FunctionComparison> model) {
|
public void modelChanged(List<FunctionComparison> model) {
|
||||||
this.model.setComparisons(model);
|
this.model.setComparisons(model);
|
||||||
functionComparisonPanel.reload();
|
functionComparisonPanel.reload();
|
||||||
setTabText(functionComparisonPanel);
|
setTabText(functionComparisonPanel.getDescription());
|
||||||
closeIfEmpty();
|
closeIfEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,25 +225,12 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter
|
||||||
functionComparisonPanel.writeConfigState(getName(), saveState);
|
functionComparisonPanel.writeConfigState(getName(), saveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the text that is displayed on the tab for this provider
|
|
||||||
*
|
|
||||||
* @param comparisonPanel the function comparison panel for this provider
|
|
||||||
*/
|
|
||||||
public void setTabText(FunctionComparisonPanel comparisonPanel) {
|
|
||||||
Function leftFunction = comparisonPanel.getLeftFunction();
|
|
||||||
Function rightFunction = comparisonPanel.getRightFunction();
|
|
||||||
String tabText = (leftFunction == null && rightFunction == null) ? "No Functions Yet"
|
|
||||||
: getTabText(leftFunction, rightFunction);
|
|
||||||
setTabText(tabText);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform initialization for this provider and its panel
|
* Perform initialization for this provider and its panel
|
||||||
*/
|
*/
|
||||||
protected void initFunctionComparisonPanel() {
|
protected void initFunctionComparisonPanel() {
|
||||||
setTransient();
|
setTransient();
|
||||||
setTabText(functionComparisonPanel);
|
setTabText(functionComparisonPanel.getDescription());
|
||||||
addSpecificCodeComparisonActions();
|
addSpecificCodeComparisonActions();
|
||||||
tool.addPopupActionProvider(this);
|
tool.addPopupActionProvider(this);
|
||||||
setHelpLocation(new HelpLocation(HELP_TOPIC, "Function Comparison"));
|
setHelpLocation(new HelpLocation(HELP_TOPIC, "Function Comparison"));
|
||||||
|
@ -267,19 +254,6 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the text that should be displayed in the tab, given the two
|
|
||||||
* left/right functions
|
|
||||||
*
|
|
||||||
* @param leftFunction
|
|
||||||
* @param rightFunction
|
|
||||||
* @return the tab text
|
|
||||||
*/
|
|
||||||
private String getTabText(Function leftFunction, Function rightFunction) {
|
|
||||||
return ((leftFunction != null) ? leftFunction.getName() : "none") + " & " +
|
|
||||||
((rightFunction != null) ? rightFunction.getName() : "none");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets actions specific to the code comparison panel and adds them to this
|
* Gets actions specific to the code comparison panel and adds them to this
|
||||||
* provider
|
* provider
|
||||||
|
|
|
@ -159,6 +159,16 @@ public class FunctionComparisonProviderManager implements FunctionComparisonProv
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a subscriber who no longer wishes to receive provider activation
|
||||||
|
* events
|
||||||
|
*
|
||||||
|
* @param listener the subscriber to remove
|
||||||
|
*/
|
||||||
|
public void removeProviderListener(ComponentProviderActivationListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes all the comparison providers that contain a function from
|
* Closes all the comparison providers that contain a function from
|
||||||
* the given program
|
* the given program
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
* @param provider the comparison provider associated with this panel
|
* @param provider the comparison provider associated with this panel
|
||||||
* @param tool the active plugin tool
|
* @param tool the active plugin tool
|
||||||
*/
|
*/
|
||||||
public MultiFunctionComparisonPanel(FunctionComparisonProvider provider,
|
public MultiFunctionComparisonPanel(MultiFunctionComparisonProvider provider,
|
||||||
PluginTool tool) {
|
PluginTool tool) {
|
||||||
super(provider, tool, null, null);
|
super(provider, tool, null, null);
|
||||||
|
|
||||||
|
@ -81,16 +81,6 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
getComparisonPanels().forEach(p -> p.setShowTitles(false));
|
getComparisonPanels().forEach(p -> p.setShowTitles(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the given functions from the comparison panel (both the
|
|
||||||
* source and target lists) (the default for this method is to only clear
|
|
||||||
* out the functions visible in the left/right panels)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void removeFunctions(Set<Function> functions) {
|
|
||||||
((MultiFunctionComparisonProvider) provider).removeFunctions(functions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears out the source and targets lists and reloads them to
|
* Clears out the source and targets lists and reloads them to
|
||||||
* ensure that they reflect the current state of the data model. Any
|
* ensure that they reflect the current state of the data model. Any
|
||||||
|
@ -105,9 +95,7 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
reloadTargetList(selectedSource);
|
reloadTargetList(selectedSource);
|
||||||
loadFunctions(selectedSource, (Function) targetFunctionsCBModel.getSelectedItem());
|
loadFunctions(selectedSource, (Function) targetFunctionsCBModel.getSelectedItem());
|
||||||
|
|
||||||
((FunctionComparisonProvider) provider).setTabText(this);
|
updateTabText();
|
||||||
((FunctionComparisonProvider) provider)
|
|
||||||
.setTitle(((FunctionComparisonProvider) provider).getTabText());
|
|
||||||
|
|
||||||
// Fire a notification to update the UI state; without this the
|
// Fire a notification to update the UI state; without this the
|
||||||
// actions would not be properly enabled/disabled
|
// actions would not be properly enabled/disabled
|
||||||
|
@ -181,6 +169,16 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
restoreSelection(targetFunctionsCB, selection);
|
restoreSelection(targetFunctionsCB, selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the text on the current tab to match whatever is displayed in the
|
||||||
|
* comparison panels
|
||||||
|
*/
|
||||||
|
private void updateTabText() {
|
||||||
|
String tabText = getDescription();
|
||||||
|
provider.setTabText(tabText);
|
||||||
|
provider.setTitle(tabText);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a given function to be the selected item in a given combo
|
* Sets a given function to be the selected item in a given combo
|
||||||
* box. If the function isn't found, the first item in the box is
|
* box. If the function isn't found, the first item in the box is
|
||||||
|
@ -238,6 +236,8 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
// to load the targets associated with it
|
// to load the targets associated with it
|
||||||
reloadTargetList((Function) sourceFunctionsCBModel.getSelectedItem());
|
reloadTargetList((Function) sourceFunctionsCBModel.getSelectedItem());
|
||||||
|
|
||||||
|
updateTabText();
|
||||||
|
|
||||||
// Fire a notification to update the UI state; without this the
|
// Fire a notification to update the UI state; without this the
|
||||||
// actions would not be properly enabled/disabled
|
// actions would not be properly enabled/disabled
|
||||||
tool.contextChanged(provider);
|
tool.contextChanged(provider);
|
||||||
|
@ -275,6 +275,8 @@ public class MultiFunctionComparisonPanel extends FunctionComparisonPanel {
|
||||||
Function selected = (Function) targetFunctionsCBModel.getSelectedItem();
|
Function selected = (Function) targetFunctionsCBModel.getSelectedItem();
|
||||||
loadFunctions((Function) sourceFunctionsCBModel.getSelectedItem(), selected);
|
loadFunctions((Function) sourceFunctionsCBModel.getSelectedItem(), selected);
|
||||||
|
|
||||||
|
updateTabText();
|
||||||
|
|
||||||
// Fire a notification to update the UI state; without this the
|
// Fire a notification to update the UI state; without this the
|
||||||
// actions would not be properly enabled/disabled
|
// actions would not be properly enabled/disabled
|
||||||
tool.contextChanged(provider);
|
tool.contextChanged(provider);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functioncompare.actions;
|
package ghidra.app.plugin.core.functioncompare.actions;
|
||||||
|
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
@ -57,9 +58,10 @@ public abstract class CompareFunctionsAction extends DockingAction {
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param tool the plugin tool
|
* @param tool the plugin tool
|
||||||
|
* @param owner the action owner (usually the plugin name)
|
||||||
*/
|
*/
|
||||||
public CompareFunctionsAction(PluginTool tool) {
|
public CompareFunctionsAction(PluginTool tool, String owner) {
|
||||||
super("Compare Functions", tool.getName());
|
super("Compare Functions", owner, KeyBindingType.SHARED);
|
||||||
this.comparisonService = tool.getService(FunctionComparisonService.class);
|
this.comparisonService = tool.getService(FunctionComparisonService.class);
|
||||||
setActionAttributes();
|
setActionAttributes();
|
||||||
}
|
}
|
||||||
|
@ -101,5 +103,8 @@ public abstract class CompareFunctionsAction extends DockingAction {
|
||||||
new ToolBarData(getToolBarIcon(), CREATE_COMPARISON_GROUP);
|
new ToolBarData(getToolBarIcon(), CREATE_COMPARISON_GROUP);
|
||||||
setToolBarData(newToolBarData);
|
setToolBarData(newToolBarData);
|
||||||
setHelpLocation(new HelpLocation("FunctionComparison", "Function_Comparison"));
|
setHelpLocation(new HelpLocation("FunctionComparison", "Function_Comparison"));
|
||||||
|
|
||||||
|
KeyBindingData data = new KeyBindingData('C', InputEvent.SHIFT_DOWN_MASK);
|
||||||
|
setKeyBindingData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import docking.ActionContext;
|
||||||
import ghidra.app.plugin.core.functionwindow.FunctionRowObject;
|
import ghidra.app.plugin.core.functionwindow.FunctionRowObject;
|
||||||
import ghidra.app.plugin.core.functionwindow.FunctionTableModel;
|
import ghidra.app.plugin.core.functionwindow.FunctionTableModel;
|
||||||
import ghidra.framework.plugintool.PluginTool;
|
import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.util.table.GhidraTable;
|
import ghidra.util.table.GhidraTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,9 +41,10 @@ public class CompareFunctionsFromFunctionTableAction extends CompareFunctionsAct
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param tool the plugin tool
|
* @param tool the plugin tool
|
||||||
|
* @param owner the action owner
|
||||||
*/
|
*/
|
||||||
public CompareFunctionsFromFunctionTableAction(PluginTool tool) {
|
public CompareFunctionsFromFunctionTableAction(PluginTool tool, String owner) {
|
||||||
super(tool);
|
super(tool, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,12 +67,9 @@ public class CompareFunctionsFromFunctionTableAction extends CompareFunctionsAct
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
FunctionTableModel model = (FunctionTableModel) table.getModel();
|
FunctionTableModel model = (FunctionTableModel) table.getModel();
|
||||||
Program program = model.getProgram();
|
|
||||||
FunctionManager functionManager = program.getFunctionManager();
|
|
||||||
List<FunctionRowObject> functionRowObjects = model.getRowObjects(selectedRows);
|
List<FunctionRowObject> functionRowObjects = model.getRowObjects(selectedRows);
|
||||||
for (FunctionRowObject functionRowObject : functionRowObjects) {
|
for (FunctionRowObject functionRowObject : functionRowObjects) {
|
||||||
long key = functionRowObject.getKey();
|
Function rowFunction = functionRowObject.getFunction();
|
||||||
Function rowFunction = functionManager.getFunction(key);
|
|
||||||
functions.add(rowFunction);
|
functions.add(rowFunction);
|
||||||
}
|
}
|
||||||
return functions;
|
return functions;
|
||||||
|
|
|
@ -34,9 +34,10 @@ public class CompareFunctionsFromListingAction extends CompareFunctionsAction {
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param tool the plugin tool
|
* @param tool the plugin tool
|
||||||
|
* @param owner the action owner
|
||||||
*/
|
*/
|
||||||
public CompareFunctionsFromListingAction(PluginTool tool) {
|
public CompareFunctionsFromListingAction(PluginTool tool, String owner) {
|
||||||
super(tool);
|
super(tool, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -93,6 +93,5 @@ public class NextFunctionAction extends DockingAction {
|
||||||
MultiFunctionComparisonPanel panel = (MultiFunctionComparisonPanel) provider.getComponent();
|
MultiFunctionComparisonPanel panel = (MultiFunctionComparisonPanel) provider.getComponent();
|
||||||
JComboBox<Function> focusedComponent = panel.getFocusedComponent();
|
JComboBox<Function> focusedComponent = panel.getFocusedComponent();
|
||||||
focusedComponent.setSelectedIndex(focusedComponent.getSelectedIndex() + 1);
|
focusedComponent.setSelectedIndex(focusedComponent.getSelectedIndex() + 1);
|
||||||
provider.contextChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functioncompare.actions;
|
package ghidra.app.plugin.core.functioncompare.actions;
|
||||||
|
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -34,7 +35,6 @@ import ghidra.framework.plugintool.PluginTool;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.HelpLocation;
|
import ghidra.util.HelpLocation;
|
||||||
import ghidra.util.SystemUtilities;
|
|
||||||
import resources.MultiIcon;
|
import resources.MultiIcon;
|
||||||
import resources.ResourceManager;
|
import resources.ResourceManager;
|
||||||
import resources.icons.ScaledImageIconWrapper;
|
import resources.icons.ScaledImageIconWrapper;
|
||||||
|
@ -86,6 +86,9 @@ public class OpenFunctionTableAction extends DockingAction {
|
||||||
HelpLocation helpLocation = new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC,
|
HelpLocation helpLocation = new HelpLocation(MultiFunctionComparisonPanel.HELP_TOPIC,
|
||||||
"Add_To_Comparison");
|
"Add_To_Comparison");
|
||||||
setHelpLocation(helpLocation);
|
setHelpLocation(helpLocation);
|
||||||
|
|
||||||
|
KeyBindingData data = new KeyBindingData('A', InputEvent.SHIFT_DOWN_MASK);
|
||||||
|
setKeyBindingData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -95,7 +98,10 @@ public class OpenFunctionTableAction extends DockingAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
Runnable runnable = () -> {
|
if (!(context.getComponentProvider() instanceof FunctionComparisonProvider)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionComparisonProvider provider =
|
FunctionComparisonProvider provider =
|
||||||
(FunctionComparisonProvider) context.getComponentProvider();
|
(FunctionComparisonProvider) context.getComponentProvider();
|
||||||
Program currentProgram = programManagerService.getCurrentProgram();
|
Program currentProgram = programManagerService.getCurrentProgram();
|
||||||
|
@ -114,8 +120,5 @@ public class OpenFunctionTableAction extends DockingAction {
|
||||||
Set<Function> functions =
|
Set<Function> functions =
|
||||||
rows.stream().map(row -> row.getFunction()).collect(Collectors.toSet());
|
rows.stream().map(row -> row.getFunction()).collect(Collectors.toSet());
|
||||||
comparisonService.compareFunctions(new HashSet<>(functions), provider);
|
comparisonService.compareFunctions(new HashSet<>(functions), provider);
|
||||||
};
|
|
||||||
|
|
||||||
SystemUtilities.runSwingLater(runnable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,5 @@ public class PreviousFunctionAction extends DockingAction {
|
||||||
MultiFunctionComparisonPanel panel = (MultiFunctionComparisonPanel) provider.getComponent();
|
MultiFunctionComparisonPanel panel = (MultiFunctionComparisonPanel) provider.getComponent();
|
||||||
JComboBox<Function> focusedComponent = panel.getFocusedComponent();
|
JComboBox<Function> focusedComponent = panel.getFocusedComponent();
|
||||||
focusedComponent.setSelectedIndex(focusedComponent.getSelectedIndex() - 1);
|
focusedComponent.setSelectedIndex(focusedComponent.getSelectedIndex() - 1);
|
||||||
provider.contextChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,6 @@ import ghidra.util.task.SwingUpdateManager;
|
||||||
category = PluginCategoryNames.CODE_VIEWER,
|
category = PluginCategoryNames.CODE_VIEWER,
|
||||||
shortDescription = "Function Viewer",
|
shortDescription = "Function Viewer",
|
||||||
description = "Provides a window that displays the list of functions in the program.",
|
description = "Provides a window that displays the list of functions in the program.",
|
||||||
servicesRequired = { FunctionComparisonService.class },
|
|
||||||
eventsConsumed = { ProgramClosedPluginEvent.class }
|
eventsConsumed = { ProgramClosedPluginEvent.class }
|
||||||
)
|
)
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
|
@ -78,9 +77,7 @@ public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectL
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
super.init();
|
super.init();
|
||||||
|
|
||||||
provider = new FunctionWindowProvider(this);
|
provider = new FunctionWindowProvider(this);
|
||||||
functionComparisonService = tool.getService(FunctionComparisonService.class);
|
|
||||||
createActions();
|
createActions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,11 +87,6 @@ public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectL
|
||||||
provider.getTable().getSelectionModel().addListSelectionListener(x -> {
|
provider.getTable().getSelectionModel().addListSelectionListener(x -> {
|
||||||
tool.contextChanged(provider);
|
tool.contextChanged(provider);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen for providers being opened/closed to we can disable the
|
|
||||||
// add-to-comparison action if there are no comparison windows
|
|
||||||
// open.
|
|
||||||
functionComparisonService.addFunctionComparisonProviderListener(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,6 +101,26 @@ public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectL
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serviceAdded(Class<?> interfaceClass, Object service) {
|
||||||
|
if (interfaceClass == FunctionComparisonService.class) {
|
||||||
|
functionComparisonService = (FunctionComparisonService) service;
|
||||||
|
|
||||||
|
// Listen for providers being opened/closed to we can disable
|
||||||
|
// comparison actions if there are no comparison providers
|
||||||
|
// open
|
||||||
|
functionComparisonService.addFunctionComparisonProviderListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serviceRemoved(Class<?> interfaceClass, Object service) {
|
||||||
|
if (interfaceClass == FunctionComparisonService.class) {
|
||||||
|
functionComparisonService.removeFunctionComparisonProviderListener(this);
|
||||||
|
functionComparisonService = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
public void domainObjectChanged(DomainObjectChangedEvent ev) {
|
||||||
|
|
||||||
|
@ -205,24 +217,10 @@ public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectL
|
||||||
selectAction = new MakeProgramSelectionAction(this, provider.getTable());
|
selectAction = new MakeProgramSelectionAction(this, provider.getTable());
|
||||||
tool.addLocalAction(provider, selectAction);
|
tool.addLocalAction(provider, selectAction);
|
||||||
|
|
||||||
compareFunctionsAction = new CompareFunctionsFromFunctionTableAction(tool);
|
compareFunctionsAction = new CompareFunctionsFromFunctionTableAction(tool, getName());
|
||||||
tool.addLocalAction(provider, compareFunctionsAction);
|
tool.addLocalAction(provider, compareFunctionsAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void installDummyAction(DockingAction action) {
|
|
||||||
// DummyKeyBindingsOptionsAction dummyAction =
|
|
||||||
// new DummyKeyBindingsOptionsAction(action.getName(), null);
|
|
||||||
// tool.addAction(dummyAction);
|
|
||||||
//
|
|
||||||
// ToolOptions options = tool.getOptions(DockingToolConstants.KEY_BINDINGS);
|
|
||||||
// options.addOptionsChangeListener(this);
|
|
||||||
//
|
|
||||||
// KeyStroke keyStroke = options.getKeyStroke(dummyAction.getFullName(), null);
|
|
||||||
// if (keyStroke != null) {
|
|
||||||
// action.setUnvalidatedKeyBindingData(new KeyBindingData(keyStroke));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
public void optionsChanged(ToolOptions options, String optionName, Object oldValue,
|
||||||
Object newValue) {
|
Object newValue) {
|
||||||
|
@ -237,11 +235,6 @@ public class FunctionWindowPlugin extends ProgramPlugin implements DomainObjectL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActionsEnabled(boolean enabled) {
|
|
||||||
selectAction.setEnabled(enabled);
|
|
||||||
compareFunctionsAction.setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void showFunctions() {
|
void showFunctions() {
|
||||||
provider.showFunctions();
|
provider.showFunctions();
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,9 +128,7 @@ public class FunctionWindowProvider extends ComponentProviderAdapter {
|
||||||
functionTable.setPreferredScrollableViewportSize(new Dimension(350, 150));
|
functionTable.setPreferredScrollableViewportSize(new Dimension(350, 150));
|
||||||
functionTable.setRowSelectionAllowed(true);
|
functionTable.setRowSelectionAllowed(true);
|
||||||
functionTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
functionTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||||
functionTable.getSelectionModel()
|
functionTable.getSelectionModel().addListSelectionListener(e -> tool.contextChanged(this));
|
||||||
.addListSelectionListener(
|
|
||||||
e -> plugin.setActionsEnabled(functionTable.getSelectedRowCount() > 0));
|
|
||||||
|
|
||||||
functionModel.addTableModelListener(e -> {
|
functionModel.addTableModelListener(e -> {
|
||||||
int rowCount = functionModel.getRowCount();
|
int rowCount = functionModel.getRowCount();
|
||||||
|
|
|
@ -27,7 +27,6 @@ import ghidra.app.plugin.core.functioncompare.*;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.exception.CancelledException;
|
|
||||||
import ghidra.util.task.TaskLauncher;
|
import ghidra.util.task.TaskLauncher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +113,7 @@ public class FunctionComparisonModel {
|
||||||
* Note: It is assumed that when using this method, all functions can be
|
* Note: It is assumed that when using this method, all functions can be
|
||||||
* compared with all other functions; meaning each function will be added as
|
* compared with all other functions; meaning each function will be added as
|
||||||
* both a source AND a target. To specify a specific source/target
|
* both a source AND a target. To specify a specific source/target
|
||||||
* relationship, see {@link #compareFunctions(Function, Function)}.
|
* relationship, use {@link #compareFunctions(Function, Function)}.
|
||||||
*
|
*
|
||||||
* @param functions the set of functions to compare
|
* @param functions the set of functions to compare
|
||||||
*/
|
*/
|
||||||
|
@ -295,13 +294,11 @@ public class FunctionComparisonModel {
|
||||||
|
|
||||||
// Now loop over the given functions and create new comparisons
|
// Now loop over the given functions and create new comparisons
|
||||||
for (Function f : functions) {
|
for (Function f : functions) {
|
||||||
try {
|
if (monitor.isCancelled()) {
|
||||||
monitor.checkCanceled();
|
|
||||||
}
|
|
||||||
catch (CancelledException e) {
|
|
||||||
Msg.info(this, "Function comparison operation cancelled");
|
Msg.info(this, "Function comparison operation cancelled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionComparison fc = new FunctionComparison();
|
FunctionComparison fc = new FunctionComparison();
|
||||||
fc.setSource(f);
|
fc.setSource(f);
|
||||||
fc.addTargets(functions);
|
fc.addTargets(functions);
|
||||||
|
|
|
@ -25,14 +25,24 @@ import ghidra.program.model.listing.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows users to create comparisons between functions which will be displayed
|
* Allows users to create comparisons between functions which will be displayed
|
||||||
* side-by-side in a {@link FunctionComparisonProvider}
|
* side-by-side in a {@link FunctionComparisonProvider}. Each side in the
|
||||||
|
* display will allow the user to select one or more functions
|
||||||
*/
|
*/
|
||||||
@ServiceInfo(defaultProvider = FunctionComparisonPlugin.class)
|
@ServiceInfo(defaultProvider = FunctionComparisonPlugin.class)
|
||||||
public interface FunctionComparisonService {
|
public interface FunctionComparisonService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a comparison between a set of functions, where each function
|
* Creates a comparison between a set of functions, where each function
|
||||||
* in the list can be compared against any other function in the list
|
* in the list can be compared against any other.
|
||||||
|
* <p>
|
||||||
|
* eg: Given a set of 3 functions (f1, f2, f3), the comparison dialog will
|
||||||
|
* allow the user to display either f1, f2 or f3 on EITHER side of the
|
||||||
|
* comparison.
|
||||||
|
* <p>
|
||||||
|
* Note that this method will always create a new provider; if you want to
|
||||||
|
* add functions to an existing comparison, use
|
||||||
|
* {@link #compareFunctions(Set, FunctionComparisonProvider) this}
|
||||||
|
* variant that takes a provider.
|
||||||
*
|
*
|
||||||
* @param functions the functions to compare
|
* @param functions the functions to compare
|
||||||
* @return the new comparison provider
|
* @return the new comparison provider
|
||||||
|
@ -40,7 +50,14 @@ public interface FunctionComparisonService {
|
||||||
public FunctionComparisonProvider compareFunctions(Set<Function> functions);
|
public FunctionComparisonProvider compareFunctions(Set<Function> functions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a comparison between two functions
|
* Creates a comparison between two functions, where the source function
|
||||||
|
* will be shown on the left side of the comparison dialog and the target
|
||||||
|
* on the right.
|
||||||
|
* <p>
|
||||||
|
* Note that this will always create a new provider; if you want to add
|
||||||
|
* functions to an existing comparison, use
|
||||||
|
* {@link #compareFunctions(Function, Function, FunctionComparisonProvider) this}
|
||||||
|
* variant that takes a provider.
|
||||||
*
|
*
|
||||||
* @param source a function in the comparison
|
* @param source a function in the comparison
|
||||||
* @param target a function in the comparison
|
* @param target a function in the comparison
|
||||||
|
@ -51,8 +68,11 @@ public interface FunctionComparisonService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a comparison between a set of functions, adding them to the
|
* Creates a comparison between a set of functions, adding them to the
|
||||||
* given comparison provider
|
* given comparison provider. Each function in the given set will be added
|
||||||
|
* to both sides of the comparison, allowing users to compare any functions
|
||||||
|
* in the existing provider with the new set.
|
||||||
*
|
*
|
||||||
|
* @see #compareFunctions(Set)
|
||||||
* @param functions the functions to compare
|
* @param functions the functions to compare
|
||||||
* @param provider the provider to add the comparisons to
|
* @param provider the provider to add the comparisons to
|
||||||
*/
|
*/
|
||||||
|
@ -61,8 +81,12 @@ public interface FunctionComparisonService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a comparison between two functions and adds it to a given
|
* Creates a comparison between two functions and adds it to a given
|
||||||
* comparison provider
|
* comparison provider. The existing comparisons in the provider will not
|
||||||
|
* be affected, unless the provider already contains a comparison with
|
||||||
|
* the same source function; in this case the given target will be added
|
||||||
|
* to that comparisons' list of targets.
|
||||||
*
|
*
|
||||||
|
* @see #compareFunctions(Function, Function)
|
||||||
* @param source a function in the comparison
|
* @param source a function in the comparison
|
||||||
* @param target a function in the comparison
|
* @param target a function in the comparison
|
||||||
* @param provider the provider to add the comparison to
|
* @param provider the provider to add the comparison to
|
||||||
|
@ -80,7 +104,7 @@ public interface FunctionComparisonService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a given function from all comparisons in the given comparison
|
* Removes a given function from all comparisons in the given comparison
|
||||||
* provider
|
* provider only
|
||||||
*
|
*
|
||||||
* @param function the function to remove
|
* @param function the function to remove
|
||||||
* @param provider the comparison provider to remove functions from
|
* @param provider the comparison provider to remove functions from
|
||||||
|
@ -94,4 +118,12 @@ public interface FunctionComparisonService {
|
||||||
* @param listener the listener to be added
|
* @param listener the listener to be added
|
||||||
*/
|
*/
|
||||||
public void addFunctionComparisonProviderListener(ComponentProviderActivationListener listener);
|
public void addFunctionComparisonProviderListener(ComponentProviderActivationListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a listener from the list of provider activation event subscribers
|
||||||
|
*
|
||||||
|
* @param listener the listener to remove
|
||||||
|
*/
|
||||||
|
public void removeFunctionComparisonProviderListener(
|
||||||
|
ComponentProviderActivationListener listener);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,8 @@ import ghidra.util.classfinder.ExtensionPoint;
|
||||||
* discovered by the {@link FunctionComparisonPanel} class and included as a
|
* discovered by the {@link FunctionComparisonPanel} class and included as a
|
||||||
* form of comparing two sections of code within the same or different programs
|
* form of comparing two sections of code within the same or different programs
|
||||||
* <p>
|
* <p>
|
||||||
* NOTE: ALL CodeComparisonPanel CLASSES MUST END IN <
|
* NOTE: ALL CodeComparisonPanel CLASSES MUST END IN
|
||||||
* code>CodeComparisonPanel</code> so they are discoverable by the
|
* <code>CodeComparisonPanel</code> so they are discoverable by the
|
||||||
* {@link ClassSearcher}
|
* {@link ClassSearcher}
|
||||||
*/
|
*/
|
||||||
public abstract class CodeComparisonPanel<T extends FieldPanelCoordinator> extends JPanel
|
public abstract class CodeComparisonPanel<T extends FieldPanelCoordinator> extends JPanel
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functioncompare;
|
package ghidra.app.plugin.core.functioncompare;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -25,10 +27,10 @@ import javax.swing.JPanel;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
|
import docking.ActionContext;
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import docking.widgets.dialogs.TableChooserDialog;
|
import docking.widgets.dialogs.TableChooserDialog;
|
||||||
import docking.widgets.table.GFilterTable;
|
import docking.widgets.table.GFilterTable;
|
||||||
import generic.test.AbstractGenericTest;
|
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.function.FunctionPlugin;
|
import ghidra.app.plugin.core.function.FunctionPlugin;
|
||||||
import ghidra.app.plugin.core.functionwindow.FunctionRowObject;
|
import ghidra.app.plugin.core.functionwindow.FunctionRowObject;
|
||||||
|
@ -46,7 +48,7 @@ import ghidra.test.TestEnv;
|
||||||
* Tests for the {@link FunctionComparisonPlugin function comparison plugin}
|
* Tests for the {@link FunctionComparisonPlugin function comparison plugin}
|
||||||
* that involve the GUI
|
* that involve the GUI
|
||||||
*/
|
*/
|
||||||
public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTest {
|
public class CompareFunctionsSlowTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
private Program program1;
|
private Program program1;
|
||||||
|
@ -65,8 +67,6 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
plugin = env.addPlugin(FunctionComparisonPlugin.class);
|
plugin = env.addPlugin(FunctionComparisonPlugin.class);
|
||||||
functionPlugin = env.addPlugin(FunctionPlugin.class);
|
functionPlugin = env.addPlugin(FunctionPlugin.class);
|
||||||
cbPlugin = env.addPlugin(CodeBrowserPlugin.class);
|
cbPlugin = env.addPlugin(CodeBrowserPlugin.class);
|
||||||
assertNotNull(plugin);
|
|
||||||
assertNotNull(functionPlugin);
|
|
||||||
buildTestProgram1();
|
buildTestProgram1();
|
||||||
buildTestProgram2();
|
buildTestProgram2();
|
||||||
showTool(plugin.getTool());
|
showTool(plugin.getTool());
|
||||||
|
@ -84,7 +84,7 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
provider = plugin.compareFunctions(functions);
|
provider = plugin.compareFunctions(functions);
|
||||||
provider = waitForComponentProvider(FunctionComparisonProvider.class);
|
provider = waitForComponentProvider(FunctionComparisonProvider.class);
|
||||||
plugin.removeFunction(foo, provider);
|
plugin.removeFunction(foo, provider);
|
||||||
assert (!provider.isVisible());
|
assertFalse(provider.isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -120,11 +120,15 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
DockingActionIf nextAction = getAction(plugin, "Compare Next Function");
|
DockingActionIf nextAction = getAction(plugin, "Compare Next Function");
|
||||||
DockingActionIf prevAction = getAction(plugin, "Compare Previous Function");
|
DockingActionIf prevAction = getAction(plugin, "Compare Previous Function");
|
||||||
|
|
||||||
assert (nextAction.isEnabled());
|
ActionContext context = provider.getActionContext(null);
|
||||||
assert (!prevAction.isEnabled());
|
assertTrue(nextAction.isEnabledForContext(context));
|
||||||
|
assertFalse(prevAction.isEnabledForContext(context));
|
||||||
|
|
||||||
performAction(nextAction);
|
performAction(nextAction);
|
||||||
assert (!nextAction.isEnabled());
|
|
||||||
assert (prevAction.isEnabled());
|
context = provider.getActionContext(null);
|
||||||
|
assertFalse(nextAction.isEnabledForContext(context));
|
||||||
|
assertTrue(prevAction.isEnabledForContext(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -141,11 +145,15 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
DockingActionIf nextAction = getAction(plugin, "Compare Next Function");
|
DockingActionIf nextAction = getAction(plugin, "Compare Next Function");
|
||||||
DockingActionIf prevAction = getAction(plugin, "Compare Previous Function");
|
DockingActionIf prevAction = getAction(plugin, "Compare Previous Function");
|
||||||
|
|
||||||
assert (nextAction.isEnabled());
|
ActionContext context = provider.getActionContext(null);
|
||||||
assert (!prevAction.isEnabled());
|
assertTrue(nextAction.isEnabledForContext(context));
|
||||||
|
assertFalse(prevAction.isEnabledForContext(context));
|
||||||
|
|
||||||
performAction(nextAction);
|
performAction(nextAction);
|
||||||
assert (!nextAction.isEnabled());
|
|
||||||
assert (prevAction.isEnabled());
|
context = provider.getActionContext(null);
|
||||||
|
assertFalse(nextAction.isEnabledForContext(context));
|
||||||
|
assertTrue(prevAction.isEnabledForContext(context));
|
||||||
|
|
||||||
JPanel rightPanel =
|
JPanel rightPanel =
|
||||||
provider.getComponent().getDualListingPanel().getRightPanel().getFieldPanel();
|
provider.getComponent().getDualListingPanel().getRightPanel().getFieldPanel();
|
||||||
|
@ -153,8 +161,9 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
provider.getComponent().updateActionEnablement();
|
provider.getComponent().updateActionEnablement();
|
||||||
|
|
||||||
assert (nextAction.isEnabled());
|
context = provider.getActionContext(null);
|
||||||
assert (!prevAction.isEnabled());
|
assertTrue(nextAction.isEnabledForContext(context));
|
||||||
|
assertFalse(prevAction.isEnabledForContext(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -163,11 +172,15 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
provider = plugin.compareFunctions(functions);
|
provider = plugin.compareFunctions(functions);
|
||||||
provider.setVisible(true);
|
provider.setVisible(true);
|
||||||
|
|
||||||
|
// Must do this or the context for the action initiated below will be
|
||||||
|
// for the listing, not the comparison provider
|
||||||
|
clickComponentProvider(provider);
|
||||||
|
|
||||||
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
||||||
performAction(openTableAction);
|
performAction(openTableAction);
|
||||||
|
|
||||||
Window selectWindow = waitForWindowByTitleContaining("Select Functions");
|
Window selectWindow = waitForWindowByTitleContaining("Select Functions");
|
||||||
assert (selectWindow != null);
|
assertNotNull(selectWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -182,26 +195,26 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
// initiated below
|
// initiated below
|
||||||
clickComponentProvider(provider);
|
clickComponentProvider(provider);
|
||||||
|
|
||||||
assert (provider.getModel().getSourceFunctions().size() == 1);
|
assertTrue(provider.getModel().getSourceFunctions().size() == 1);
|
||||||
assert (provider.getModel().getSourceFunctions().contains(foo));
|
assertTrue(provider.getModel().getSourceFunctions().contains(foo));
|
||||||
|
|
||||||
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
||||||
performAction(openTableAction);
|
performAction(openTableAction);
|
||||||
|
|
||||||
TableChooserDialog<FunctionTableModel> chooser =
|
TableChooserDialog<FunctionTableModel> chooser =
|
||||||
waitForDialogComponent(TableChooserDialog.class);
|
waitForDialogComponent(TableChooserDialog.class);
|
||||||
assert (chooser != null);
|
assertNotNull(chooser);
|
||||||
|
|
||||||
GFilterTable<FunctionRowObject> table =
|
GFilterTable<FunctionRowObject> table =
|
||||||
(GFilterTable<FunctionRowObject>) getInstanceField("gFilterTable", chooser);
|
(GFilterTable<FunctionRowObject>) getInstanceField("gFilterTable", chooser);
|
||||||
assert (table.getModel().getRowCount() == 2);
|
assertTrue(table.getModel().getRowCount() == 2);
|
||||||
clickTableCell(table.getTable(), 1, 0, 1);
|
clickTableCell(table.getTable(), 1, 0, 1);
|
||||||
|
|
||||||
pressButtonByText(chooser, "OK");
|
pressButtonByText(chooser, "OK");
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
assert (provider.getModel().getSourceFunctions().size() == 2);
|
assertTrue(provider.getModel().getSourceFunctions().size() == 2);
|
||||||
assert (provider.getModel().getSourceFunctions().contains(foo));
|
assertTrue(provider.getModel().getSourceFunctions().contains(foo));
|
||||||
assert (provider.getModel().getSourceFunctions().contains(bat));
|
assertTrue(provider.getModel().getSourceFunctions().contains(bat));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -215,9 +228,9 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
provider = plugin.compareFunctions(functions);
|
provider = plugin.compareFunctions(functions);
|
||||||
provider.setVisible(true);
|
provider.setVisible(true);
|
||||||
|
|
||||||
assert (provider.getModel().getSourceFunctions().size() == 2);
|
assertTrue(provider.getModel().getSourceFunctions().size() == 2);
|
||||||
assert (provider.getModel().getSourceFunctions().contains(foo));
|
assertTrue(provider.getModel().getSourceFunctions().contains(foo));
|
||||||
assert (provider.getModel().getSourceFunctions().contains(bar));
|
assertTrue(provider.getModel().getSourceFunctions().contains(bar));
|
||||||
|
|
||||||
Address addr = program1.getAddressFactory().getAddress("10018cf");
|
Address addr = program1.getAddressFactory().getAddress("10018cf");
|
||||||
ProgramLocation loc = new ProgramLocation(program1, addr);
|
ProgramLocation loc = new ProgramLocation(program1, addr);
|
||||||
|
@ -227,8 +240,8 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
|
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
assert (provider.getModel().getSourceFunctions().size() == 1);
|
assertTrue(provider.getModel().getSourceFunctions().size() == 1);
|
||||||
assert (provider.getModel().getSourceFunctions().contains(bar));
|
assertTrue(provider.getModel().getSourceFunctions().contains(bar));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,7 +259,6 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
bat = builder.createEmptyFunction("Bat", "100299e", 130, null, p, p, p);
|
bat = builder.createEmptyFunction("Bat", "100299e", 130, null, p, p, p);
|
||||||
|
|
||||||
program1 = builder.getProgram();
|
program1 = builder.getProgram();
|
||||||
AbstractGenericTest.setInstanceField("recordChanges", program1, Boolean.TRUE);
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +276,6 @@ public class CompareFunctionsTestSlow extends AbstractGhidraHeadedIntegrationTes
|
||||||
bar = builder.createEmptyFunction("Bar", "10018cf", 10, null, p);
|
bar = builder.createEmptyFunction("Bar", "10018cf", 10, null, p);
|
||||||
|
|
||||||
program2 = builder.getProgram();
|
program2 = builder.getProgram();
|
||||||
AbstractGenericTest.setInstanceField("recordChanges", program2, Boolean.TRUE);
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functioncompare;
|
package ghidra.app.plugin.core.functioncompare;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -64,7 +64,6 @@ public class CompareFunctionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
DummyPluginTool tool = new DummyPluginTool();
|
DummyPluginTool tool = new DummyPluginTool();
|
||||||
plugin = new FunctionComparisonPlugin(tool);
|
plugin = new FunctionComparisonPlugin(tool);
|
||||||
assertNotNull(plugin);
|
|
||||||
buildTestProgram1();
|
buildTestProgram1();
|
||||||
buildTestProgram2();
|
buildTestProgram2();
|
||||||
|
|
||||||
|
@ -81,7 +80,7 @@ public class CompareFunctionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
public void testSetNoFunctions() throws Exception {
|
public void testSetNoFunctions() throws Exception {
|
||||||
Set<Function> functions = CompareFunctionsTestUtility.getFunctionsAsSet();
|
Set<Function> functions = CompareFunctionsTestUtility.getFunctionsAsSet();
|
||||||
FunctionComparisonProvider provider = plugin.compareFunctions(functions);
|
FunctionComparisonProvider provider = plugin.compareFunctions(functions);
|
||||||
assert (provider == null);
|
assertNull(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functioncompare;
|
package ghidra.app.plugin.core.functioncompare;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
|
@ -23,7 +26,7 @@ import ghidra.program.model.listing.Function;
|
||||||
* Helper methods for use with function comparison tests
|
* Helper methods for use with function comparison tests
|
||||||
*
|
*
|
||||||
* @see {@link CompareFunctionsTest}
|
* @see {@link CompareFunctionsTest}
|
||||||
* @see {@link CompareFunctionsTestSlow}
|
* @see {@link CompareFunctionsSlowTest}
|
||||||
*/
|
*/
|
||||||
public class CompareFunctionsTestUtility {
|
public class CompareFunctionsTestUtility {
|
||||||
|
|
||||||
|
@ -38,8 +41,8 @@ public class CompareFunctionsTestUtility {
|
||||||
Function... functions) {
|
Function... functions) {
|
||||||
Set<Function> funcs = new HashSet<>(Arrays.asList(functions));
|
Set<Function> funcs = new HashSet<>(Arrays.asList(functions));
|
||||||
Set<Function> fcs = provider.getModel().getSourceFunctions();
|
Set<Function> fcs = provider.getModel().getSourceFunctions();
|
||||||
assert (fcs.size() == funcs.size());
|
assertEquals(fcs.size(), funcs.size());
|
||||||
assert (fcs.containsAll(funcs));
|
assertTrue(fcs.containsAll(funcs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,8 +57,8 @@ public class CompareFunctionsTestUtility {
|
||||||
Function source, Function... targets) {
|
Function source, Function... targets) {
|
||||||
Set<Function> targetsAsList = new HashSet<>(Arrays.asList(targets));
|
Set<Function> targetsAsList = new HashSet<>(Arrays.asList(targets));
|
||||||
Set<Function> tgts = provider.getModel().getTargetFunctions(source);
|
Set<Function> tgts = provider.getModel().getTargetFunctions(source);
|
||||||
assert (tgts.size() == targetsAsList.size());
|
assertEquals(tgts.size(), targetsAsList.size());
|
||||||
assert (tgts.containsAll(targetsAsList));
|
assertTrue(tgts.containsAll(targetsAsList));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,8 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.feature.vt.gui.provider.functionassociation;
|
package ghidra.feature.vt.gui.provider.functionassociation;
|
||||||
|
|
||||||
import static ghidra.feature.vt.api.impl.VTChangeManager.*;
|
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_ASSOCIATION_STATUS_CHANGED;
|
||||||
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.*;
|
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_MATCH_ADDED;
|
||||||
|
import static ghidra.feature.vt.api.impl.VTChangeManager.DOCR_VT_MATCH_DELETED;
|
||||||
|
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_ALL;
|
||||||
|
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_UNACCEPTED;
|
||||||
|
import static ghidra.feature.vt.gui.provider.functionassociation.FilterSettings.SHOW_UNMATCHED;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
@ -473,8 +477,10 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
|
||||||
|
|
||||||
sourceFunctionsModel.addTableModelListener(new TitleUpdateListener());
|
sourceFunctionsModel.addTableModelListener(new TitleUpdateListener());
|
||||||
|
|
||||||
sourceFunctionsTable.getColumnModel().getColumn(
|
sourceFunctionsTable.getColumnModel()
|
||||||
VTFunctionAssociationTableModel.ADDRESS_COL).setPreferredWidth(
|
.getColumn(
|
||||||
|
VTFunctionAssociationTableModel.ADDRESS_COL)
|
||||||
|
.setPreferredWidth(
|
||||||
VTFunctionAssociationTableModel.ADDRESS_COL_WIDTH);
|
VTFunctionAssociationTableModel.ADDRESS_COL_WIDTH);
|
||||||
|
|
||||||
sourceTableFilterPanel =
|
sourceTableFilterPanel =
|
||||||
|
@ -530,8 +536,10 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
|
||||||
JTableHeader functionHeader = destinationFunctionsTable.getTableHeader();
|
JTableHeader functionHeader = destinationFunctionsTable.getTableHeader();
|
||||||
functionHeader.setUpdateTableInRealTime(true);
|
functionHeader.setUpdateTableInRealTime(true);
|
||||||
|
|
||||||
destinationFunctionsTable.getColumnModel().getColumn(
|
destinationFunctionsTable.getColumnModel()
|
||||||
VTFunctionAssociationTableModel.ADDRESS_COL).setPreferredWidth(
|
.getColumn(
|
||||||
|
VTFunctionAssociationTableModel.ADDRESS_COL)
|
||||||
|
.setPreferredWidth(
|
||||||
VTFunctionAssociationTableModel.ADDRESS_COL_WIDTH);
|
VTFunctionAssociationTableModel.ADDRESS_COL_WIDTH);
|
||||||
|
|
||||||
destinationTableFilterPanel =
|
destinationTableFilterPanel =
|
||||||
|
|
|
@ -181,7 +181,7 @@ public class FunctionComparisonScreenShots extends GhidraScreenShotGenerator {
|
||||||
waitForSwing();
|
waitForSwing();
|
||||||
|
|
||||||
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
DockingActionIf openTableAction = getAction(plugin, "Add Functions To Comparison");
|
||||||
performAction(openTableAction);
|
performAction(openTableAction, false);
|
||||||
|
|
||||||
TableChooserDialog<?> dialog =
|
TableChooserDialog<?> dialog =
|
||||||
waitForDialogComponent(TableChooserDialog.class);
|
waitForDialogComponent(TableChooserDialog.class);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue