diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java index d72df68d7b..5a725d0372 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AbstractCodeBrowserPlugin.java @@ -19,7 +19,8 @@ import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.math.BigInteger; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.ImageIcon; @@ -27,25 +28,19 @@ import javax.swing.JComponent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import docking.ActionContext; import docking.action.DockingAction; -import docking.action.MenuData; -import docking.action.builder.ActionBuilder; -import docking.tool.ToolConstants; import docking.widgets.fieldpanel.*; import docking.widgets.fieldpanel.field.Field; import docking.widgets.fieldpanel.support.FieldLocation; import docking.widgets.fieldpanel.support.FieldSelection; import ghidra.GhidraOptions; -import ghidra.app.context.ListingActionContext; import ghidra.app.events.ProgramHighlightPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.core.codebrowser.hover.ListingHoverService; -import ghidra.app.plugin.core.table.TableComponentProvider; import ghidra.app.services.*; -import ghidra.app.util.*; -import ghidra.app.util.query.TableService; +import ghidra.app.util.HighlightProvider; +import ghidra.app.util.ProgramDropProvider; import ghidra.app.util.viewer.field.ListingField; import ghidra.app.util.viewer.field.ListingTextField; import ghidra.app.util.viewer.format.*; @@ -58,15 +53,11 @@ import ghidra.framework.options.*; import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.address.*; -import ghidra.program.model.listing.*; -import ghidra.program.model.symbol.Reference; +import ghidra.program.model.listing.Data; +import ghidra.program.model.listing.Program; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.util.*; -import ghidra.util.datastruct.Accumulator; -import ghidra.util.exception.CancelledException; -import ghidra.util.table.*; -import ghidra.util.task.TaskMonitor; import resources.ResourceManager; public abstract class AbstractCodeBrowserPlugin
extends Plugin @@ -96,9 +87,6 @@ public abstract class AbstractCodeBrowserPlugin
ex private ChangeListener markerChangeListener; private FocusingMouseListener focusingMouseListener = new FocusingMouseListener(); - private DockingAction tableFromSelectionAction; - private DockingAction showXrefsAction; - private Color cursorHighlightColor; private boolean isHighlightCursorLine; private ProgramDropProvider dndProvider; @@ -122,7 +110,6 @@ public abstract class AbstractCodeBrowserPlugin
ex initOptions(fieldOptions); initDisplayOptions(displayOptions); initMiscellaneousOptions(); - initActions(); displayOptions.addOptionsChangeListener(this); fieldOptions.addOptionsChangeListener(this); tool.setDefaultComponent(connectedProvider); @@ -231,10 +218,6 @@ public abstract class AbstractCodeBrowserPlugin
ex @Override public void serviceAdded(Class> interfaceClass, Object service) { - if (interfaceClass == TableService.class) { - tool.addAction(tableFromSelectionAction); - tool.addAction(showXrefsAction); - } if (interfaceClass == ViewManagerService.class && viewManager == null) { viewManager = (ViewManagerService) service; viewChanged(viewManager.getCurrentView()); @@ -262,12 +245,6 @@ public abstract class AbstractCodeBrowserPlugin
ex @Override public void serviceRemoved(Class> interfaceClass, Object service) { - if (interfaceClass == TableService.class) { - if (tool != null) { - tool.removeAction(tableFromSelectionAction); - tool.removeAction(showXrefsAction); - } - } if ((service == viewManager) && (currentProgram != null)) { viewManager = null; viewChanged(currentProgram.getMemory()); @@ -666,81 +643,6 @@ public abstract class AbstractCodeBrowserPlugin
ex } - public void initActions() { - - // note: these actions gets added later when the TableService is added - - tableFromSelectionAction = new DockingAction("Create Table From Selection", getName()) { - ImageIcon markerIcon = ResourceManager.loadImage("images/searchm_obj.gif"); - - @Override - public void actionPerformed(ActionContext context) { - Listing listing = currentProgram.getListing(); - ProgramSelection selection = connectedProvider.getSelection(); - CodeUnitIterator codeUnits = listing.getCodeUnits(selection, true); - TableService tableService = tool.getService(TableService.class); - if (!codeUnits.hasNext()) { - tool.setStatusInfo( - "Unable to create table from selection: no " + "code units in selection"); - return; - } - - GhidraProgramTableModel
model = createTableModel(codeUnits, selection); - String title = "Selection Table"; - TableComponentProvider tableProvider = - tableService.showTableWithMarkers(title + " " + model.getName(), "Selection", - model, PluginConstants.SEARCH_HIGHLIGHT_COLOR, markerIcon, title, null); - tableProvider.installRemoveItemsAction(); - } - - @Override - public boolean isEnabledForContext(ActionContext context) { - ProgramSelection programSelection = connectedProvider.getSelection(); - return programSelection != null && !programSelection.isEmpty(); - } - }; - - tableFromSelectionAction.setEnabled(false); - tableFromSelectionAction.setMenuBarData(new MenuData( - new String[] { ToolConstants.MENU_SELECTION, "Create Table From Selection" }, null, - "SelectUtils")); - tableFromSelectionAction - .setHelpLocation(new HelpLocation("CodeBrowserPlugin", "Selection_Table")); - - showXrefsAction = new ActionBuilder("Show Xrefs", getName()) - .description("Show the Xrefs to the code unit containing the cursor") - .validContextWhen(context -> context instanceof ListingActionContext) - .onAction(context -> showXrefs(context)) - .build(); - } - - private void showXrefs(ActionContext context) { - - TableService service = tool.getService(TableService.class); - if (service == null) { - return; - } - - ListingActionContext lac = (ListingActionContext) context; - ProgramLocation location = lac.getLocation(); - if (location == null) { - return; // not sure if this can happen - } - - Setex } } - private class CodeUnitFromSelectionTableModelLoader implements TableModelLoader
{ - - private CodeUnitIterator iterator; - private ProgramSelection selection; - - CodeUnitFromSelectionTableModelLoader(CodeUnitIterator iterator, - ProgramSelection selection) { - this.iterator = iterator; - this.selection = selection; - } - - @Override - public void load(Accumulator accumulator, TaskMonitor monitor) - throws CancelledException { - - long size = selection.getNumAddresses(); - monitor.initialize(size); - - while (iterator.hasNext()) { - monitor.checkCanceled(); - CodeUnit cu = iterator.next(); - accumulator.add(cu.getMinAddress()); - monitor.incrementProgress(cu.getLength()); - } - } - } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java index 93fffa3da2..4a68f3c545 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java @@ -15,15 +15,28 @@ */ package ghidra.app.plugin.core.codebrowser; +import javax.swing.ImageIcon; + import docking.action.builder.ActionBuilder; import docking.tool.ToolConstants; import ghidra.app.CorePluginPackage; import ghidra.app.plugin.PluginCategoryNames; +import ghidra.app.plugin.core.table.TableComponentProvider; import ghidra.app.util.HelpTopics; +import ghidra.app.util.PluginConstants; +import ghidra.app.util.query.TableService; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginStatus; +import ghidra.program.model.address.Address; +import ghidra.program.model.listing.*; import ghidra.program.util.ProgramSelection; import ghidra.util.HelpLocation; +import ghidra.util.Msg; +import ghidra.util.datastruct.Accumulator; +import ghidra.util.exception.CancelledException; +import ghidra.util.table.*; +import ghidra.util.task.TaskMonitor; +import resources.ResourceManager; /** * Plugin for adding some basic selection actions for Code Browser Listings. @@ -78,6 +91,77 @@ public class CodeBrowserSelectionPlugin extends Plugin { .onAction(c -> ((CodeViewerProvider) c.getComponentProvider()).selectComplement()) .buildAndInstall(tool); + new ActionBuilder("Create Table From Selection", getName()) + .menuPath(ToolConstants.MENU_SELECTION, "Create Table From Selection") + .menuGroup("SelectUtils") + .helpLocation(new HelpLocation("CodeBrowserPlugin", "Selection_Table")) + .supportsDefaultToolContext(true) + .withContext(CodeViewerActionContext.class) + .inWindow(ActionBuilder.When.CONTEXT_MATCHES) + .onAction(c -> createTable((CodeViewerProvider) c.getComponentProvider())) + .buildAndInstall(tool); } + private void createTable(CodeViewerProvider componentProvider) { + TableService tableService = tool.getService(TableService.class); + if (tableService == null) { + Msg.showWarn(this, null, "No Table Service", "Please add the TableServicePlugin."); + return; + } + Program program = componentProvider.getProgram(); + Listing listing = program.getListing(); + + ProgramSelection selection = componentProvider.getSelection(); + CodeUnitIterator codeUnits = listing.getCodeUnits(selection, true); + if (!codeUnits.hasNext()) { + tool.setStatusInfo( + "Unable to create table from selection: no " + "code units in selection"); + return; + } + + GhidraProgramTableModel model = createTableModel(program, codeUnits, selection); + String title = "Selection Table"; + ImageIcon markerIcon = ResourceManager.loadImage("images/searchm_obj.gif"); + TableComponentProvider tableProvider = + tableService.showTableWithMarkers(title + " " + model.getName(), "Selection", + model, PluginConstants.SEARCH_HIGHLIGHT_COLOR, markerIcon, title, null); + tableProvider.installRemoveItemsAction(); + } + + private GhidraProgramTableModel createTableModel(Program program, + CodeUnitIterator iterator, ProgramSelection selection) { + + CodeUnitFromSelectionTableModelLoader loader = + new CodeUnitFromSelectionTableModelLoader(iterator, selection); + + return new CustomLoadingAddressTableModel(" - from " + selection.getMinAddress(), tool, + program, loader, null, true); + } + + private class CodeUnitFromSelectionTableModelLoader implements TableModelLoader { + + private CodeUnitIterator iterator; + private ProgramSelection selection; + + CodeUnitFromSelectionTableModelLoader(CodeUnitIterator iterator, + ProgramSelection selection) { + this.iterator = iterator; + this.selection = selection; + } + + @Override + public void load(Accumulator accumulator, TaskMonitor monitor) + throws CancelledException { + + long size = selection.getNumAddresses(); + monitor.initialize(size); + + while (iterator.hasNext()) { + monitor.checkCanceled(); + CodeUnit cu = iterator.next(); + accumulator.add(cu.getMinAddress()); + monitor.incrementProgress(cu.getLength()); + } + } + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPlugin.java index 582c26b387..9bda8c8696 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPlugin.java @@ -17,7 +17,9 @@ package ghidra.app.plugin.core.navigation.locationreferences; import java.util.*; +import docking.ActionContext; import docking.action.DockingAction; +import docking.action.builder.ActionBuilder; import ghidra.app.CorePluginPackage; import ghidra.app.context.ListingActionContext; import ghidra.app.events.ProgramClosedPluginEvent; @@ -26,12 +28,15 @@ import ghidra.app.plugin.PluginCategoryNames; import ghidra.app.plugin.core.navigation.FindAppliedDataTypesService; import ghidra.app.services.GoToService; import ghidra.app.services.ProgramManager; +import ghidra.app.util.XReferenceUtils; +import ghidra.app.util.query.TableService; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.program.model.data.Composite; import ghidra.program.model.data.DataType; import ghidra.program.model.listing.Program; +import ghidra.program.model.symbol.Reference; import ghidra.program.util.ProgramLocation; import ghidra.util.HelpLocation; import ghidra.util.Msg; @@ -104,6 +109,34 @@ public class LocationReferencesPlugin extends Plugin // that point. // DeleteTableRowAction.registerDummy(tool, getName()); + + // Note: the following action has no access (no menu path, no key binding, etc.) It exists + // only so the user can bind a key binding to it if they wish. + new ActionBuilder("Show Xrefs", getName()) + .description("Show the Xrefs to the code unit containing the cursor") + .validContextWhen(context -> context instanceof ListingActionContext) + .helpLocation(new HelpLocation("CodeBrowserPlugin", "Show_Xrefs")) + .onAction(context -> showXrefs(context)) + .buildAndInstall(tool); + + } + + private void showXrefs(ActionContext context) { + + TableService service = tool.getService(TableService.class); + if (service == null) { + Msg.showWarn(this, null, "No Table Service", "Please add the TableServicePlugin."); + return; + } + + ListingActionContext lac = (ListingActionContext) context; + ProgramLocation location = lac.getLocation(); + if (location == null) { + return; // not sure if this can happen + } + + Set