Merge remote-tracking branch

'origin/GP-6365-dragonmacher-find-refs-action-update--SQUASHED'
(Closes #8899)
This commit is contained in:
Ryan Kurtz
2026-01-27 04:44:54 -05:00
11 changed files with 173 additions and 59 deletions

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,10 +15,14 @@
*/
package ghidra.app.actions;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.KeyBindingType;
import ghidra.app.context.NavigatableActionContext;
import ghidra.app.context.NavigatableContextAction;
import ghidra.app.context.ProgramLocationSupplierContext;
import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesService;
import ghidra.app.services.GoToService;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
@@ -33,7 +37,7 @@ import ghidra.util.Msg;
* context for more information, potentially searching for more than just direct references to
* the code unit at the current address.
*/
public abstract class AbstractFindReferencesToAddressAction extends NavigatableContextAction {
public abstract class AbstractFindReferencesToAddressAction extends DockingAction {
public static final String NAME = "Show References To Address";
private static final String HELP_TOPIC = "LocationReferencesPlugin";
@@ -44,12 +48,34 @@ public abstract class AbstractFindReferencesToAddressAction extends NavigatableC
super(NAME, owner, KeyBindingType.SHARED);
this.tool = tool;
setDescription("Shows references to the current Instruction or Data");
setDescription("Shows references to the current address");
setHelpLocation(new HelpLocation(HELP_TOPIC, "Show_Refs_To_Code_Unit"));
setContextClass(ProgramLocationSupplierContext.class, true);
}
@Override
public void actionPerformed(NavigatableActionContext context) {
public void actionPerformed(ActionContext context) {
ProgramLocationSupplierContext plc = (ProgramLocationSupplierContext) context;
Navigatable navigatable = null;
if (plc instanceof NavigatableActionContext nac) {
navigatable = nac.getNavigatable();
}
else {
GoToService goToService = tool.getService(GoToService.class);
if (goToService == null) {
Msg.showError(this, null, "Missing Plugin",
"The " + GoToService.class.getSimpleName() + " is not installed.\n" +
"Please add the plugin implementing this service.");
return;
}
navigatable = goToService.getDefaultNavigatable();
}
showReferences(plc, navigatable);
}
private void showReferences(ProgramLocationSupplierContext context, Navigatable navigatable) {
LocationReferencesService service = tool.getService(LocationReferencesService.class);
if (service == null) {
@@ -59,8 +85,8 @@ public abstract class AbstractFindReferencesToAddressAction extends NavigatableC
return;
}
Program program = context.getProgram();
ProgramLocation location = getLocation(context);
ProgramLocation location = context.getLocation();
Program program = location.getProgram();
Address address = location.getAddress();
Listing listing = program.getListing();
CodeUnit cu = listing.getCodeUnitContaining(address);
@@ -74,14 +100,19 @@ public abstract class AbstractFindReferencesToAddressAction extends NavigatableC
AddressFieldLocation addressLocation =
new AddressFieldLocation(program, address, path, address.toString(), 0);
service.showReferencesToLocation(addressLocation, context.getNavigatable());
service.showReferencesToLocation(addressLocation, navigatable);
}
@Override
protected boolean isEnabledForContext(NavigatableActionContext context) {
public boolean isEnabledForContext(ActionContext context) {
ProgramLocationSupplierContext plc = (ProgramLocationSupplierContext) context;
if (plc instanceof NavigatableActionContext nac) {
if (!isMyNavigatable(nac)) {
return false;
}
}
Program program = context.getProgram();
ProgramLocation location = getLocation(context);
ProgramLocation location = plc.getLocation();
if (location == null) {
return false;
}
@@ -91,6 +122,7 @@ public abstract class AbstractFindReferencesToAddressAction extends NavigatableC
return false;
}
Program program = location.getProgram();
Listing listing = program.getListing();
CodeUnit cu = listing.getCodeUnitContaining(address);
if (cu == null) {
@@ -100,7 +132,5 @@ public abstract class AbstractFindReferencesToAddressAction extends NavigatableC
return true;
}
protected ProgramLocation getLocation(NavigatableActionContext context) {
return context.getLocation();
}
protected abstract boolean isMyNavigatable(NavigatableActionContext context);
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -23,7 +23,7 @@ import ghidra.program.model.listing.Function;
/**
* A "mix-in" interface that specific implementers of {@link ActionContext} may also implement if
* they can supply functions in their action context. Actions that want to work on functions
* can look for this interface, which can used in a variety of contexts.
* can look for this interface, which can be used in a variety of contexts.
*/
public interface FunctionSupplierContext extends ActionContext {

View File

@@ -15,6 +15,7 @@
*/
package ghidra.app.context;
import java.awt.Component;
import java.util.HashSet;
import java.util.Set;
@@ -24,7 +25,7 @@ import ghidra.program.model.listing.*;
import ghidra.program.util.*;
public class ProgramLocationActionContext extends ProgramActionContext
implements FunctionSupplierContext {
implements FunctionSupplierContext, ProgramLocationSupplierContext {
private final ProgramLocation location;
private final ProgramSelection selection;
@@ -41,9 +42,15 @@ public class ProgramLocationActionContext extends ProgramActionContext
this.highlight = highlight;
}
/**
* @return Returns the program location.
*/
public ProgramLocationActionContext(ComponentProvider provider, Program program,
Component sourceComponent, ProgramLocation location) {
super(provider, program, sourceComponent);
this.location = location;
this.selection = null;
this.highlight = null;
}
@Override
public ProgramLocation getLocation() {
return location;
}

View File

@@ -0,0 +1,32 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.context;
import docking.ActionContext;
import ghidra.program.util.ProgramLocation;
/**
* A "mix-in" interface that specific implementers of {@link ActionContext} may also implement if
* they can supply a program location in their action context. Actions that want to work on
* locations can look for this interface, which can be used in a variety of contexts.
*/
public interface ProgramLocationSupplierContext extends ActionContext {
/**
* {@return the program location}
*/
public ProgramLocation getLocation();
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,8 +21,10 @@ import java.util.*;
import docking.ComponentProvider;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.ProgramLocation;
public class ProgramSymbolActionContext extends ProgramActionContext {
public class ProgramSymbolActionContext extends ProgramActionContext
implements ProgramLocationSupplierContext {
private List<Symbol> symbols = new ArrayList<Symbol>();
@@ -46,4 +48,13 @@ public class ProgramSymbolActionContext extends ProgramActionContext {
public Iterable<Symbol> getSymbols() {
return symbols;
}
@Override
public ProgramLocation getLocation() {
if (symbols.isEmpty()) {
return null;
}
Symbol s = symbols.get(0);
return s.getProgramLocation();
}
}

View File

@@ -182,7 +182,7 @@ public class BookmarkPlugin extends ProgramPlugin implements PopupActionProvider
DockingAction selectionAction = new DockingAction("Select Bookmark Locations", getName()) {
@Override
public void actionPerformed(ActionContext context) {
select(provider.getBookmarkLocations());
select(provider.getBookmarkSelection());
}
};
icon = new GIcon("icon.plugin.bookmark.select");

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -30,13 +30,16 @@ import docking.action.KeyBindingData;
import docking.widgets.combobox.GhidraComboBox;
import docking.widgets.table.GTable;
import ghidra.app.context.ProgramActionContext;
import ghidra.app.context.ProgramLocationActionContext;
import ghidra.app.services.GoToService;
import ghidra.framework.cmd.BackgroundCommand;
import ghidra.framework.model.DomainObject;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.HelpLocation;
import ghidra.util.table.*;
@@ -106,7 +109,26 @@ public class BookmarkProvider extends ComponentProviderAdapter {
if (program == null) {
return null;
}
return new ProgramActionContext(this, program, bookmarkTable);
ProgramLocation location = getBookmarkLocation();
return new ProgramLocationActionContext(this, program, bookmarkTable, location);
}
private ProgramLocation getBookmarkLocation() {
int row = bookmarkTable.getSelectedRow();
if (row < 0) {
return null;
}
BookmarkRowObject rowObject = model.getRowObject(row);
if (rowObject == null) {
return null; // this can happen when closing
}
BookmarkManager manager = program.getBookmarkManager();
Bookmark bookmark = manager.getBookmark(rowObject.getKey());
Address address = bookmark.getAddress();
return new ProgramLocation(program, address);
}
void setGoToService(GoToService goToService) {
@@ -339,7 +361,7 @@ public class BookmarkProvider extends ComponentProviderAdapter {
}
}
ProgramSelection getBookmarkLocations() {
ProgramSelection getBookmarkSelection() {
return bookmarkTable.getProgramSelection();
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -29,10 +29,13 @@ import docking.action.DockingAction;
import docking.action.builder.ActionBuilder;
import generic.theme.GIcon;
import ghidra.app.context.FunctionSupplierContext;
import ghidra.app.context.ProgramLocationSupplierContext;
import ghidra.app.services.FunctionComparisonService;
import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.*;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
import ghidra.util.table.*;
import ghidra.util.table.actions.MakeProgramSelectionAction;
@@ -258,24 +261,18 @@ public class FunctionWindowProvider extends ComponentProviderAdapter {
return functionModel;
}
/**
* @see docking.ComponentProvider#getWindowSubMenuName()
*/
@Override
public String getWindowSubMenuName() {
return null;
}
/**
* @see docking.ComponentProvider#isTransient()
*/
@Override
public boolean isTransient() {
return false;
}
private class FunctionWindowActionContext extends DefaultActionContext
implements FunctionSupplierContext {
implements FunctionSupplierContext, ProgramLocationSupplierContext {
FunctionWindowActionContext() {
super(FunctionWindowProvider.this, functionTable);
@@ -300,5 +297,18 @@ public class FunctionWindowProvider extends ComponentProviderAdapter {
}
return functions;
}
@Override
public ProgramLocation getLocation() {
int row = functionTable.getSelectedRow();
if (row < 0) {
return null;
}
FunctionRowObject rowObject = functionModel.getRowObject(row);
Function f = rowObject.getFunction();
Symbol s = f.getSymbol();
return s.getProgramLocation();
}
}
}

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -36,12 +36,9 @@ public class FindReferencesToAddressAction extends AbstractFindReferencesToAddre
}
@Override
public boolean isEnabledForContext(NavigatableActionContext context) {
if (!(context instanceof ListingActionContext)) {
// Restrict this action to the Listing. We have guilty knowledge that there are
// other sibling classes to this one for other contexts.
return false;
}
return super.isEnabledForContext(context);
protected boolean isMyNavigatable(NavigatableActionContext context) {
// Restrict this action to the Listing. We have guilty knowledge that there are
// other sibling classes to this one for other contexts.
return context instanceof ListingActionContext;
}
}

View File

@@ -21,6 +21,7 @@ import java.util.function.Predicate;
import docking.DefaultActionContext;
import ghidra.app.context.DataLocationListContext;
import ghidra.app.context.ProgramLocationSupplierContext;
import ghidra.program.model.data.DataUtilities;
import ghidra.program.model.listing.Data;
import ghidra.program.model.listing.Program;
@@ -28,7 +29,8 @@ import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;
import ghidra.util.table.GhidraTable;
public class DefinedStringsContext extends DefaultActionContext implements DataLocationListContext {
public class DefinedStringsContext extends DefaultActionContext implements DataLocationListContext,
ProgramLocationSupplierContext {
private final DefinedStringsProvider viewStringsProvider;
private final GhidraTable table;
@@ -52,6 +54,15 @@ public class DefinedStringsContext extends DefaultActionContext implements DataL
return viewStringsProvider.getProgram();
}
@Override
public ProgramLocation getLocation() {
int row = table.getSelectedRow();
if (row < 0) {
return null;
}
return tableModel.getRowObject(row);
}
@Override
public List<ProgramLocation> getDataLocationList() {
return getDataLocationList(null);

View File

@@ -24,7 +24,6 @@ import ghidra.app.plugin.core.navigation.locationreferences.LocationReferencesSe
import ghidra.app.util.HelpTopics;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.util.ProgramLocation;
import ghidra.util.HelpLocation;
/**
@@ -40,21 +39,16 @@ public class FindReferencesToAddressAction extends AbstractFindReferencesToAddre
}
@Override
protected ProgramLocation getLocation(NavigatableActionContext context) {
if (!(context instanceof DecompilerActionContext)) {
return null;
}
return context.getLocation();
protected boolean isMyNavigatable(NavigatableActionContext context) {
return context instanceof DecompilerActionContext;
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof DecompilerActionContext)) {
if (!(context instanceof DecompilerActionContext dac)) {
return false;
}
DecompilerActionContext decompilerContext = (DecompilerActionContext) context;
updateMenuName(decompilerContext.getAddress());
updateMenuName(dac.getAddress());
return super.isEnabledForContext(context);
}