diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java index d66d4e6ccd..1c097ad119 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointMarkerPlugin.java @@ -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. @@ -25,9 +25,7 @@ import javax.swing.Icon; import javax.swing.SwingUtilities; import docking.ActionContext; -import docking.Tool; import docking.action.*; -import docking.actions.PopupActionProvider; import generic.theme.GColor; import ghidra.app.context.ProgramLocationActionContext; import ghidra.app.decompiler.*; @@ -88,8 +86,7 @@ import ghidra.util.Msg; DebuggerLogicalBreakpointService.class, MarkerService.class, }) -public class DebuggerBreakpointMarkerPlugin extends Plugin - implements PopupActionProvider { +public class DebuggerBreakpointMarkerPlugin extends Plugin { private static final Color COLOR_BREAKPOINT_ENABLED_MARKER = new GColor("color.debugger.plugin.resources.breakpoint.marker.enabled"); @@ -818,8 +815,6 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin this.autoOptionsWiring = AutoOptions.wireOptions(this); updateDebouncer.addListener(__ -> SwingUtilities.invokeLater(() -> updateAllMarks())); - - tool.addPopupActionProvider(this); } @Override @@ -828,6 +823,14 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin createActions(); } + @Override + protected void dispose() { + super.dispose(); + if (markerService != null) { + markerService.setMarkerClickedListener(null); + } + } + @AutoOptionConsumed( name = DebuggerResources.OPTION_NAME_COLORS_ENABLED_BREAKPOINT_COLORING_BACKGROUND) private void setEnabledBreakpointMarkerBackground(boolean breakpointColoringBackground) { @@ -1041,7 +1044,7 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin } this.breakpointService = breakpointService; if (this.breakpointService != null) { - breakpointService.addChangeListener(updateMarksListener); + this.breakpointService.addChangeListener(updateMarksListener); updateAllMarks(); } } @@ -1089,11 +1092,6 @@ public class DebuggerBreakpointMarkerPlugin extends Plugin tool.setMenuGroup(new String[] { SetBreakpointAction.NAME }, SetBreakpointAction.GROUP); } - @Override - public List getPopupActions(Tool __, ActionContext context) { - return List.of(); // TODO: Actions by individual breakpoint? - } - @Override public void processEvent(PluginEvent event) { if (event instanceof ProgramOpenedPluginEvent) { diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java index af17c8d699..83cb2a39d1 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointMarkerPluginTest.java @@ -19,9 +19,8 @@ import static org.junit.Assert.*; import java.awt.*; import java.awt.event.MouseEvent; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -47,6 +46,8 @@ import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin; import ghidra.app.plugin.core.debug.service.modules.DebuggerStaticMappingUtils; import ghidra.app.plugin.core.decompile.DecompilePlugin; import ghidra.app.plugin.core.decompile.DecompilerProvider; +import ghidra.app.plugin.core.functiongraph.FGProvider; +import ghidra.app.plugin.core.functiongraph.FunctionGraphPlugin; import ghidra.app.services.*; import ghidra.app.util.viewer.listingpanel.ListingPanel; import ghidra.debug.api.breakpoint.LogicalBreakpoint; @@ -88,6 +89,7 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest protected DebuggerBreakpointMarkerPlugin breakpointMarkerPlugin; protected DebuggerListingPlugin listingPlugin; protected CodeBrowserPlugin codeBrowserPlugin; + protected FunctionGraphPlugin functionGraphPlugin; // Not initialized in setup protected DebuggerLogicalBreakpointService breakpointService; protected DebuggerStaticMappingService mappingService; @@ -907,4 +909,64 @@ public abstract class AbstractDebuggerBreakpointMarkerPluginTest } }); } + + @Test + public void testWithFunctionGraphPlugin() throws Throwable { + functionGraphPlugin = addPlugin(tool, FunctionGraphPlugin.class); + + tool.removePlugins(List.of(breakpointMarkerPlugin)); + breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class); + + tool.removePlugins(List.of(functionGraphPlugin)); + } + + protected void toggleInstallFunctionGraphPlugin() throws Throwable { + if (functionGraphPlugin == null) { + functionGraphPlugin = addPlugin(tool, FunctionGraphPlugin.class); + } + else { + tool.removePlugins(List.of(functionGraphPlugin)); + functionGraphPlugin = null; + } + } + + protected void toggleInstallBreakointMarkerPlugin() throws Throwable { + if (breakpointMarkerPlugin == null) { + breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class); + } + else { + tool.removePlugins(List.of(breakpointMarkerPlugin)); + breakpointMarkerPlugin = null; + } + } + + @Test + public void testWithFunctionGraphPluginFrenetically() throws Throwable { + Random rnd = new Random(); + for (int i = 0; i < 100; i++) { + if (rnd.nextBoolean()) { + toggleInstallFunctionGraphPlugin(); + } + else { + toggleInstallBreakointMarkerPlugin(); + } + } + } + + @Test + public void testWithFunctionGraphPluginAndOpenProgram() throws Throwable { + functionGraphPlugin = addPlugin(tool, FunctionGraphPlugin.class); + tool.removePlugins(List.of(breakpointMarkerPlugin)); + + FGProvider functionGraphProvider = waitForComponentProvider(FGProvider.class); + prepareDecompiler(); // Just to get a minimally meaningful program + functionGraphProvider.setVisible(true); + + breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class); + tool.removePlugins(List.of(functionGraphPlugin)); + breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class); + tool.removePlugins(List.of(functionGraphPlugin)); + breakpointMarkerPlugin = addPlugin(tool, DebuggerBreakpointMarkerPlugin.class); + tool.removePlugins(List.of(functionGraphPlugin)); + } }