From eb168f0b1b6e5ac9dd6f3befd34c3a910e004e1b Mon Sep 17 00:00:00 2001 From: Dan <46821332+nsadeveloper789@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:33:34 +0000 Subject: [PATCH] GP-7191: Fix FlatDebuggerAPI register reads when used with emulation. --- .../ghidra/debug/flatapi/FlatDebuggerAPI.java | 111 ++++++++---------- .../flatapi/AbstractFlatDebuggerAPITest.java | 12 +- .../flatapi/DeadFlatDebuggerAPITest.java | 9 +- .../debug/flatapi/FlatDebuggerRmiAPITest.java | 30 ++--- 4 files changed, 74 insertions(+), 88 deletions(-) diff --git a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java index e4f1e4e8e8..bf8db1b8f6 100644 --- a/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java +++ b/Ghidra/Debug/Debugger-api/src/main/java/ghidra/debug/flatapi/FlatDebuggerAPI.java @@ -55,6 +55,7 @@ import ghidra.trace.model.target.TraceObject; import ghidra.trace.model.target.TraceObjectValue; import ghidra.trace.model.target.path.KeyPath; import ghidra.trace.model.thread.TraceThread; +import ghidra.trace.model.time.TraceSnapshot; import ghidra.trace.model.time.schedule.TraceSchedule; import ghidra.util.MathUtilities; import ghidra.util.Swing; @@ -63,7 +64,6 @@ import ghidra.util.task.TaskMonitor; /** * This interface is a flattened version of the Debugger and Trace APIs. - * *

* To use this "mix-in" interface, extend {@link GhidraScript} as you normally would for your * script, but also add this interface to the {@code implements} clause of your script, e.g., @@ -73,7 +73,6 @@ public interface FlatDebuggerAPI { /** * The method used to wait on futures. - * *

* By default, this waits at most 1 minute. * @@ -91,7 +90,6 @@ public interface FlatDebuggerAPI { /** * Get the script state - * *

* This is required to get various debugger services. It should be implemented by virtue of * extending {@link GhidraScript}. @@ -102,7 +100,6 @@ public interface FlatDebuggerAPI { /** * Require a service from the tool - * *

* If the service is missing, an exception is thrown directing the user to run the script from * the Debugger tool. @@ -237,7 +234,6 @@ public interface FlatDebuggerAPI { /** * Get the current thread - * *

* While uncommon, it is possible for there to be a current trace, but no current thread. * @@ -278,7 +274,6 @@ public interface FlatDebuggerAPI { /** * Get the current trace program view - * *

* The view is an adapter for traces that allows them to be used as a {@link Program}. However, * it only works for a chosen snapshot. Typically, {@link TraceProgramView#getSnap()} for this @@ -310,7 +305,6 @@ public interface FlatDebuggerAPI { /** * Get the current frame, 0 being the innermost - * *

* If the target doesn't support frames, this will return 0 * @@ -323,7 +317,6 @@ public interface FlatDebuggerAPI { /** * Get the current snap, i.e., snapshot key - * *

* Snaps are the trace's notion of time. Positive keys should be monotonic with respect to time: * a higher value implies a later point in time. Negative keys do not; they are used as scratch @@ -339,7 +332,6 @@ public interface FlatDebuggerAPI { /** * Get the current emulation schedule - * *

* This constitutes the current snapshot and an optional schedule of emulation steps. If there * is a schedule, then the view's snap will be the destination scratch snap rather than the @@ -353,7 +345,6 @@ public interface FlatDebuggerAPI { /** * Make the given trace the active trace - * *

* If the trace is not already open in the tool, it will be opened automatically * @@ -373,7 +364,6 @@ public interface FlatDebuggerAPI { /** * Make the given thread the active thread - * *

* if the trace is not already open in the tool, it will be opened automatically * @@ -403,7 +393,6 @@ public interface FlatDebuggerAPI { /** * Make the given snapshot the active snapshot - * *

* Activating negative snapshot keys is not recommended. The trace manager uses negative keys * for emulation scratch space and will activate them indirectly as needed. @@ -425,7 +414,6 @@ public interface FlatDebuggerAPI { /** * Get the current trace program view and address - * *

* This constitutes a portion of the debugger coordinates plus the current dynamic address. The * program given by {@link ProgramLocation#getProgram()} can be safely cast to @@ -449,7 +437,6 @@ public interface FlatDebuggerAPI { /** * Go to the given dynamic location in the dynamic listing - * *

* To "go to" a point in time, use {@link #activateSnap(long)} or * {@link #emulate(Trace, TraceSchedule, TaskMonitor)}. @@ -494,7 +481,6 @@ public interface FlatDebuggerAPI { /** * Get the current program - * *

* This is implemented by virtue of extending {@link FlatProgramAPI}, which is inherited via * {@link GhidraScript}. @@ -521,7 +507,6 @@ public interface FlatDebuggerAPI { /** * Translate the given static location to the corresponding dynamic location - * *

* This uses the trace's static mappings (see {@link Trace#getStaticMappingManager()} and * {@link DebuggerStaticMappingService}) to translate a static location to the corresponding @@ -542,7 +527,6 @@ public interface FlatDebuggerAPI { /** * Translate the given static address to the corresponding dynamic address - * *

* This does the same as {@link #translateStaticToDynamic(ProgramLocation)}, but assumes the * address is for the current program. The returned address is for the current trace view. @@ -558,7 +542,6 @@ public interface FlatDebuggerAPI { /** * Translate the given dynamic location to the corresponding static location - * *

* This does the opposite of {@link #translateStaticToDynamic(ProgramLocation)}. The resulting * static location could be for any open program, not just the current one, since a target may @@ -574,7 +557,6 @@ public interface FlatDebuggerAPI { /** * Translate the given dynamic address to the corresponding static address - * *

* This does the same as {@link #translateDynamicToStatic(ProgramLocation)}, but assumes the * address is for the current trace view. The returned address is for the current program. If @@ -603,7 +585,6 @@ public interface FlatDebuggerAPI { /** * Load the given program into a trace suitable for emulation in the UI, starting at the given * address - * *

* Note that the program bytes are not actually loaded into the trace. Rather a static mapping * is generated, allowing the emulator to load bytes from the target program lazily. The trace @@ -716,7 +697,6 @@ public interface FlatDebuggerAPI { /** * Step the current trace count skipped instructions via emulation - * *

* Note there's no such thing as "skipping in reverse." If a negative count is given, this will * behave the same as {@link #stepEmuInstruction(long, TaskMonitor)}. @@ -739,7 +719,6 @@ public interface FlatDebuggerAPI { /** * Step the current trace count skipped p-code operations via emulation - * *

* Note there's no such thing as "skipping in reverse." If a negative count is given, this will * behave the same as {@link #stepEmuPcodeOp(int, TaskMonitor)}. @@ -779,7 +758,6 @@ public interface FlatDebuggerAPI { /** * Create an address range, avoiding address overflow by truncating - * *

* If the length would cause address overflow, it is adjusted such that the range's maximum * address is the space's maximum address. @@ -823,7 +801,8 @@ public interface FlatDebuggerAPI { default void refreshMemoryIfLive(Trace trace, long snap, Address start, int length, TaskMonitor monitor) throws CancelledException { Target target = getTargetService().getTarget(trace); - if (target == null || target.getSnap() != snap) { + + if (!isLive(target, snap)) { return; } target.readMemory(new AddressSet(safeRange(start, length)), monitor); @@ -900,7 +879,6 @@ public interface FlatDebuggerAPI { /** * Search trace memory for a given masked byte sequence - * *

* NOTE: This searches the trace only. It will not interrogate the live target. There are * two mechanisms for searching a live target's full memory: 1) Capture the full memory (or the @@ -908,7 +886,6 @@ public interface FlatDebuggerAPI { * {@link #refreshMemoryIfLive(Trace, long, Address, int, TaskMonitor)} -- then search the * trace. 2) If possible, invoke the target debugger's search functions -- using, e.g., * {@link #executeCapture(String)}. - * *

* This delegates to * {@link TraceMemoryOperations#findBytes(long, AddressRange, ByteBuffer, ByteBuffer, boolean, TaskMonitor)}. @@ -918,7 +895,6 @@ public interface FlatDebuggerAPI { * {@code 00} is matched as usual, as is any stale byte. Only those ranges which have * never been recorded are culled. While not required, memory is conventionally read * and recorded in pages, so culling tends to occur at page boundaries. - * *

* Be wary of leading or trailing wildcards, i.e., masked-out bytes. The full data array must * fit within the given range after culling. For example, suppose the byte {@code 12} is @@ -965,6 +941,35 @@ public interface FlatDebuggerAPI { mask == null ? null : ByteBuffer.wrap(mask), forward, monitor); } + /** + * Check if the given snap could incorporate any "live" data of the target + * + * @param target the target + * @param snap the snapshot key + * @return true if live data retrieval is appropriate from the given snapshot's view + */ + default boolean isLive(Target target, long snap) { + if (target == null || !target.isValid()) { + return false; + } + + Trace trace = target.getTrace(); + TraceSnapshot snapshot = trace.getTimeManager().getSnapshot(snap, false); + if (Objects.equals(target.getTime(), snapshot.getSchedule())) { + return true; + } + + // LATER: This may be expensive.... + TraceTimeViewport viewport = trace.createTimeViewport(); + viewport.setSnap(snap); + for (long s : viewport.getReversedSnaps()) { + if (target.getSnap() == s) { + return true; + } + } + return false; + } + /** * Copy registers from target to trace, if applicable and not already cached * @@ -976,10 +981,9 @@ public interface FlatDebuggerAPI { */ default void refreshRegistersIfLive(TracePlatform platform, TraceThread thread, int frame, long snap, Collection registers) { - Trace trace = thread.getTrace(); + Target target = getTargetService().getTarget(thread.getTrace()); - Target target = getTargetService().getTarget(trace); - if (target == null || target.getSnap() != snap) { + if (!isLive(target, snap)) { return; } Set asSet = registers instanceof Set s ? s : Set.copyOf(registers); @@ -1004,7 +1008,9 @@ public interface FlatDebuggerAPI { if (regs == null) { return registers.stream().map(RegisterValue::new).collect(Collectors.toList()); } - return registers.stream().map(r -> regs.getValue(snap, r)).collect(Collectors.toList()); + return registers.stream() + .map(r -> regs.getViewValue(platform, snap, r)) + .collect(Collectors.toList()); } /** @@ -1034,7 +1040,7 @@ public interface FlatDebuggerAPI { default List readRegisters(Collection registers) { DebuggerCoordinates current = getCurrentDebuggerCoordinates(); return readRegisters(requireCurrentPlatform(), requireThread(current.getThread()), - current.getFrame(), current.getSnap(), registers); + current.getFrame(), current.getViewSnap(), registers); } /** @@ -1109,7 +1115,7 @@ public interface FlatDebuggerAPI { "Register " + register + " is not in language " + language); } return readRegister(platform, requireThread(current.getThread()), current.getFrame(), - current.getSnap(), register); + current.getViewSnap(), register); } /** @@ -1168,7 +1174,7 @@ public interface FlatDebuggerAPI { TracePlatform platform = requirePlatform(coordinates.getPlatform()); Language language = platform.getLanguage(); RegisterValue value = readRegister(platform, requireThread(coordinates.getThread()), - coordinates.getFrame(), coordinates.getSnap(), language.getProgramCounter()); + coordinates.getFrame(), coordinates.getViewSnap(), language.getProgramCounter()); if (value == null || !value.hasValue()) { return null; } @@ -1194,7 +1200,7 @@ public interface FlatDebuggerAPI { TracePlatform platform = requirePlatform(coordinates.getPlatform()); CompilerSpec cSpec = platform.getCompilerSpec(); RegisterValue value = readRegister(platform, requireThread(coordinates.getThread()), - coordinates.getFrame(), coordinates.getSnap(), cSpec.getStackPointer()); + coordinates.getFrame(), coordinates.getViewSnap(), cSpec.getStackPointer()); if (!value.hasValue()) { return null; } @@ -1287,7 +1293,6 @@ public interface FlatDebuggerAPI { /** * Patch memory using the given editor - * *

* The success or failure of this method depends on a few factors. First is the user-selected * control mode for the trace. See {@link #setControlMode(ControlMode)}. In read-only mode, this @@ -1319,7 +1324,6 @@ public interface FlatDebuggerAPI { /** * Patch memory of the given target, according to its current control mode - * *

* If you intend to apply several patches, consider using {@link #createStateEditor(Trace,long)} * and {@link #writeMemory(StateEditor, Address, byte[])} @@ -1336,7 +1340,6 @@ public interface FlatDebuggerAPI { /** * Patch memory of the current target, according to the current control mode - * *

* If you intend to apply several patches, consider using {@link #createStateEditor()} and * {@link #writeMemory(StateEditor, Address, byte[])} @@ -1351,7 +1354,6 @@ public interface FlatDebuggerAPI { /** * Patch a register using the given editor - * *

* The success or failure of this methods depends on a few factors. First is the user-selected * control mode for the trace. See {@link #setControlMode(ControlMode)}. In read-only mode, this @@ -1382,7 +1384,6 @@ public interface FlatDebuggerAPI { /** * Patch a register of the given context, according to its current control mode - * *

* If you intend to apply several patches, consider using * {@link #createStateEditor(TraceThread,int,long)} and @@ -1418,7 +1419,6 @@ public interface FlatDebuggerAPI { /** * Patch a register of the current thread, according to the current control mode - * *

* If you intend to apply several patches, consider using {@link #createStateEditor()} and * {@link #writeRegister(StateEditor, RegisterValue)}. @@ -1571,7 +1571,6 @@ public interface FlatDebuggerAPI { /** * Resume execution of the live target for the given trace thread - * *

* This is commonly called "continue" or "go," as well. * @@ -1584,7 +1583,6 @@ public interface FlatDebuggerAPI { /** * Resume execution of the live target for the given trace - * *

* This is commonly called "continue" or "go," as well. * @@ -1609,7 +1607,6 @@ public interface FlatDebuggerAPI { /** * Interrupt execution of the live target for the given trace thread - * *

* This is commonly called "pause" or "break," as well, but not "stop." * @@ -1622,7 +1619,6 @@ public interface FlatDebuggerAPI { /** * Interrupt execution of the live target for the given trace - * *

* This is commonly called "pause" or "break," as well, but not "stop." * @@ -1647,7 +1643,6 @@ public interface FlatDebuggerAPI { /** * Terminate execution of the live target for the given trace thread - * *

* This is commonly called "stop" as well. * @@ -1660,7 +1655,6 @@ public interface FlatDebuggerAPI { /** * Terminate execution of the live target for the given trace - * *

* This is commonly called "stop" as well. * @@ -1685,7 +1679,6 @@ public interface FlatDebuggerAPI { /** * Get the current state of the given trace - * *

* If the trace does not have a live target, it is considered * {@link TraceExecutionState#TERMINATED} (even if the trace never technically had a @@ -1711,7 +1704,6 @@ public interface FlatDebuggerAPI { /** * Get the current state of the given thread - * *

* If the thread does not have a corresponding live target thread, it is considered * {@link TraceExecutionState#TERMINATED} (even if the thread never technically had a @@ -1744,7 +1736,6 @@ public interface FlatDebuggerAPI { /** * Check if the current target is alive - * *

* NOTE: To be "current," the target must be recorded, and its trace must be the current * trace. @@ -1767,7 +1758,6 @@ public interface FlatDebuggerAPI { /** * Check if the current target thread is alive - * *

* NOTE: To be the "current" target thread, the target must be recorded, and its trace * thread must be the current thread. @@ -1780,7 +1770,6 @@ public interface FlatDebuggerAPI { /** * Wait for the trace's target to break - * *

* If the trace has no target, this method returns immediately, i.e., it assumes the target has * terminated. @@ -2028,7 +2017,6 @@ public interface FlatDebuggerAPI { /** * Get all the breakpoints - * *

* This returns all logical breakpoints among all open programs and traces (targets) * @@ -2104,7 +2092,6 @@ public interface FlatDebuggerAPI { /** * Perform some operations expected to cause changes, and then wait for those changes to settle - * *

* Use this via a try-with-resources block containing the operations causing changes. * @@ -2123,7 +2110,7 @@ public interface FlatDebuggerAPI { */ default Set breakpointsToggle(ProgramLocation location) { DebuggerLogicalBreakpointService service = getBreakpointService(); - try (ExpectingBreakpointChanges exp = expectBreakpointChanges()) { + try (ExpectingBreakpointChanges _ = expectBreakpointChanges()) { return waitOn(service.toggleBreakpointsAt(location, () -> CompletableFuture.completedFuture(Set.of()))); } @@ -2134,7 +2121,6 @@ public interface FlatDebuggerAPI { /** * Set a breakpoint at the given location - * *

* NOTE: Many asynchronous events take place when creating a breakpoint, esp., among * several live targets. Furthermore, some targets may adjust the breakpoint specification just @@ -2153,7 +2139,7 @@ public interface FlatDebuggerAPI { default Set breakpointSet(ProgramLocation location, long length, TraceBreakpointKindSet kinds, String name) { DebuggerLogicalBreakpointService service = getBreakpointService(); - try (ExpectingBreakpointChanges exp = expectBreakpointChanges()) { + try (ExpectingBreakpointChanges _ = expectBreakpointChanges()) { waitOn(service.placeBreakpointAt(location, length, kinds, name)); } catch (InterruptedException | ExecutionException | TimeoutException e) { @@ -2193,7 +2179,6 @@ public interface FlatDebuggerAPI { /** * Set a read breakpoint at the given location - * *

* This might also be called a "read watchpoint" or a "read access breakpoint." * @@ -2210,7 +2195,6 @@ public interface FlatDebuggerAPI { /** * Set a write breakpoint at the given location - * *

* This might also be called a "write watchpoint" or a "write access breakpoint." * @@ -2227,7 +2211,6 @@ public interface FlatDebuggerAPI { /** * Set an access breakpoint at the given location - * *

* This might also be called a "watchpoint." * @@ -2265,7 +2248,7 @@ public interface FlatDebuggerAPI { default Set breakpointsEnable(ProgramLocation location) { DebuggerLogicalBreakpointService service = getBreakpointService(); Set col = service.getBreakpointsAt(location); - try (ExpectingBreakpointChanges exp = expectBreakpointChanges()) { + try (ExpectingBreakpointChanges _ = expectBreakpointChanges()) { waitOn(service.enableAll(col, getTrace(location))); } catch (InterruptedException | ExecutionException | TimeoutException e) { @@ -2283,7 +2266,7 @@ public interface FlatDebuggerAPI { default Set breakpointsDisable(ProgramLocation location) { DebuggerLogicalBreakpointService service = getBreakpointService(); Set col = service.getBreakpointsAt(location); - try (ExpectingBreakpointChanges exp = expectBreakpointChanges()) { + try (ExpectingBreakpointChanges _ = expectBreakpointChanges()) { waitOn(service.disableAll(col, getTrace(location))); } catch (InterruptedException | ExecutionException | TimeoutException e) { @@ -2301,7 +2284,7 @@ public interface FlatDebuggerAPI { default boolean breakpointsClear(ProgramLocation location) { DebuggerLogicalBreakpointService service = getBreakpointService(); Set col = service.getBreakpointsAt(location); - try (ExpectingBreakpointChanges exp = expectBreakpointChanges()) { + try (ExpectingBreakpointChanges _ = expectBreakpointChanges()) { waitOn(service.deleteAll(col, getTrace(location))); } catch (InterruptedException | ExecutionException | TimeoutException e) { @@ -2312,7 +2295,6 @@ public interface FlatDebuggerAPI { /** * Flush each stage of the asynchronous processing pipelines from end to end - * *

* This method includes as many components as its author knows to flush. It flushes the trace's * event queue. Then, it waits for various services' changes to settle, in dependency order. @@ -2320,7 +2302,6 @@ public interface FlatDebuggerAPI { * Note that some stages use timeouts. It's also possible the target had not generated all the * expected events by the time this method began flushing its queue. Thus, callers should still * check that some expected condition is met and possibly repeat the flush before proceeding. - * *

* There are additional dependents in the GUI; however, scripts should not depend on them, so we * do not wait on them. diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java index ee97b43919..4456c23c01 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/AbstractFlatDebuggerAPITest.java @@ -95,7 +95,7 @@ public abstract class AbstractFlatDebuggerAPITest createTrace(); } TraceThread thread; - try (Transaction tx = tb.startTransaction()) { + try (Transaction _ = tb.startTransaction()) { tb.createRootObject(buildContext(), "Target"); thread = tb.getOrAddThread("Threads[0]", 0); tb.createObjectsFramesAndRegs(thread, Lifespan.nowOn(0), tb.host, 3); @@ -107,7 +107,7 @@ public abstract class AbstractFlatDebuggerAPITest protected void createTraceWithBinText() throws Throwable { createAndOpenTrace(); - try (Transaction tx = tb.startTransaction()) { + try (Transaction _ = tb.startTransaction()) { tb.createRootObject(buildContext(), "Target"); DBTraceMemoryManager mm = tb.trace.getMemoryManager(); mm.createRegion("Memory[bin.text]", 0, tb.range(0x00400000, 0x0040ffff), @@ -129,14 +129,14 @@ public abstract class AbstractFlatDebuggerAPITest programManager.openProgram(program); traceManager.activateTrace(tb.trace); - try (Transaction tx = program.openTransaction("add block")) { + try (Transaction _ = program.openTransaction("add block")) { program.getMemory() .createInitializedBlock(".text", addr(program, 0x00400000), 4096, (byte) 0, monitor, false); } CompletableFuture changesSettled; - try (Transaction tx = tb.startTransaction()) { + try (Transaction _ = tb.startTransaction()) { tb.createRootObject(buildContext(), "Target"); tb.trace.getMemoryManager() .createRegion("Memory[bin.text]", 0, tb.range(0x00400000, 0x00400fff), @@ -153,7 +153,7 @@ public abstract class AbstractFlatDebuggerAPITest programManager.openProgram(program); Address entry = addr(program, 0x00400000); - try (Transaction start = program.openTransaction("init")) { + try (Transaction _ = program.openTransaction("init")) { program.getMemory() .createInitializedBlock(".text", entry, 4096, (byte) 0, monitor, false); @@ -284,7 +284,7 @@ public abstract class AbstractFlatDebuggerAPITest programManager.openProgram(program); waitForSwing(); - try (Transaction tx = program.openTransaction("Add block")) { + try (Transaction _ = program.openTransaction("Add block")) { program.getMemory() .createInitializedBlock( ".text", addr(program, 0x00400000), 1024, (byte) 0, monitor, false); diff --git a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java index e1d3541d07..b8615a2dc3 100644 --- a/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java +++ b/Ghidra/Test/DebuggerIntegrationTest/src/test/java/ghidra/debug/flatapi/DeadFlatDebuggerAPITest.java @@ -99,7 +99,7 @@ public class DeadFlatDebuggerAPITest extends AbstractFlatDebuggerAPITest { - try (Transaction tx = tb.startTransaction()) { + var args = rmiMethodReadMem.expect(_ -> { + try (Transaction _ = tb.startTransaction()) { tb.trace.getMemoryManager() .putBytes(target.getSnap(), tb.addr(0x00400000), tb.buf(1, 2, 3, 4, 5, 6, 7, 8)); @@ -111,8 +111,8 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest { - try (Transaction tx = tb.startTransaction()) { + var args = rmiMethodReadRegs.expect(_ -> { + try (Transaction _ = tb.startTransaction()) { DBTraceMemorySpace regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs.setValue(target.getSnap(), new RegisterValue(r0, new BigInteger("1234"))); @@ -133,8 +133,8 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest { - try (Transaction tx = tb.startTransaction()) { + var args = rmiMethodReadRegs.expect(_ -> { + try (Transaction _ = tb.startTransaction()) { DBTraceMemorySpace regs = tb.trace.getMemoryManager().getMemoryRegisterSpace(thread, true); regs.setValue(target.getSnap(), new RegisterValue(r0, new BigInteger("1234"))); @@ -204,7 +204,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest null); + var args = method.get().expect(_ -> null); assertTrue(step.test(thread)); assertEquals(Map.ofEntries( Map.entry("thread", thread.getObject())), @@ -218,17 +218,17 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest api.stepInto(), () -> rmiMethodStepInto); + runTestStep(_ -> api.stepInto(), () -> rmiMethodStepInto); } @Test public void testStepOver() throws Throwable { - runTestStep(t -> api.stepOver(), () -> rmiMethodStepOver); + runTestStep(_ -> api.stepOver(), () -> rmiMethodStepOver); } @Test public void testStepOut() throws Throwable { - runTestStep(t -> api.stepOut(), () -> rmiMethodStepOut); + runTestStep(_ -> api.stepOut(), () -> rmiMethodStepOut); } @Override @@ -237,7 +237,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest null); + var args = rmiMethodResume.expect(_ -> null); assertTrue(resume.getAsBoolean()); assertEquals(Map.ofEntries( Map.entry("process", tb.obj("Processes[1]"))), @@ -250,7 +250,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest null); + var args = rmiMethodInterrupt.expect(_ -> null); assertTrue(interrupt.getAsBoolean()); assertEquals(Map.ofEntries( Map.entry("process", tb.obj("Processes[1]"))), @@ -263,7 +263,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest null); + var args = rmiMethodKill.expect(_ -> null); assertTrue(kill.getAsBoolean()); assertEquals(Map.ofEntries( Map.entry("process", tb.obj("Processes[1]"))), @@ -276,7 +276,7 @@ public class FlatDebuggerRmiAPITest extends AbstractLiveFlatDebuggerAPITest "result"); + var args = rmiMethodExecute.expect(_ -> "result"); assertEquals("result", api.executeCapture("some command")); assertEquals(Map.ofEntries( Map.entry("cmd", "some command"),