diff --git a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java index 00d046d55a..1ee0071121 100644 --- a/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java +++ b/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/TraceRmiTarget.java @@ -334,13 +334,13 @@ public class TraceRmiTarget extends AbstractTarget { ActionName.STEP_OUT.equals(name) || ActionName.STEP_OVER.equals(name) || ActionName.STEP_SKIP.equals(name)) { - return () -> whenState(obj, state -> state != null && state.isStopped()); + return () -> whenState(obj, state -> state != null && (state.isStopped() || state.isUnknown())); } else if (ActionName.INTERRUPT.equals(name)) { - return () -> whenState(obj, state -> state == null || state.isRunning()); + return () -> whenState(obj, state -> state == null || state.isRunning() || state.isUnknown()); } else if (ActionName.KILL.equals(name)) { - return () -> whenState(obj, state -> state == null || state.isAlive()); + return () -> whenState(obj, state -> state == null || !state.isTerminated()); } return () -> true; } diff --git a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetExecutionStateful.java b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetExecutionStateful.java index 9b3c2ae669..79f54f754d 100644 --- a/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetExecutionStateful.java +++ b/Ghidra/Debug/Framework-Debugging/src/main/java/ghidra/dbg/target/TargetExecutionStateful.java @@ -5,7 +5,7 @@ * 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 + * 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, @@ -40,7 +40,7 @@ public interface TargetExecutionStateful extends TargetObject { * This may apply, e.g., to a GDB "Inferior," which has no yet been used to launch or attach * to a process. */ - INACTIVE(false, false, false), + INACTIVE(false, false, false, false), /** * The object is alive, but its execution state is unspecified @@ -52,12 +52,12 @@ public interface TargetExecutionStateful extends TargetObject { * when all of its threads are stopped. For the clients' sakes, all models should * implement these conventions internally. */ - ALIVE(true, false, false), + ALIVE(true, false, false, false), /** * The object is alive, but not executing */ - STOPPED(true, false, true), + STOPPED(true, false, true, false), /** * The object is alive and executing @@ -67,7 +67,7 @@ public interface TargetExecutionStateful extends TargetObject { * thread is currently executing, waiting on an event, or scheduled for execution. It does * not necessarily mean it is executing on a CPU at this exact moment. */ - RUNNING(true, true, false), + RUNNING(true, true, false, false), /** * The object is no longer alive @@ -77,16 +77,18 @@ public interface TargetExecutionStateful extends TargetObject { * stale handles to objects which may still be queried (e.g., for a process exit code), or * e.g., a GDB "Inferior," which could be re-used to launch or attach to another process. */ - TERMINATED(false, false, false); + TERMINATED(false, false, false, true); private final boolean alive; private final boolean running; private final boolean stopped; + private final boolean terminated; - private TargetExecutionState(boolean alive, boolean running, boolean stopped) { + private TargetExecutionState(boolean alive, boolean running, boolean stopped, boolean terminated) { this.alive = alive; this.running = running; this.stopped = stopped; + this.terminated = terminated; } /** @@ -115,6 +117,24 @@ public interface TargetExecutionStateful extends TargetObject { public boolean isStopped() { return stopped; } + + /** + * Check if this state implies the object was terminated + * + * @return true if terminated + */ + public boolean isTerminated() { + return terminated; + } + + /** + * Check if this state is ambiguous + * + * @return true if terminated + */ + public boolean isUnknown() { + return !stopped && !running && !terminated; + } } /**