mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
GP-7191: Fix FlatDebuggerAPI register reads when used with emulation.
This commit is contained in:
@@ -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.
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* By default, this waits at most 1 minute.
|
||||
*
|
||||
@@ -91,7 +90,6 @@ public interface FlatDebuggerAPI {
|
||||
|
||||
/**
|
||||
* Get the script state
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> 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)}.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* <em>never</em> been recorded are culled. While not required, memory is conventionally read
|
||||
* and recorded in pages, so culling tends to occur at page boundaries.
|
||||
*
|
||||
* <p>
|
||||
* 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<Register> 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<Register> asSet = registers instanceof Set<Register> 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<RegisterValue> readRegisters(Collection<Register> 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* This is commonly called "stop" as well.
|
||||
*
|
||||
@@ -1660,7 +1655,6 @@ public interface FlatDebuggerAPI {
|
||||
|
||||
/**
|
||||
* Terminate execution of the live target for the given trace
|
||||
*
|
||||
* <p>
|
||||
* This is commonly called "stop" as well.
|
||||
*
|
||||
@@ -1685,7 +1679,6 @@ public interface FlatDebuggerAPI {
|
||||
|
||||
/**
|
||||
* Get the current state of the given trace
|
||||
*
|
||||
* <p>
|
||||
* If the trace does not have a live target, it is considered
|
||||
* {@link TraceExecutionState#TERMINATED} (even if the trace <em>never</em> technically had a
|
||||
@@ -1711,7 +1704,6 @@ public interface FlatDebuggerAPI {
|
||||
|
||||
/**
|
||||
* Get the current state of the given thread
|
||||
*
|
||||
* <p>
|
||||
* If the thread does not have a corresponding live target thread, it is considered
|
||||
* {@link TraceExecutionState#TERMINATED} (even if the thread <em>never</em> technically had a
|
||||
@@ -1744,7 +1736,6 @@ public interface FlatDebuggerAPI {
|
||||
|
||||
/**
|
||||
* Check if the current target is alive
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> 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
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* Use this via a try-with-resources block containing the operations causing changes.
|
||||
*
|
||||
@@ -2123,7 +2110,7 @@ public interface FlatDebuggerAPI {
|
||||
*/
|
||||
default Set<LogicalBreakpoint> 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
|
||||
*
|
||||
* <p>
|
||||
* <b>NOTE:</b> 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<LogicalBreakpoint> 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
*
|
||||
* <p>
|
||||
* This might also be called a "watchpoint."
|
||||
*
|
||||
@@ -2265,7 +2248,7 @@ public interface FlatDebuggerAPI {
|
||||
default Set<LogicalBreakpoint> breakpointsEnable(ProgramLocation location) {
|
||||
DebuggerLogicalBreakpointService service = getBreakpointService();
|
||||
Set<LogicalBreakpoint> 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<LogicalBreakpoint> breakpointsDisable(ProgramLocation location) {
|
||||
DebuggerLogicalBreakpointService service = getBreakpointService();
|
||||
Set<LogicalBreakpoint> 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<LogicalBreakpoint> 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
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <p>
|
||||
* There are additional dependents in the GUI; however, scripts should not depend on them, so we
|
||||
* do not wait on them.
|
||||
|
||||
Reference in New Issue
Block a user