mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-24 03:09:36 +08:00
Merge remote-tracking branch 'origin/GP-6016-dragonmacher-function-compare-save--SQUASHED'
This commit is contained in:
+65
-9
@@ -18,8 +18,7 @@ package ghidra.features.base.codecompare.listing;
|
||||
import static ghidra.util.datastruct.Duo.Side.*;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
@@ -37,8 +36,8 @@ import ghidra.app.plugin.core.functioncompare.actions.*;
|
||||
import ghidra.app.util.ListingHighlightProvider;
|
||||
import ghidra.app.util.viewer.format.*;
|
||||
import ghidra.app.util.viewer.listingpanel.*;
|
||||
import ghidra.features.base.codecompare.panel.CodeComparisonViewActionContext;
|
||||
import ghidra.features.base.codecompare.panel.CodeComparisonView;
|
||||
import ghidra.features.base.codecompare.panel.CodeComparisonViewActionContext;
|
||||
import ghidra.framework.options.*;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.*;
|
||||
@@ -63,6 +62,7 @@ public class ListingCodeComparisonView
|
||||
extends CodeComparisonView implements FormatModelListener, OptionsChangeListener {
|
||||
|
||||
public static final String NAME = "Listing View";
|
||||
private static final String FORMAT_KEY = "FIELD_FORMAT";
|
||||
private static final String DIFF_NAVIGATE_GROUP = "A2_DiffNavigate";
|
||||
|
||||
//@formatter:off
|
||||
@@ -79,6 +79,8 @@ public class ListingCodeComparisonView
|
||||
ALL, UNMATCHED, DIFF
|
||||
}
|
||||
|
||||
private SaveState defaultSaveState;
|
||||
private SaveState saveState;
|
||||
private ListingCodeComparisonOptions comparisonOptions;
|
||||
|
||||
private Duo<ListingDisplay> displays;
|
||||
@@ -112,6 +114,9 @@ public class ListingCodeComparisonView
|
||||
|
||||
listingDiff = buildListingDiff();
|
||||
displays = buildListingDisplays();
|
||||
|
||||
buildDefaultSaveState();
|
||||
|
||||
buildPanel();
|
||||
createActions();
|
||||
|
||||
@@ -139,6 +144,63 @@ public class ListingCodeComparisonView
|
||||
return new Duo<>(leftDisplay, rightDisplay);
|
||||
}
|
||||
|
||||
private void buildDefaultSaveState() {
|
||||
SaveState ss = new SaveState();
|
||||
saveFormat(ss);
|
||||
defaultSaveState = ss;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSaveState(SaveState ss) {
|
||||
|
||||
this.saveState = ss;
|
||||
|
||||
if (hasStateChanges()) {
|
||||
loadFormat(ss);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean hasStateChanges() {
|
||||
if (!saveState.isEmpty()) {
|
||||
return !equals(saveState, defaultSaveState);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean equals(SaveState state1, SaveState state2) {
|
||||
String s1 = state1.toString();
|
||||
String s2 = state2.toString();
|
||||
return Objects.equals(s1, s2);
|
||||
}
|
||||
|
||||
private void changeRightToMatchLeftFormat(FieldFormatModel model) {
|
||||
SaveState formatState = new SaveState();
|
||||
displays.get(LEFT).getFormatManager().saveState(formatState);
|
||||
displays.get(RIGHT).getFormatManager().readState(formatState);
|
||||
|
||||
saveFormat(saveState);
|
||||
tool.setConfigChanged(true);
|
||||
}
|
||||
|
||||
private void loadFormat(SaveState ss) {
|
||||
|
||||
SaveState formatState = ss.getSaveState(FORMAT_KEY);
|
||||
if (formatState == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
displays.get(LEFT).getFormatManager().readState(formatState);
|
||||
displays.get(RIGHT).getFormatManager().readState(formatState);
|
||||
}
|
||||
|
||||
private void saveFormat(SaveState ss) {
|
||||
SaveState formatState = new SaveState();
|
||||
FormatManager format = displays.get(LEFT).getFormatManager();
|
||||
format.saveState(formatState);
|
||||
ss.putSaveState(FORMAT_KEY, formatState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComparisonComponent(Side side) {
|
||||
return displays.get(side).getListingPanel();
|
||||
@@ -590,12 +652,6 @@ public class ListingCodeComparisonView
|
||||
comparisonOptions.loadOptions(options);
|
||||
}
|
||||
|
||||
private void changeRightToMatchLeftFormat(FieldFormatModel model) {
|
||||
SaveState saveState = new SaveState();
|
||||
displays.get(LEFT).getFormatManager().saveState(saveState);
|
||||
displays.get(RIGHT).getFormatManager().readState(saveState);
|
||||
}
|
||||
|
||||
private void updateProgramViews() {
|
||||
displays.get(LEFT).setProgramView(getProgram(LEFT), getAddresses(LEFT), "listing1");
|
||||
displays.get(RIGHT).setProgramView(getProgram(RIGHT), getAddresses(RIGHT), "listing2");
|
||||
|
||||
+31
-42
@@ -49,12 +49,11 @@ import help.HelpService;
|
||||
* A panel for displaying {@link Function functions} side-by-side for comparison purposes
|
||||
*/
|
||||
public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
private static final String ORIENTATION_PROPERTY_NAME = "ORIENTATION";
|
||||
|
||||
private static final String DEFAULT_CODE_COMPARISON_VIEW = ListingCodeComparisonView.NAME;
|
||||
private static final String COMPARISON_VIEW_DISPLAYED = "COMPARISON_VIEW_DISPLAYED";
|
||||
private static final String CODE_COMPARISON_LOCK_SCROLLING_TOGETHER =
|
||||
"CODE_COMPARISON_LOCK_SCROLLING_TOGETHER";
|
||||
private static final String DEFAULT_VIEW = ListingCodeComparisonView.NAME;
|
||||
private static final String KEY_ACTIVE_VIEW = "ACTIVE_VIEW";
|
||||
private static final String KEY_SCROLL_LOCK = "SCROLL_LOCK";
|
||||
private static final String KEY_ORIENTATION = "ORIENTATION";
|
||||
|
||||
private static final String HELP_TOPIC = "FunctionComparison";
|
||||
|
||||
@@ -67,7 +66,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
private static final String DUAL_SCROLLING_HELP_TOPIC = "FunctionComparison";
|
||||
|
||||
private JTabbedPane tabbedPane;
|
||||
private Map<String, JComponent> tabNameToComponentMap;
|
||||
private Map<String, JComponent> tabComponentsByName;
|
||||
private List<CodeComparisonView> codeComparisonViews;
|
||||
private ToggleScrollLockAction toggleScrollLockAction;
|
||||
private boolean syncScrolling = false;
|
||||
@@ -89,10 +88,16 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
state.addUpdateCallback(this::comparisonStateUpdated);
|
||||
|
||||
codeComparisonViews = getCodeComparisonViews(tool, owner);
|
||||
tabNameToComponentMap = new HashMap<>();
|
||||
tabComponentsByName = new HashMap<>();
|
||||
createMainPanel();
|
||||
createActions(owner);
|
||||
setScrollingSyncState(true);
|
||||
|
||||
// reload saved state; add the listener after we are fully finished build so we do not save
|
||||
// any default state
|
||||
readPanelState();
|
||||
tabbedPane.addChangeListener(this);
|
||||
|
||||
HelpService help = Help.getHelpService();
|
||||
help.registerHelp(this, new HelpLocation(HELP_TOPIC, "Function Comparison"));
|
||||
}
|
||||
@@ -237,9 +242,8 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
* @param name name of view to set as the current tab
|
||||
* @return true if the named view was found in the view map
|
||||
*/
|
||||
public boolean setCurrentTabbedComponent(String name) {
|
||||
|
||||
JComponent component = tabNameToComponentMap.get(name);
|
||||
public boolean setActiveView(String name) {
|
||||
JComponent component = tabComponentsByName.get(name);
|
||||
if (component != null) {
|
||||
if (tabbedPane.getSelectedComponent() == component) {
|
||||
tabChanged();
|
||||
@@ -254,7 +258,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
*
|
||||
* @return the tab name, or null if there is nothing selected
|
||||
*/
|
||||
public String getCurrentComponentName() {
|
||||
public String getActiveViewName() {
|
||||
int selectedIndex = tabbedPane.getSelectedIndex();
|
||||
if (selectedIndex >= 0) {
|
||||
return tabbedPane.getTitleAt(selectedIndex);
|
||||
@@ -262,14 +266,6 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of views in the tabbed pane
|
||||
* @return the number of views in the tabbed pane
|
||||
*/
|
||||
int getNumberOfTabbedComponents() {
|
||||
return tabNameToComponentMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all views in the tabbed pane
|
||||
*/
|
||||
@@ -288,7 +284,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
public CodeComparisonView getCodeComparisonView(String name) {
|
||||
public CodeComparisonView getView(String name) {
|
||||
for (CodeComparisonView view : codeComparisonViews) {
|
||||
if (name.equals(view.getName())) {
|
||||
return view;
|
||||
@@ -297,21 +293,12 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void selectComparisonView(String name) {
|
||||
for (CodeComparisonView view : codeComparisonViews) {
|
||||
if (name.equals(view.getName())) {
|
||||
tabbedPane.setSelectedComponent(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the main tabbed panel
|
||||
*/
|
||||
private void createMainPanel() {
|
||||
tabbedPane = new JTabbedPane();
|
||||
|
||||
tabbedPane.addChangeListener(this);
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
add(tabbedPane, BorderLayout.CENTER);
|
||||
@@ -319,7 +306,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
|
||||
for (CodeComparisonView view : codeComparisonViews) {
|
||||
tabbedPane.add(view.getName(), view);
|
||||
tabNameToComponentMap.put(view.getName(), view);
|
||||
tabComponentsByName.put(view.getName(), view);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,32 +343,34 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
private void readPanelState() {
|
||||
|
||||
SaveState panelState = state.getPanelState();
|
||||
String currentTabView =
|
||||
panelState.getString(COMPARISON_VIEW_DISPLAYED, DEFAULT_CODE_COMPARISON_VIEW);
|
||||
setCurrentTabbedComponent(currentTabView);
|
||||
setScrollingSyncState(
|
||||
panelState.getBoolean(CODE_COMPARISON_LOCK_SCROLLING_TOGETHER, true));
|
||||
String activeView = panelState.getString(KEY_ACTIVE_VIEW, DEFAULT_VIEW);
|
||||
setActiveView(activeView);
|
||||
|
||||
boolean scrollLock = panelState.getBoolean(KEY_SCROLL_LOCK, true);
|
||||
setScrollingSyncState(scrollLock);
|
||||
|
||||
for (CodeComparisonView view : codeComparisonViews) {
|
||||
String key = view.getName() + ORIENTATION_PROPERTY_NAME;
|
||||
String key = view.getName() + KEY_ORIENTATION;
|
||||
view.setSideBySide(panelState.getBoolean(key, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTabState() {
|
||||
String currentComponentName = getCurrentComponentName();
|
||||
if (currentComponentName == null) {
|
||||
return;
|
||||
|
||||
String viewName = getActiveViewName();
|
||||
if (viewName == null) {
|
||||
return; // null can happen during tabbed pane disposal
|
||||
}
|
||||
|
||||
SaveState panelState = state.getPanelState();
|
||||
panelState.putString(COMPARISON_VIEW_DISPLAYED, getCurrentComponentName());
|
||||
panelState.putString(KEY_ACTIVE_VIEW, getActiveViewName());
|
||||
|
||||
state.setChanged();
|
||||
}
|
||||
|
||||
private void writeScrollState() {
|
||||
SaveState panelState = state.getPanelState();
|
||||
panelState.putBoolean(CODE_COMPARISON_LOCK_SCROLLING_TOGETHER, isScrollingSynced());
|
||||
panelState.putBoolean(KEY_SCROLL_LOCK, isScrollingSynced());
|
||||
state.setChanged();
|
||||
}
|
||||
|
||||
@@ -389,7 +378,7 @@ public class FunctionComparisonPanel extends JPanel implements ChangeListener {
|
||||
|
||||
SaveState panelState = state.getPanelState();
|
||||
for (CodeComparisonView view : codeComparisonViews) {
|
||||
String key = view.getName() + ORIENTATION_PROPERTY_NAME;
|
||||
String key = view.getName() + KEY_ORIENTATION;
|
||||
boolean sideBySide = view.isSideBySide();
|
||||
panelState.putBoolean(key, sideBySide);
|
||||
}
|
||||
|
||||
+7
-4
@@ -31,8 +31,11 @@ public class FunctionComparisonState {
|
||||
|
||||
private static final String PROVIDER_SAVE_STATE_NAME = "FunctionComparison";
|
||||
|
||||
// generic panel state that applies to the top-level panel, such as divider location
|
||||
private SaveState panelState = new SaveState();
|
||||
private CodeComparisonViewState comparisonState = new CodeComparisonViewState();
|
||||
|
||||
// view-specific state that is managed by each discovered view
|
||||
private CodeComparisonViewState viewState = new CodeComparisonViewState();
|
||||
|
||||
private PluginTool tool;
|
||||
|
||||
@@ -55,7 +58,7 @@ public class FunctionComparisonState {
|
||||
* @return the state
|
||||
*/
|
||||
public CodeComparisonViewState getViewState() {
|
||||
return comparisonState;
|
||||
return viewState;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +70,7 @@ public class FunctionComparisonState {
|
||||
|
||||
public void writeConfigState(SaveState saveState) {
|
||||
saveState.putSaveState(PROVIDER_SAVE_STATE_NAME, panelState);
|
||||
comparisonState.writeConfigState(saveState);
|
||||
viewState.writeConfigState(saveState);
|
||||
}
|
||||
|
||||
public void readConfigState(SaveState saveState) {
|
||||
@@ -76,7 +79,7 @@ public class FunctionComparisonState {
|
||||
panelState = restoredPanelState;
|
||||
}
|
||||
|
||||
comparisonState.readConfigState(saveState);
|
||||
viewState.readConfigState(saveState);
|
||||
updateCallbacks.forEach(Callback::call);
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -354,12 +354,12 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter
|
||||
}
|
||||
}
|
||||
|
||||
public CodeComparisonView getCodeComparisonView(String name) {
|
||||
return functionComparisonPanel.getCodeComparisonView(name);
|
||||
public CodeComparisonView getView(String name) {
|
||||
return functionComparisonPanel.getView(name);
|
||||
}
|
||||
|
||||
public void selectComparisonView(String name) {
|
||||
functionComparisonPanel.selectComparisonView(name);
|
||||
public void setActiveView(String name) {
|
||||
functionComparisonPanel.setActiveView(name);
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ public abstract class AbstractDualDecompilerTest extends AbstractGhidraHeadedInt
|
||||
protected void setActivePanel(FunctionComparisonProvider provider,
|
||||
CodeComparisonView comparisonProvider) {
|
||||
runSwing(
|
||||
() -> provider.getComponent().setCurrentTabbedComponent(comparisonProvider.getName()));
|
||||
() -> provider.getComponent().setActiveView(comparisonProvider.getName()));
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -294,7 +294,7 @@ public class CompareFunctionsProviderTest extends AbstractGhidraHeadedIntegratio
|
||||
private void setActivePanel(FunctionComparisonProvider provider,
|
||||
CodeComparisonView comparisonProvider) {
|
||||
runSwing(
|
||||
() -> provider.getComponent().setCurrentTabbedComponent(comparisonProvider.getName()));
|
||||
() -> provider.getComponent().setActiveView(comparisonProvider.getName()));
|
||||
waitForSwing();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -375,7 +375,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
|
||||
functionComparisonPanel = fcService.createComparisonViewer();
|
||||
|
||||
addSpecificCodeComparisonActions();
|
||||
functionComparisonPanel.setCurrentTabbedComponent(ListingCodeComparisonView.NAME);
|
||||
functionComparisonPanel.setActiveView(ListingCodeComparisonView.NAME);
|
||||
functionComparisonPanel.setTitlePrefixes("Source:", "Destination:");
|
||||
|
||||
comparisonSplitPane =
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
|
||||
functionComparisonPanel = fcService.createComparisonViewer();
|
||||
|
||||
addSpecificCodeComparisonActions();
|
||||
functionComparisonPanel.setCurrentTabbedComponent(ListingCodeComparisonView.NAME);
|
||||
functionComparisonPanel.setActiveView(ListingCodeComparisonView.NAME);
|
||||
functionComparisonPanel.getAccessibleContext().setAccessibleName("Function Comparison");
|
||||
functionComparisonPanel.setTitlePrefixes("Source:", "Destination:");
|
||||
ListingCodeComparisonView dualListingProvider =
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class FunctionComparisonScreenShots extends GhidraScreenShotGenerator {
|
||||
waitForComponentProvider(FunctionComparisonProvider.class);
|
||||
FunctionComparisonPanel functionComparisonPanel = provider.getComponent();
|
||||
runSwing(() -> {
|
||||
functionComparisonPanel.setCurrentTabbedComponent("Listing View");
|
||||
functionComparisonPanel.setActiveView("Listing View");
|
||||
ListingCodeComparisonView dualListing =
|
||||
(ListingCodeComparisonView) functionComparisonPanel.getDisplayedView();
|
||||
ListingPanel leftPanel = dualListing.getListingPanel(LEFT);
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ public class CompareFunctionsDecompilerViewTest extends AbstractGhidraHeadedInte
|
||||
checkFunctions(provider, LEFT, fun1, fun1, fun2);
|
||||
DecompilerCodeComparisonView comparisonProvider =
|
||||
(DecompilerCodeComparisonView) provider
|
||||
.getCodeComparisonView(DecompilerCodeComparisonView.NAME);
|
||||
.getView(DecompilerCodeComparisonView.NAME);
|
||||
|
||||
waitForDecompiler(comparisonProvider);
|
||||
assertHasLines(comparisonProvider.getLeftPanel(), 28);
|
||||
|
||||
+2
-2
@@ -500,13 +500,13 @@ public class CompareFunctionsFunctionGraphViewTest extends AbstractGhidraHeadedI
|
||||
}
|
||||
|
||||
private void selectFgPanel(FunctionComparisonProvider provider) {
|
||||
runSwing(() -> provider.selectComparisonView(FunctionGraphCodeComparisonView.NAME));
|
||||
runSwing(() -> provider.setActiveView(FunctionGraphCodeComparisonView.NAME));
|
||||
}
|
||||
|
||||
private FunctionGraphCodeComparisonView getFgComparisonProvider(
|
||||
FunctionComparisonProvider provider) {
|
||||
return runSwing(() -> (FunctionGraphCodeComparisonView) provider
|
||||
.getCodeComparisonView(FunctionGraphCodeComparisonView.NAME));
|
||||
.getView(FunctionGraphCodeComparisonView.NAME));
|
||||
}
|
||||
|
||||
private void waitForFunctionGraph(FunctionGraphCodeComparisonView panel) {
|
||||
|
||||
Reference in New Issue
Block a user