Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java')
-rw-r--r--plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java245
1 files changed, 174 insertions, 71 deletions
diff --git a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java
index e01a4d26a..45c9aaca6 100644
--- a/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java
+++ b/plugins/org.eclipse.tm.tcf.debug.ui/src/org/eclipse/tm/internal/tcf/debug/ui/commands/StepReturnCommand.java
@@ -10,97 +10,200 @@
*******************************************************************************/
package org.eclipse.tm.internal.tcf.debug.ui.commands;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
-import org.eclipse.debug.core.commands.IEnabledStateRequest;
import org.eclipse.debug.core.commands.IStepReturnHandler;
import org.eclipse.tm.internal.tcf.debug.ui.Activator;
import org.eclipse.tm.internal.tcf.debug.ui.model.TCFModel;
-import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode;
-import org.eclipse.tm.internal.tcf.debug.ui.model.TCFRunnable;
+import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext;
+import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame;
import org.eclipse.tm.tcf.protocol.IToken;
+import org.eclipse.tm.tcf.services.IBreakpoints;
import org.eclipse.tm.tcf.services.IRunControl;
+import org.eclipse.tm.tcf.services.IRunControl.RunControlContext;
-public class StepReturnCommand implements IStepReturnHandler {
+public class StepReturnCommand extends StepCommand implements IStepReturnHandler {
- private final TCFModel model;
-
- public StepReturnCommand(TCFModel model) {
- this.model = model;
- }
-
- public void canExecute(final IEnabledStateRequest monitor) {
- new TCFRunnable(model.getDisplay(), monitor) {
- public void run() {
- Object[] elements = monitor.getElements();
- boolean res = false;
- for (int i = 0; i < elements.length; i++) {
- TCFNode node = null;
- if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i];
- else node = model.getRootNode();
- while (node != null && !node.isDisposed()) {
- if (!node.validateNode(this)) return;
- IRunControl.RunControlContext ctx = node.getRunContext();
- if (ctx == null || !ctx.canResume(IRunControl.RM_STEP_OUT)) {
- node = node.getParent();
- }
- else {
- if (node.isSuspended()) res = true;
- node = null;
+ private static final long TIMEOUT = 10000;
+
+ private static class StepStateMachine extends TCFModel.ContextAction implements IRunControl.RunControlListener {
+
+ private final IDebugCommandRequest monitor;
+ private final Runnable done;
+ private final IRunControl rc = model.getLaunch().getService(IRunControl.class);
+ private final IBreakpoints bps = model.getLaunch().getService(IBreakpoints.class);
+
+ private IRunControl.RunControlContext ctx;
+ private TCFNodeExecContext node;
+ private TCFNodeStackFrame frame;
+ private int step_cnt;
+ private Map<String,Object> bp;
+ private boolean started;
+ private boolean exited;
+
+ StepStateMachine(TCFModel model, IDebugCommandRequest monitor,
+ IRunControl.RunControlContext ctx, Runnable done) {
+ super(model, ctx.getID());
+ this.monitor = monitor;
+ this.ctx = ctx;
+ this.done = done;
+ }
+
+ public void run() {
+ assert !exited;
+ if (!started) {
+ started = true;
+ rc.addListener(this);
+ node = (TCFNodeExecContext)model.getNode(ctx.getID());
+ if (node == null) {
+ exit(new Exception("Invalid context ID"));
+ return;
+ }
+ if (!ctx.canResume(IRunControl.RM_STEP_OUT)) {
+ model.invokeLater(TIMEOUT, new Runnable() {
+ public void run() {
+ exit(new Exception("Time out"));
}
- }
+ });
}
- monitor.setEnabled(res);
- monitor.setStatus(Status.OK_STATUS);
- done();
}
- };
- }
-
- public boolean execute(final IDebugCommandRequest monitor) {
- new TCFRunnable(model.getDisplay(), monitor) {
- public void run() {
- Object[] elements = monitor.getElements();
- Set<IRunControl.RunControlContext> set = new HashSet<IRunControl.RunControlContext>();
- for (int i = 0; i < elements.length; i++) {
- TCFNode node = null;
- if (elements[i] instanceof TCFNode) node = (TCFNode)elements[i];
- else node = model.getRootNode();
- while (node != null && !node.isDisposed()) {
- if (!node.validateNode(this)) return;
- IRunControl.RunControlContext ctx = node.getRunContext();
- if (ctx == null || !ctx.canResume(IRunControl.RM_STEP_OUT)) {
- node = node.getParent();
- }
- else {
- set.add(ctx);
- node = null;
- }
+ if (!node.validateNode(this)) return;
+ if (!node.isSuspended()) {
+ exit(new Exception("Context is not suspended"));
+ return;
+ }
+ if (ctx.canResume(IRunControl.RM_STEP_OUT)) {
+ if (step_cnt > 0) return;
+ ctx.resume(IRunControl.RM_STEP_OUT, 1, new IRunControl.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ exit(error);
}
+ });
+ step_cnt++;
+ return;
+ }
+ if (frame == null) {
+ frame = node.getTopFrame();
+ if (frame == null) {
+ exit(new Exception("Cannot get top stack frame"));
+ return;
}
- final Set<IToken> cmds = new HashSet<IToken>();
- for (Iterator<IRunControl.RunControlContext> i = set.iterator(); i.hasNext();) {
- IRunControl.RunControlContext ctx = i.next();
- cmds.add(ctx.resume(IRunControl.RM_STEP_OUT, 1, new IRunControl.DoneCommand() {
+ }
+ if (!frame.validateNode(this)) return;
+ if (frame.getFrameNo() < 0) {
+ // Stepped out of selected function
+ exit(null);
+ }
+ else if (bps != null && ctx.canResume(IRunControl.RM_RESUME)) {
+ if (bp == null) {
+ BigInteger addr = frame.getReturnAddress();
+ if (addr == null) {
+ exit(new Exception("Unknown stack frame return address"));
+ return;
+ }
+ bp = new HashMap<String,Object>();
+ bp.put(IBreakpoints.PROP_ID, "Step" + System.currentTimeMillis());
+ bp.put(IBreakpoints.PROP_LOCATION, addr.toString());
+ bp.put(IBreakpoints.PROP_CONDITION, "$thread==\"" + ctx.getID() + "\"");
+ bp.put(IBreakpoints.PROP_ENABLED, Boolean.TRUE);
+ bps.add(bp, new IBreakpoints.DoneCommand() {
public void doneCommand(IToken token, Exception error) {
- assert cmds.contains(token);
- cmds.remove(token);
- if (error != null) {
- monitor.setStatus(new Status(IStatus.ERROR,
- Activator.PLUGIN_ID, IStatus.OK, "Cannot step into", error));
- }
- if (cmds.isEmpty()) done();
+ if (error != null) exit(error);
}
- }));
+ });
}
+ ctx.resume(IRunControl.RM_RESUME, 1, new IRunControl.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ if (error != null) exit(error);
+ }
+ });
+ }
+ else {
+ exit(new Exception("Step out is not supported"));
+ }
+ }
+
+ private void exit(Throwable error) {
+ assert started;
+ if (exited) return;
+ if (bp != null) {
+ bps.remove(new String[]{ (String)bp.get(IBreakpoints.PROP_ID) }, new IBreakpoints.DoneCommand() {
+ public void doneCommand(IToken token, Exception error) {
+ }
+ });
}
- };
- return true;
+ rc.removeListener(this);
+ exited = true;
+ if (error != null) {
+ monitor.setStatus(new Status(IStatus.ERROR,
+ Activator.PLUGIN_ID, IStatus.OK, "Cannot step", error));
+ }
+ done.run();
+ done();
+ }
+
+ public void containerResumed(String[] context_ids) {
+ }
+
+ public void containerSuspended(String context, String pc,
+ String reason, Map<String, Object> params,
+ String[] suspended_ids) {
+ for (String id : suspended_ids) {
+ if (!id.equals(context)) contextSuspended(id, null, null, null);
+ }
+ contextSuspended(context, pc, reason, params);
+ }
+
+ public void contextAdded(RunControlContext[] contexts) {
+ }
+
+ public void contextChanged(RunControlContext[] contexts) {
+ for (RunControlContext c : contexts) {
+ if (c.getID().equals(ctx.getID())) ctx = c;
+ }
+ }
+
+ public void contextException(String context, String msg) {
+ if (context.equals(ctx.getID())) exit(new Exception(msg));
+ }
+
+ public void contextRemoved(String[] context_ids) {
+ for (String context : context_ids) {
+ if (context.equals(ctx.getID())) exit(null);
+ }
+ }
+
+ public void contextResumed(String context) {
+ }
+
+ public void contextSuspended(String context, String pc, String reason,
+ Map<String, Object> params) {
+ if (!context.equals(ctx.getID())) return;
+ exit(null);
+ }
+ }
+
+ public StepReturnCommand(TCFModel model) {
+ super(model);
+ }
+
+ @Override
+ protected boolean canExecute(IRunControl.RunControlContext ctx) {
+ if (ctx == null) return false;
+ if (ctx.canResume(IRunControl.RM_STEP_OUT)) return true;
+ if (ctx.canResume(IRunControl.RM_RESUME) && model.getLaunch().getService(IBreakpoints.class) != null) return true;
+ return false;
+ }
+
+ @Override
+ protected void execute(final IDebugCommandRequest monitor, final IRunControl.RunControlContext ctx,
+ boolean src_step, final Runnable done) {
+ new StepStateMachine(model, monitor, ctx, done);
}
}

Back to the top