diff --git a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm index 61e648d8e0..3ea8baa9cb 100644 --- a/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm +++ b/Ghidra/Features/Base/src/main/help/help/topics/CodeBrowserPlugin/CodeBrowser.htm @@ -111,21 +111,27 @@ "help/topics/Tool/ToolOptions_Dialog.htm">Edit Tool Options dialog for control over certain Navigation behaviors.

+ +

In the XRef field, sometimes there are too many addresses to display so the the field will display "[more]" to indicate that one or more cross-reference addresses are not shown.

Double-clicking on the "[more]" text will cause a Location - References Dialog to appear. Also, double-clicking on the XREF header text (XREF[n]:) will too show this dialog.

+ "green">XREF[n]: or [more]" text will cause a + dialog containing all the Xrefs to appear.

+

+ This differs from the + Show References to ... feature in that the Xrefs dialog is simply a display + of what already exists in the database, whereas Show References to ... will + perform a search to find references additional to what is in the database. +

This dialog lists all the Xref addresses, any labels that are at that address and a preview of the instruction at that address. Clicking on any row in the table will cause - the browser to navigate to that address. Double-clicking will navigate and dismiss the - dialog.

+ the browser to navigate to that address

Keyboard Controls

diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationActionContext.java b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationActionContext.java index 6e6018c5a0..d4c40daf1f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationActionContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/context/ProgramLocationActionContext.java @@ -69,7 +69,8 @@ public class ProgramLocationActionContext extends ProgramActionContext { } /** - * @return the code unit at the action's program location or null + * Returns the code unit containing the action's program location or null + * @return the code unit containing the action's program location or null */ public CodeUnit getCodeUnit() { if (!codeUnitInitialized) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java index b274c5d4ad..8e5c3411e9 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserPlugin.java @@ -21,6 +21,7 @@ import java.awt.event.MouseEvent; import java.math.BigInteger; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; import javax.swing.ImageIcon; import javax.swing.JComponent; @@ -32,12 +33,14 @@ import org.jdom.Element; 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.*; import ghidra.GhidraOptions; import ghidra.app.CorePluginPackage; +import ghidra.app.context.ListingActionContext; import ghidra.app.events.*; import ghidra.app.nav.Navigatable; import ghidra.app.plugin.PluginCategoryNames; @@ -60,6 +63,7 @@ import ghidra.framework.plugintool.*; import ghidra.framework.plugintool.util.PluginStatus; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; +import ghidra.program.model.symbol.Reference; import ghidra.program.util.ProgramLocation; import ghidra.program.util.ProgramSelection; import ghidra.util.*; @@ -121,6 +125,8 @@ public class CodeBrowserPlugin extends Plugin private FocusingMouseListener focusingMouseListener = new FocusingMouseListener(); private DockingAction tableFromSelectionAction; + private DockingAction showXrefsAction; + private Color cursorHighlightColor; private boolean isHighlightCursorLine; private ProgramDropProvider dndProvider; @@ -440,6 +446,7 @@ public class CodeBrowserPlugin extends Plugin 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; @@ -471,6 +478,7 @@ public class CodeBrowserPlugin extends Plugin if (interfaceClass == TableService.class) { if (tool != null) { tool.removeAction(tableFromSelectionAction); + tool.removeAction(showXrefsAction); } } if ((service == viewManager) && (currentProgram != null)) { @@ -902,6 +910,9 @@ public class CodeBrowserPlugin extends Plugin } 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"); @@ -932,13 +943,35 @@ public class CodeBrowserPlugin extends Plugin } }; - // note: this action gets added later when the TableService is added 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 + } + + Supplier> refs = () -> XReferenceUtil.getAllXrefs(location); + XReferenceUtil.showAllXrefs(connectedProvider, tool, service, location, refs); } private GhidraProgramTableModel
createTableModel(CodeUnitIterator iterator, diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java index 0ff677a42c..ff7d25c0fe 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java @@ -449,6 +449,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter action = new GotoNextFunctionAction(tool, plugin.getName()); tool.addAction(action); + } void fieldOptionChanged(String fieldName, Object newValue) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPanel.java index a7d27011a5..7b345cffb3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/navigation/locationreferences/LocationReferencesPanel.java @@ -22,7 +22,6 @@ import java.util.Collection; import javax.swing.JPanel; import javax.swing.ListSelectionModel; -import javax.swing.border.TitledBorder; import javax.swing.event.TableModelListener; import ghidra.app.services.GoToService; @@ -57,7 +56,6 @@ public class LocationReferencesPanel extends JPanel { table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); setLayout(new BorderLayout(10, 10)); - setBorder(new TitledBorder("Reference(s)")); PluginTool tool = locationReferencesProvider.getTool(); GoToService goToService = tool.getService(GoToService.class); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/XReferenceUtil.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/XReferenceUtil.java index b86ff6fa2c..b0b895840a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/XReferenceUtil.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/XReferenceUtil.java @@ -16,14 +16,24 @@ package ghidra.app.util; import java.util.*; +import java.util.function.Supplier; +import org.apache.commons.collections4.CollectionUtils; + +import ghidra.app.nav.Navigatable; +import ghidra.app.plugin.core.table.TableComponentProvider; +import ghidra.app.util.query.TableService; +import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.*; +import ghidra.program.util.ProgramLocation; +import ghidra.util.table.ReferencesFromTableModel; +import ghidra.util.table.field.ReferenceEndpoint; /** * A utility class to handle the generation of - * direct and offcut cross-reference (XREF) lists + * direct and offcut cross-reference (xref) lists * on code units and stack variables. */ public class XReferenceUtil { @@ -36,11 +46,11 @@ public class XReferenceUtil { /** * Returns an array containing all - * direct XREF addresses to the specified code unit. + * direct xref addresses to the specified code unit. * - * @param cu the code unit to generate the XREFs + * @param cu the code unit to generate the xrefs * - * @return array of all XREFs to the code unit + * @return array of all xrefs to the code unit */ public final static Address[] getXRefList(CodeUnit cu) { return getXRefList(cu, -1); // get all @@ -48,13 +58,13 @@ public class XReferenceUtil { /** * Returns an array containing the first maxNumber - * direct XREF addresses to the specified code unit. + * direct xref addresses to the specified code unit. * - * @param cu the code unit to generate the XREFs - * @param maxNumber max number of XREFs to get, + * @param cu the code unit to generate the xrefs + * @param maxNumber max number of xrefs to get, * or -1 to get all references * - * @return array first maxNumber XREFs to the code unit + * @return array first maxNumber xrefs to the code unit */ public final static Address[] getXRefList(CodeUnit cu, int maxNumber) { Program prog = cu.getProgram(); @@ -62,7 +72,7 @@ public class XReferenceUtil { return EMPTY_ADDR_ARRAY; } List
xrefList = new ArrayList
(); - //lookup the direct XREFs to the current code unit + //lookup the direct xrefs to the current code unit // ReferenceIterator iter = prog.getReferenceManager().getReferencesTo(cu.getMinAddress()); while (iter.hasNext()) { @@ -80,13 +90,13 @@ public class XReferenceUtil { /** * Returns an array containing the first maxNumber - * direct XREF references to the specified code unit. + * direct xref references to the specified code unit. * - * @param cu the code unit to generate the XREFs - * @param maxNumber max number of XREFs to get, + * @param cu the code unit to generate the xrefs + * @param maxNumber max number of xrefs to get, * or -1 to get all references * - * @return array first maxNumber XREFs to the code unit + * @return array first maxNumber xrefs to the code unit */ public final static Reference[] getXReferences(CodeUnit cu, int maxNumber) { Program prog = cu.getProgram(); @@ -94,7 +104,7 @@ public class XReferenceUtil { return EMPTY_REF_ARRAY; } List xrefList = new ArrayList(); - //lookup the direct XREFs to the current code unit + //lookup the direct xrefs to the current code unit // ReferenceIterator iter = prog.getReferenceManager().getReferencesTo(cu.getMinAddress()); while (iter.hasNext()) { @@ -121,11 +131,11 @@ public class XReferenceUtil { /** * Returns an array containing all - * offcut XREF addresses to the specified code unit. + * offcut xref addresses to the specified code unit. * - * @param cu the code unit to generate the offcut XREFs + * @param cu the code unit to generate the offcut xrefs * - * @return array of all offcut XREFs to the code unit + * @return array of all offcut xrefs to the code unit */ public final static Address[] getOffcutXRefList(CodeUnit cu) { return getOffcutXRefList(cu, -1); // get all @@ -133,13 +143,13 @@ public class XReferenceUtil { /** * Returns an array containing all - * offcut XREF addresses to the specified code unit. + * offcut xref addresses to the specified code unit. * - * @param cu the code unit to generate the offcut XREFs - * @param maxXRefs max number of offcut XREFs to get, + * @param cu the code unit to generate the offcut xrefs + * @param maxXRefs max number of offcut xrefs to get, * or -1 to get all offcut references * - * @return array of all offcut XREFs to the code unit + * @return array of all offcut xrefs to the code unit */ public final static Address[] getOffcutXRefList(CodeUnit cu, int maxXRefs) { Program prog = cu.getProgram(); @@ -147,7 +157,7 @@ public class XReferenceUtil { return EMPTY_ADDR_ARRAY; } List
offcutList = new ArrayList
(); - // Lookup the offcut XREFs... + // Lookup the offcut xrefs... // if (cu.getLength() > 1) { ReferenceManager refMgr = prog.getReferenceManager(); @@ -173,14 +183,12 @@ public class XReferenceUtil { } /** - * Returns an array containing all - * offcut XREF references to the specified code unit. + * Returns an array containing all offcut xref references to the specified code unit * - * @param cu the code unit to generate the offcut XREFs - * @param maxXRefs max number of offcut XREFs to get, - * or -1 to get all offcut references + * @param cu the code unit to generate the offcut xrefs + * @param maxXRefs max number of offcut xrefs to get, or -1 to get all offcut references * - * @return array of all offcut XREFs to the code unit + * @return array of all offcut xrefs to the code unit */ public final static Reference[] getOffcutXReferences(CodeUnit cu, int maxXRefs) { Program prog = cu.getProgram(); @@ -188,7 +196,7 @@ public class XReferenceUtil { return EMPTY_REF_ARRAY; } List offcutList = new ArrayList(); - // Lookup the offcut XREFs... + // Lookup the offcut xrefs... // if (cu.getLength() > 1) { ReferenceManager refMgr = prog.getReferenceManager(); @@ -214,10 +222,9 @@ public class XReferenceUtil { } /** - * Returns the count of all - * offcut XREF addresses to the specified code unit. - * @param cu the code unit to generate the offcut XREFs - * @return count of all offcut XREFs to the code unit + * Returns the count of all offcut xref addresses to the specified code unit + * @param cu the code unit to generate the offcut xrefs + * @return count of all offcut xrefs to the code unit */ public static int getOffcutXRefCount(CodeUnit cu) { Program prog = cu.getProgram(); @@ -243,18 +250,19 @@ public class XReferenceUtil { } /** - * Populates the provided array lists with the direct and - * offcut XREFs to the specified variable. + * Populates the provided lists with the direct and offcut xrefs to the specified variable * * @param var variable to get references - * @param xrefs list to put direct references on - * @param offcuts list to put offcut references on + * @param xrefs list to put direct references in + * @param offcuts list to put offcut references in */ - public static void getVariableRefs(Variable var, List xrefs, List offcuts) { + public static void getVariableRefs(Variable var, List xrefs, + List offcuts) { Address addr = var.getMinAddress(); if (addr == null) { return; } + Program program = var.getFunction().getProgram(); ReferenceManager refMgr = program.getReferenceManager(); Reference[] vrefs = refMgr.getReferencesTo(var); @@ -269,18 +277,93 @@ public class XReferenceUtil { } /** - * Get the reference count to the min address of the given code unit. - * If an external entry exists there, then subtract one from the count. - * @param cu code unit - * @return reference count, excluding an external entry reference + * Returns the direct and offcut xrefs to the specified variable + * + * @param var variable to get references + * @return the set of references */ - public static int getReferenceCount(CodeUnit cu) { - Program program = cu.getProgram(); - Address toAddr = cu.getMinAddress(); - int count = program.getReferenceManager().getReferenceCountTo(toAddr); - if (program.getSymbolTable().isExternalEntryPoint(toAddr)) { - --count; + public static Set getVariableRefs(Variable var) { + + Set results = new HashSet<>(); + Address addr = var.getMinAddress(); + if (addr == null) { + return results; } - return count; + + Program program = var.getFunction().getProgram(); + ReferenceManager refMgr = program.getReferenceManager(); + Reference[] vrefs = refMgr.getReferencesTo(var); + for (Reference vref : vrefs) { + results.add(vref); + } + return results; + } + + /** + * Shows all xrefs to the given location in a new table. These xrefs are retrieved + * from the given supplier. Thus, it is up to the client to determine which xrefs to show. + * + * @param navigatable the navigatable used for navigation from the table + * @param serviceProvider the service provider needed to wire navigation + * @param service the service needed to show the table + * @param location the location for which to find references + * @param xrefs the supplier of xrefs to show + */ + public static void showAllXrefs(Navigatable navigatable, ServiceProvider serviceProvider, + TableService service, ProgramLocation location, Supplier> xrefs) { + + Set refs = xrefs.get(); + + ReferencesFromTableModel model = + new ReferencesFromTableModel(new ArrayList<>(refs), serviceProvider, + location.getProgram()); + TableComponentProvider provider = service.showTable( + "XRefs to " + location.getAddress().toString(), "XRefs", model, "XRefs", navigatable); + provider.installRemoveItemsAction(); + } + + /** + * Returns all xrefs to the given location. If in data, then xrefs to the specific data + * component will be returned. Otherwise, the code unit containing the address of the + * given location will be used as the source of the xrefs. + * + * @param location the location for which to get xrefs + * @return the xrefs + */ + public static Set getAllXrefs(ProgramLocation location) { + + CodeUnit cu = getImmediateDataContaining(location); + if (cu == null) { + Address toAddress = location.getAddress(); + Listing listing = location.getProgram().getListing(); + cu = listing.getCodeUnitContaining(toAddress); + } + + Reference[] xrefs = getXReferences(cu, ALL_REFS); + Reference[] offcuts = getOffcutXReferences(cu, ALL_REFS); + + // Remove duplicates + Set set = new HashSet<>(); + CollectionUtils.addAll(set, xrefs); + CollectionUtils.addAll(set, offcuts); + return set; + } + + /** + * Returns the nearest {@link Data} object containing a given address. + * + * @param location the program location within the data object + * @return the Data object + */ + private static Data getImmediateDataContaining(ProgramLocation location) { + Address addr = location.getAddress(); + Listing listing = location.getProgram().getListing(); + Data dataContaining = listing.getDataContaining(addr); + if (dataContaining == null) { + return null; + } + + Data dataAtAddr = dataContaining.getComponent(location.getComponentPath()); + return dataAtAddr; } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/VariableXRefFieldMouseHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/VariableXRefFieldMouseHandler.java index c71753f734..4171011fed 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/VariableXRefFieldMouseHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/VariableXRefFieldMouseHandler.java @@ -15,7 +15,8 @@ */ package ghidra.app.util.viewer.field; -import java.util.*; +import java.util.Set; +import java.util.function.Supplier; import ghidra.app.nav.Navigatable; import ghidra.app.util.XReferenceUtil; @@ -28,11 +29,10 @@ import ghidra.program.model.symbol.Reference; import ghidra.program.util.*; /** - * A handler to process {@link VariableXRefFieldLocation} clicks. + * A handler to process {@link VariableXRefFieldLocation} clicks */ public class VariableXRefFieldMouseHandler extends XRefFieldMouseHandler { - private final static Class[] SUPPORTED_CLASSES = new Class[] { VariableXRefFieldLocation.class, VariableXRefHeaderFieldLocation.class }; @@ -60,9 +60,6 @@ public class VariableXRefFieldMouseHandler extends XRefFieldMouseHandler { return ((VariableXRefFieldLocation) programLocation).getIndex(); } - /** - * @see XRefFieldMouseHandler#getSupportedProgramLocations() - */ @Override public Class[] getSupportedProgramLocations() { return SUPPORTED_CLASSES; @@ -80,27 +77,10 @@ public class VariableXRefFieldMouseHandler extends XRefFieldMouseHandler { return; } - Address toAddress = location.getAddress(); - Program program = navigatable.getProgram(); - VariableLocation variableLocation = (VariableLocation) location; Variable variable = variableLocation.getVariable(); - List refs = getReferences(variable); - showReferenceTable(navigatable, serviceProvider, service, toAddress, program, refs); - } - - private List getReferences(Variable variable) { - - List refs = new ArrayList<>(); - List offcutRefs = new ArrayList<>(); - XReferenceUtil.getVariableRefs(variable, refs, offcutRefs); - - // Convert to a set before combining lists, to remove duplicates. - Set refsSet = new HashSet(refs); - Set offcutRefsSet = new HashSet(offcutRefs); - refsSet.addAll(offcutRefsSet); - - return new ArrayList<>(refsSet); + Supplier> refs = () -> XReferenceUtil.getVariableRefs(variable); + XReferenceUtil.showAllXrefs(navigatable, serviceProvider, service, location, refs); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldMouseHandler.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldMouseHandler.java index d3885188fd..e44c22a691 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldMouseHandler.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldMouseHandler.java @@ -16,7 +16,8 @@ package ghidra.app.util.viewer.field; import java.awt.event.MouseEvent; -import java.util.*; +import java.util.Set; +import java.util.function.Supplier; import docking.widgets.fieldpanel.field.FieldElement; import docking.widgets.fieldpanel.field.TextField; @@ -26,14 +27,12 @@ import ghidra.app.util.XReferenceUtil; import ghidra.app.util.query.TableService; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.Address; -import ghidra.program.model.listing.*; +import ghidra.program.model.listing.Program; import ghidra.program.model.symbol.Reference; import ghidra.program.util.*; -import ghidra.util.table.ReferencesFromTableModel; -import util.CollectionUtils; /** - * A handler to process {@link XRefFieldMouseHandler} clicks. + * A handler to process {@link XRefFieldMouseHandler} clicks */ public class XRefFieldMouseHandler implements FieldMouseHandlerExtension { @@ -100,61 +99,15 @@ public class XRefFieldMouseHandler implements FieldMouseHandlerExtension { return ((XRefFieldLocation) programLocation).getIndex(); } - protected void showXRefDialog(Navigatable navigatable, ProgramLocation location, + private void showXRefDialog(Navigatable navigatable, ProgramLocation location, ServiceProvider serviceProvider) { TableService service = serviceProvider.getService(TableService.class); if (service == null) { return; } - Address toAddress = location.getAddress(); - Program program = navigatable.getProgram(); - - CodeUnit cu = getImmediateDataContaining(location, program); - if (cu == null) { - Listing listing = program.getListing(); - cu = listing.getCodeUnitContaining(toAddress); - } - - List refs = getReferences(cu); - showReferenceTable(navigatable, serviceProvider, service, toAddress, program, refs); - } - - protected void showReferenceTable(Navigatable navigatable, ServiceProvider serviceProvider, - TableService service, Address toAddress, Program program, List refs) { - ReferencesFromTableModel model = - new ReferencesFromTableModel(refs, serviceProvider, program); - service.showTable("XRefs to " + toAddress.toString(), "XRefs", model, "XRefs", navigatable); - } - - private List getReferences(CodeUnit cu) { - Reference[] xrefs = XReferenceUtil.getXReferences(cu, XReferenceUtil.ALL_REFS); - Reference[] offcuts = XReferenceUtil.getOffcutXReferences(cu, XReferenceUtil.ALL_REFS); - - // Convert to a set before combining lists, to remove duplicates. - Set set = CollectionUtils.asSet(xrefs); - set.addAll(Arrays.asList(offcuts)); - - return new ArrayList<>(set); - } - - /** - * Returns the nearest {@link Data} object containing a given address. - * - * @param location the program location within the data object - * @param program the current program - * @return the Data object - */ - private Data getImmediateDataContaining(ProgramLocation location, Program program) { - Address addr = location.getAddress(); - Listing listing = program.getListing(); - Data dataContaining = listing.getDataContaining(addr); - if (dataContaining == null) { - return null; - } - - Data dataAtAddr = dataContaining.getComponent(location.getComponentPath()); - return dataAtAddr; + Supplier> refs = () -> XReferenceUtil.getAllXrefs(location); + XReferenceUtil.showAllXrefs(navigatable, serviceProvider, service, location, refs); } protected ProgramLocation getReferredToLocation(Navigatable sourceNavigatable, diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java index 3327586c85..797a05fb98 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentPlaceholder.java @@ -24,6 +24,7 @@ import javax.swing.*; import docking.action.DockingAction; import docking.action.DockingActionIf; +import ghidra.util.Swing; import ghidra.util.exception.AssertException; /** @@ -60,10 +61,14 @@ public class ComponentPlaceholder { /** * XML Constructor!!!!! - * @param name the name of the component. - * @param owner the owner of the component. - * @param show whether or not the component is showing. - * @param node componentNode that has this placeholder. + * + * @param name the name of the component + * @param owner the owner of the component + * @param group the window group + * @param title the title + * @param show whether or not the component is showing + * @param node componentNode that has this placeholder + * @param instanceID the instance ID */ ComponentPlaceholder(String name, String owner, String group, String title, boolean show, ComponentNode node, long instanceID) { @@ -83,7 +88,8 @@ public class ComponentPlaceholder { } /** - * Returns the componentNode containing this placeholder. + * Returns the componentNode containing this placeholder + * @return the node */ ComponentNode getNode() { return compNode; @@ -111,7 +117,8 @@ public class ComponentPlaceholder { } /** - * Returns true if the component is not hidden. + * Returns true if the component is not hidden + * @return true if showing */ boolean isShowing() { return isShowing && componentProvider != null; @@ -234,19 +241,21 @@ public class ComponentPlaceholder { * Requests focus for the component associated with this placeholder. */ void requestFocus() { - if (comp != null) { - compNode.makeSelectedTab(this); - activateWindow(); - - // make sure the tab has time to become active before trying to request focus - comp.requestFocus(); - final Component tmp = comp;// put in temp variable in case another thread deletes it - SwingUtilities.invokeLater(() -> { - if (tmp != null) { - tmp.requestFocus(); - } - }); + Component tmp = comp;// put in temp variable in case another thread deletes it + if (tmp == null) { + return; } + + compNode.makeSelectedTab(this); + activateWindow(); + + // make sure the tab has time to become active before trying to request focus + tmp.requestFocus(); + + Swing.runLater(() -> { + tmp.requestFocus(); + contextChanged(); + }); } // makes sure that the given window is not in an iconified state @@ -273,7 +282,8 @@ public class ComponentPlaceholder { } /** - * Returns a Dockable component that wraps the component for this placeholder. + * Returns a Dockable component that wraps the component for this placeholder + * @return the component */ public DockableComponent getComponent() { if (disposed) { @@ -307,8 +317,8 @@ public class ComponentPlaceholder { } /** - * Returns the title for this component. - * @return the title for this component. + * Returns the title for this component + * @return the title for this component */ public String getTitle() { return title; @@ -339,14 +349,16 @@ public class ComponentPlaceholder { } /** - * Returns the owner for the component. + * Returns the owner for the component + * @return the owner */ String getOwner() { return owner; } /** - * Returns the component associated with this placeholder. + * Returns the component associated with this placeholder + * @return the component */ JComponent getProviderComponent() { if (componentProvider != null) { @@ -356,7 +368,8 @@ public class ComponentPlaceholder { } /** - * Returns true if this placeholder's component is currently in a tabbed pane with other components. + * Returns true if this placeholder's component is in a tabbed pane with other components + * @return true if in a tabbed pane */ boolean isStacked() { if (compNode != null) { @@ -368,13 +381,15 @@ public class ComponentPlaceholder { /** * Returns true if this placeholder is currently associated with a component. If it is not, * then it exists as a place holder. + * @return true if this placeholder is currently associated with a component */ boolean hasProvider() { return componentProvider != null; } /** - * Sets the component provider for this placeholder. + * Sets the component provider for this placeholder + * @param newProvider the new provider */ void setProvider(ComponentProvider newProvider) { this.componentProvider = newProvider; @@ -488,15 +503,16 @@ public class ComponentPlaceholder { } /** - * Return iterator over all the local actions defined for this component. + * Return iterator over all the local actions defined for this component + * @return the actions */ Iterator getActions() { return actions.iterator(); } /** - * notifies the node that this component has focus. - * + * Notifies the node that this component has focus + * @param state the state */ void setSelected(boolean state) { if (comp != null) {