diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java index ca4d04dfc9..cca3d31bb4 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerBreakpointsProvider.java @@ -851,9 +851,6 @@ public class DebuggerBreakpointsProvider extends ComponentProviderAdapter } private void locationDeleted(TraceBreakpointLocation location) { - if (!isVisible(location)) { - return; - } breakpointLocationRemoved(location); } diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java index 4a9bf27c93..41a286df92 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/breakpoint/PlaceEmuBreakpointActionItem.java @@ -104,7 +104,7 @@ public record PlaceEmuBreakpointActionItem(Trace trace, long snap, Address addre try (Transaction tx = trace.openTransaction("Place Emulated Breakpoint")) { // Defaults with emuEnable=true TraceBreakpointLocation loc = trace.getBreakpointManager() - .addBreakpoint(computePath(), Lifespan.at(snap), + .addBreakpoint(computePath(), Lifespan.ALL, BreakpointActionItem.range(address, length), Set.of(), kinds, false, null); loc.setName(snap, createName(address)); loc.setEmuSleigh(snap, emuSleigh); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java index 020e43a58c..56fa44bb94 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/AbstractDebuggerBreakpointsProviderTest.java @@ -99,6 +99,9 @@ public abstract class AbstractDebuggerBreakpointsProviderTest protected abstract void handleToggleBreakpointInvocation( TraceBreakpointLocation expectedBreakpoint, boolean expectedEnabled) throws Throwable; + protected abstract void handleDeleteBreakpointInvocation(T target, + TraceBreakpointLocation expectedLoc) throws Throwable; + protected void addStaticMemoryAndBreakpoint() throws LockException, DuplicateNameException, MemoryConflictException, AddressOverflowException, CancelledException { try (Transaction tx = program.openTransaction("Add bookmark break")) { @@ -121,6 +124,7 @@ public abstract class AbstractDebuggerBreakpointsProviderTest protected void assertProviderEmpty() { assertTrue(breakpointsProvider.breakpointTableModel.getModelData().isEmpty()); + assertTrue(breakpointsProvider.locationTableModel.getModelData().isEmpty()); } @Before @@ -454,10 +458,23 @@ public abstract class AbstractDebuggerBreakpointsProviderTest } @Test - public void testActionClearSelectedBreakpoints() throws Exception { - createProgram(); + public void testActionClearSelectedBreakpoints() throws Throwable { + T target = createTarget1(); + Trace trace = getTrace(target); + createProgramFromTrace(trace); + intoProject(trace); + intoProject(program); + addMapping(trace, program); + addLiveMemoryAndBreakpoint(getProcess1(), target); programManager.openProgram(program); - waitForSwing(); + traceManager.openTrace(trace); + traceManager.activateTrace(trace); + waitForPass(() -> { + LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints()); + assertEquals(program, lb.getProgram()); + assertEquals(Set.of(trace), lb.getParticipatingTraces()); + assertEquals(State.ENABLED, lb.computeState()); + }); assertFalse(breakpointsProvider.actionClearSelectedBreakpoints.isEnabled()); @@ -466,6 +483,7 @@ public abstract class AbstractDebuggerBreakpointsProviderTest assertFalse(breakpointsProvider.actionClearSelectedBreakpoints.isEnabled()); + LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints()); LogicalBreakpointRow row = Unique.assertOne(breakpointsProvider.breakpointTableModel.getModelData()); breakpointsProvider.breakpointFilterPanel.setSelectedItem(row); @@ -485,29 +503,91 @@ public abstract class AbstractDebuggerBreakpointsProviderTest performAction(breakpointsProvider.actionClearSelectedBreakpoints); + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); + lb.delete(); + handleDeleteBreakpointInvocation(target, brk); + assertProviderEmpty(); assertFalse(breakpointsProvider.actionClearSelectedBreakpoints.isEnabled()); } @Test - public void testActionClearAllBreakpoints() throws Exception { - createProgram(); + public void testActionClearAllBreakpoints() throws Throwable { + T target = createTarget1(); + Trace trace = getTrace(target); + createProgramFromTrace(trace); + intoProject(trace); + intoProject(program); + programManager.openProgram(program); - waitForSwing(); + traceManager.openTrace(trace); + traceManager.activateTrace(trace); assertFalse(breakpointsProvider.actionClearAllBreakpoints.isEnabled()); + addMapping(trace, program); + addLiveMemoryAndBreakpoint(getProcess1(), target); + waitForPass(() -> { + LogicalBreakpoint lb = Unique.assertOne(breakpointService.getAllBreakpoints()); + assertEquals(program, lb.getProgram()); + assertEquals(Set.of(trace), lb.getParticipatingTraces()); + assertEquals(State.ENABLED, lb.computeState()); + }); addStaticMemoryAndBreakpoint(); waitForDomainObject(program); assertTrue(breakpointsProvider.actionClearAllBreakpoints.isEnabled()); performAction(breakpointsProvider.actionClearAllBreakpoints); + for (LogicalBreakpoint lb : breakpointService.getAllBreakpoints()) { + TraceBreakpointLocation brk = Unique.assertOne(lb.getTraceBreakpoints(tb.trace)); + lb.delete(); + handleDeleteBreakpointInvocation(target, brk); + } assertProviderEmpty(); assertFalse(breakpointsProvider.actionClearAllBreakpoints.isEnabled()); } + @Test + public void testClearEmuBreakpoint() throws Throwable { + DebuggerControlService controlService = addPlugin(tool, + DebuggerControlServicePlugin.class); + + T target = createTarget1(); + Trace trace = getTrace(target); + controlService.setCurrentMode(trace, ControlMode.RW_EMULATOR); + createProgramFromTrace(trace); + intoProject(trace); + intoProject(program); + addMapping(trace, program); + addStaticMemoryAndBreakpoint(); + addLiveMemory(getProcess1()); + programManager.openProgram(program); + traceManager.openTrace(trace); + traceManager.activateTrace(trace); + + LogicalBreakpointRow row = waitForPass(() -> { + LogicalBreakpointRow newRow = + Unique.assertOne(breakpointsProvider.breakpointTableModel.getModelData()); + LogicalBreakpoint lb = newRow.getLogicalBreakpoint(); + assertEquals(program, lb.getProgram()); + assertEquals(Set.of(trace), lb.getMappedTraces()); + assertEquals(Set.of(), lb.getParticipatingTraces()); + assertEquals(State.INEFFECTIVE_ENABLED, newRow.getState()); + return newRow; + }); + row.setEnabled(true); + + breakpointsProvider.breakpointFilterPanel.setSelectedItem(row); + waitForSwing(); + + performAction(breakpointsProvider.actionClearSelectedBreakpoints); + waitForSwing(); + + assertProviderEmpty(); + } + @Test public void testActionMakeBreakpointsEffective() throws Throwable { DebuggerConsolePlugin consolePlugin = addPlugin(tool, DebuggerConsolePlugin.class); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java index cccf32b73b..6ec7bc382a 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/app/plugin/core/debug/gui/breakpoint/DebuggerRmiBreakpointsProviderTest.java @@ -139,6 +139,20 @@ public class DebuggerRmiBreakpointsProviderTest } } + @Override + protected void handleDeleteBreakpointInvocation(TraceRmiTarget target, + TraceBreakpointLocation expectedLoc) throws Throwable { + Map args = rmiMethodDeleteBreak.expect(); + try (Transaction tx = tb.startTransaction()) { + expectedLoc.getObject().removeTree(Lifespan.nowOn(target.getSnap())); + } + waitForDomainObject(tb.trace); + rmiMethodDeleteBreak.result(null); + assertEquals( + Map.ofEntries(Map.entry("breakpoint", expectedLoc.getSpecification().getObject())), + args); + } + @Override protected void handleToggleBreakpointInvocation(TraceBreakpointLocation expectedLoc, boolean expectedEn) throws Throwable {