mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-21 16:05:25 +02:00
[233230] Support for RunToLine
This commit is contained in:
parent
2a321cdc23
commit
3f6473cfed
9 changed files with 724 additions and 89 deletions
|
@ -162,6 +162,11 @@
|
||||||
<adapter type="org.eclipse.debug.ui.contexts.ISuspendTrigger"/>
|
<adapter type="org.eclipse.debug.ui.contexts.ISuspendTrigger"/>
|
||||||
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory"/>
|
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory"/>
|
||||||
</factory>
|
</factory>
|
||||||
|
<factory
|
||||||
|
class="org.eclipse.cdt.dsf.gdb.internal.ui.GdbRunToLineAdapterFactory"
|
||||||
|
adaptableType="org.eclipse.cdt.dsf.ui.viewmodel.IVMContext">
|
||||||
|
<adapter type="org.eclipse.debug.core.model.ISuspendResume"/>
|
||||||
|
</factory>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
<extension point="org.eclipse.debug.ui.memoryRenderings">
|
<extension point="org.eclipse.debug.ui.memoryRenderings">
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRunToLine;
|
||||||
|
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||||
|
import org.eclipse.core.runtime.IAdaptable;
|
||||||
|
import org.eclipse.core.runtime.IAdapterFactory;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.core.model.ISuspendResume;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public class GdbRunToLineAdapterFactory implements IAdapterFactory {
|
||||||
|
|
||||||
|
static class GdbSuspendResume implements ISuspendResume, IAdaptable {
|
||||||
|
|
||||||
|
private final GdbRunToLine fRunToLine;
|
||||||
|
|
||||||
|
GdbSuspendResume(IExecutionDMContext execCtx) {
|
||||||
|
fRunToLine = new GdbRunToLine(execCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getAdapter(Class adapter) {
|
||||||
|
if (adapter.isInstance(fRunToLine)) {
|
||||||
|
return fRunToLine;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canResume() { return false; }
|
||||||
|
public boolean canSuspend() { return false; }
|
||||||
|
public boolean isSuspended() { return false; }
|
||||||
|
public void resume() throws DebugException {}
|
||||||
|
public void suspend() throws DebugException {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getAdapter(Object adaptableObject, Class adapterType) {
|
||||||
|
if (ISuspendResume.class.equals(adapterType)) {
|
||||||
|
if (adaptableObject instanceof IDMVMContext) {
|
||||||
|
IExecutionDMContext execDmc = DMContexts.getAncestorOfType(
|
||||||
|
((IDMVMContext)adaptableObject).getDMContext(),
|
||||||
|
IExecutionDMContext.class);
|
||||||
|
// It only makes sense to RunToLine if we are dealing with a thread, not a container
|
||||||
|
if (execDmc != null && !(execDmc instanceof IContainerDMContext)) {
|
||||||
|
return new GdbSuspendResume(execDmc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getAdapterList() {
|
||||||
|
return new Class[] { ISuspendResume.class };
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Wind River Systems and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Wind River Systems - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.model.IRunToLine;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.DebugException;
|
||||||
|
import org.eclipse.debug.ui.actions.IRunToLineTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the CDT's run to line interface. This interface is called by CDT's
|
||||||
|
* {@link IRunToLineTarget} implementation.
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public class GdbRunToLine implements IRunToLine {
|
||||||
|
|
||||||
|
private final IExecutionDMContext fContext;
|
||||||
|
|
||||||
|
public GdbRunToLine(IExecutionDMContext context) {
|
||||||
|
fContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canRunToLine(IFile file, int lineNumber) {
|
||||||
|
return canRunToLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canRunToLine(String fileName, int lineNumber) {
|
||||||
|
return canRunToLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canRunToLine() {
|
||||||
|
DsfSession session = DsfSession.getSession(fContext.getSessionId());
|
||||||
|
if (session != null && session.isActive()) {
|
||||||
|
try {
|
||||||
|
Query<Boolean> query = new Query<Boolean>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(DataRequestMonitor<Boolean> rm) {
|
||||||
|
DsfServicesTracker tracker =
|
||||||
|
new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId());
|
||||||
|
|
||||||
|
IRunControl runControl = tracker.getService(IRunControl.class);
|
||||||
|
if (runControl != null) {
|
||||||
|
runControl.canResume(fContext, rm);
|
||||||
|
} else {
|
||||||
|
rm.setData(false);
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
tracker.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session.getExecutor().execute(query);
|
||||||
|
return query.get();
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runToLine(IFile file, int lineNumber, boolean skipBreakpoints) throws DebugException {
|
||||||
|
runToLine(file.getLocation().makeAbsolute().toOSString(), lineNumber, skipBreakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runToLine(final String fileName, final int lineNumber, final boolean skipBreakpoints) throws DebugException {
|
||||||
|
DsfSession session = DsfSession.getSession(fContext.getSessionId());
|
||||||
|
if (session != null && session.isActive()) {
|
||||||
|
Throwable exception = null;
|
||||||
|
try {
|
||||||
|
Query<Object> query = new Query<Object>() {
|
||||||
|
@Override
|
||||||
|
protected void execute(final DataRequestMonitor<Object> rm) {
|
||||||
|
DsfServicesTracker tracker =
|
||||||
|
new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fContext.getSessionId());
|
||||||
|
|
||||||
|
IMIRunControl miRunControl = tracker.getService(IMIRunControl.class);
|
||||||
|
if (miRunControl != null) {
|
||||||
|
miRunControl.runToLine(
|
||||||
|
fContext, fileName, Integer.toString(lineNumber), skipBreakpoints,
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
rm.setData(new Object());
|
||||||
|
rm.done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "MIRunControl service not available", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
tracker.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
session.getExecutor().execute(query);
|
||||||
|
query.get();
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
exception = e;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
exception = e;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
exception = e;
|
||||||
|
}
|
||||||
|
if (exception != null) {
|
||||||
|
new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Faild executing run to line", exception)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new DebugException(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Debug session is not active", null)); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,26 +24,60 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
public class GDBRunControl extends MIRunControl {
|
public class GDBRunControl extends MIRunControl {
|
||||||
|
|
||||||
|
private static class RunToLineActiveOperation {
|
||||||
|
private IMIExecutionDMContext fThreadContext;
|
||||||
|
private int fBpId;
|
||||||
|
private String fLocation;
|
||||||
|
private boolean fSkipBreakpoints;
|
||||||
|
|
||||||
|
public RunToLineActiveOperation(IMIExecutionDMContext threadContext,
|
||||||
|
int bpId, String location, boolean skipBreakpoints) {
|
||||||
|
fThreadContext = threadContext;
|
||||||
|
fBpId = bpId;
|
||||||
|
fLocation = location;
|
||||||
|
fSkipBreakpoints = skipBreakpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMIExecutionDMContext getThreadContext() { return fThreadContext; }
|
||||||
|
public int getBreakointId() { return fBpId; }
|
||||||
|
public String getLocation() { return fLocation; }
|
||||||
|
public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; }
|
||||||
|
}
|
||||||
|
|
||||||
private IGDBBackend fGdb;
|
private IGDBBackend fGdb;
|
||||||
private IMIProcesses fProcService;
|
private IMIProcesses fProcService;
|
||||||
|
|
||||||
// Record list of execution contexts
|
// Record list of execution contexts
|
||||||
private IExecutionDMContext[] fOldExecutionCtxts;
|
private IExecutionDMContext[] fOldExecutionCtxts;
|
||||||
|
|
||||||
|
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
|
|
||||||
public GDBRunControl(DsfSession session) {
|
public GDBRunControl(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
|
@ -65,6 +99,7 @@ public class GDBRunControl extends MIRunControl {
|
||||||
fProcService = getServicesTracker().getService(IMIProcesses.class);
|
fProcService = getServicesTracker().getService(IMIProcesses.class);
|
||||||
|
|
||||||
register(new String[]{IRunControl.class.getName(),
|
register(new String[]{IRunControl.class.getName(),
|
||||||
|
IMIRunControl.class.getName(),
|
||||||
MIRunControl.class.getName(),
|
MIRunControl.class.getName(),
|
||||||
GDBRunControl.class.getName()}, new Hashtable<String,String>());
|
GDBRunControl.class.getName()}, new Hashtable<String,String>());
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
|
@ -210,4 +245,108 @@ public class GDBRunControl extends MIRunControl {
|
||||||
canResume(context, rm);
|
canResume(context, rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.0 */
|
||||||
|
@Override
|
||||||
|
public void runToLine(final IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm){
|
||||||
|
// Later add support for Address and function.
|
||||||
|
|
||||||
|
assert context != null;
|
||||||
|
|
||||||
|
final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
|
if (dmc == null){
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCanResume(context)) {
|
||||||
|
final String location = fileName + ":" + lineNo; //$NON-NLS-1$
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class);
|
||||||
|
getConnection().queueCommand(
|
||||||
|
new MIBreakInsert(bpDmc, true, false, null, 0,
|
||||||
|
location, dmc.getThreadId()),
|
||||||
|
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess() {
|
||||||
|
// We must set are RunToLineActiveOperation *before* we do the resume
|
||||||
|
// or else we may get the stopped event, before we have set this variable.
|
||||||
|
int bpId = getData().getMIBreakpoints()[0].getNumber();
|
||||||
|
fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints);
|
||||||
|
|
||||||
|
resume(context, new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleFailure() {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
|
"Cannot resume given DMC.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||||
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(MIInferiorExitEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.0 */
|
||||||
|
@Override
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(final MIStoppedEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$
|
||||||
|
if (location.equals(fRunToLineActiveOperation.getLocation())) {
|
||||||
|
// We stopped on our temporary breakpoint. All is well.
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
} else {
|
||||||
|
// Didn't stop at the right line yet
|
||||||
|
if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) {
|
||||||
|
getConnection().queueCommand(
|
||||||
|
new MIExecContinue(fRunToLineActiveOperation.getThreadContext()),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
|
||||||
|
// Don't send the stop event since we are resuming again.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Stopped at another breakpoint or not a breakpoint at all. Just remove our temporary one
|
||||||
|
// since we don't want it to hit later
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.eventDispatched(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
|
@ -30,9 +31,13 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommand
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseContinue;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseContinue;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNext;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNextInstruction;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseNextInstruction;
|
||||||
|
@ -40,18 +45,46 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseStep;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseStepInstruction;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecReverseStepInstruction;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUncall;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUncall;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.RawCommand;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.RawCommand;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunControl {
|
public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunControl {
|
||||||
|
|
||||||
|
private static class RunToLineActiveOperation {
|
||||||
|
private IMIExecutionDMContext fThreadContext;
|
||||||
|
private int fBpId;
|
||||||
|
private String fLocation;
|
||||||
|
private boolean fSkipBreakpoints;
|
||||||
|
|
||||||
|
public RunToLineActiveOperation(IMIExecutionDMContext threadContext,
|
||||||
|
int bpId, String location, boolean skipBreakpoints) {
|
||||||
|
fThreadContext = threadContext;
|
||||||
|
fBpId = bpId;
|
||||||
|
fLocation = location;
|
||||||
|
fSkipBreakpoints = skipBreakpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMIExecutionDMContext getThreadContext() { return fThreadContext; }
|
||||||
|
public int getBreakointId() { return fBpId; }
|
||||||
|
public String getLocation() { return fLocation; }
|
||||||
|
public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; }
|
||||||
|
}
|
||||||
|
|
||||||
private IGDBBackend fGdb;
|
private IGDBBackend fGdb;
|
||||||
private IMIProcesses fProcService;
|
private IMIProcesses fProcService;
|
||||||
private boolean fReverseSupported = true;
|
private boolean fReverseSupported = true;
|
||||||
private boolean fReverseStepping = false;
|
private boolean fReverseStepping = false;
|
||||||
private boolean fReverseModeEnabled = false;
|
private boolean fReverseModeEnabled = false;
|
||||||
|
|
||||||
|
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
public GDBRunControl_7_0(DsfSession session) {
|
public GDBRunControl_7_0(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +109,9 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
fReverseSupported = false;
|
fReverseSupported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName(),
|
register(new String[]{IRunControl.class.getName(),
|
||||||
|
IMIRunControl.class.getName(),
|
||||||
|
MIRunControl.class.getName(),
|
||||||
IReverseRunControl.class.getName()},
|
IReverseRunControl.class.getName()},
|
||||||
new Hashtable<String,String>());
|
new Hashtable<String,String>());
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
|
@ -400,6 +435,111 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 2.0 */
|
||||||
|
@Override
|
||||||
|
public void runToLine(final IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm){
|
||||||
|
// Later add support for Address and function.
|
||||||
|
|
||||||
|
assert context != null;
|
||||||
|
|
||||||
|
final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
|
if (dmc == null){
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Given context: " + context + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCanResume(context)) {
|
||||||
|
final String location = fileName + ":" + lineNo; //$NON-NLS-1$
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class);
|
||||||
|
getConnection().queueCommand(
|
||||||
|
new MIBreakInsert(bpDmc, true, false, null, 0,
|
||||||
|
location, dmc.getThreadId()),
|
||||||
|
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess() {
|
||||||
|
// We must set are RunToLineActiveOperation *before* we do the resume
|
||||||
|
// or else we may get the stopped event, before we have set this variable.
|
||||||
|
int bpId = getData().getMIBreakpoints()[0].getNumber();
|
||||||
|
fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints);
|
||||||
|
|
||||||
|
resume(context, new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleFailure() {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
|
"Cannot resume given DMC.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||||
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(MIInferiorExitEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 2.0 */
|
||||||
|
@Override
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(final MIStoppedEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$
|
||||||
|
if (location.equals(fRunToLineActiveOperation.getLocation())) {
|
||||||
|
// We stopped on our temporary breakpoint. All is well.
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
} else {
|
||||||
|
// Didn't stop at the right line yet
|
||||||
|
if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) {
|
||||||
|
getConnection().queueCommand(
|
||||||
|
new MIExecContinue(fRunToLineActiveOperation.getThreadContext()),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
|
||||||
|
// Don't send the stop event since we are resuming again.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Stopped at another breakpoint. Just remove our temporary one
|
||||||
|
// since we don't want it to hit later
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
getConnection().queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.eventDispatched(e);
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 2.0 */
|
/** @since 2.0 */
|
||||||
public void setReverseModeEnabled(boolean enabled) {
|
public void setReverseModeEnabled(boolean enabled) {
|
||||||
fReverseModeEnabled = enabled;
|
fReverseModeEnabled = enabled;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
|
@ -33,8 +34,11 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommand
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
import org.eclipse.cdt.dsf.mi.service.MIRunControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
import org.eclipse.cdt.dsf.mi.service.MIStack;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecInterrupt;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecInterrupt;
|
||||||
|
@ -42,11 +46,11 @@ import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNextInstruction;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNextInstruction;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStep;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStep;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStepInstruction;
|
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStepInstruction;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUntil;
|
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIErrorEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIErrorEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIInferiorExitEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MISharedLibEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MISharedLibEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent;
|
||||||
|
@ -55,6 +59,7 @@ import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadCreatedEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadCreatedEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
|
@ -75,7 +80,7 @@ import org.osgi.framework.BundleContext;
|
||||||
* sync with the service state.
|
* sync with the service state.
|
||||||
* @since 1.1
|
* @since 1.1
|
||||||
*/
|
*/
|
||||||
public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunControl, ICachingService
|
public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunControl, ICachingService
|
||||||
{
|
{
|
||||||
@Immutable
|
@Immutable
|
||||||
private static class ExecutionData implements IExecutionDMData {
|
private static class ExecutionData implements IExecutionDMData {
|
||||||
|
@ -192,6 +197,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
StateChangeReason fStateChangeReason;
|
StateChangeReason fStateChangeReason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class RunToLineActiveOperation {
|
||||||
|
private IMIExecutionDMContext fThreadContext;
|
||||||
|
private int fBpId;
|
||||||
|
private String fLocation;
|
||||||
|
private boolean fSkipBreakpoints;
|
||||||
|
|
||||||
|
public RunToLineActiveOperation(IMIExecutionDMContext threadContext,
|
||||||
|
int bpId, String location, boolean skipBreakpoints) {
|
||||||
|
fThreadContext = threadContext;
|
||||||
|
fBpId = bpId;
|
||||||
|
fLocation = location;
|
||||||
|
fSkipBreakpoints = skipBreakpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMIExecutionDMContext getThreadContext() { return fThreadContext; }
|
||||||
|
public int getBreakointId() { return fBpId; }
|
||||||
|
public String getLocation() { return fLocation; }
|
||||||
|
public boolean shouldSkipBreakpoints() { return fSkipBreakpoints; }
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// MIRunControlNS
|
// MIRunControlNS
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -203,6 +228,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
// ThreadStates indexed by the execution context
|
// ThreadStates indexed by the execution context
|
||||||
protected Map<IMIExecutionDMContext, MIThreadRunState> fThreadRunStates = new HashMap<IMIExecutionDMContext, MIThreadRunState>();
|
protected Map<IMIExecutionDMContext, MIThreadRunState> fThreadRunStates = new HashMap<IMIExecutionDMContext, MIThreadRunState>();
|
||||||
|
|
||||||
|
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Initialization and shutdown
|
// Initialization and shutdown
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -222,7 +249,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doInitialize(final RequestMonitor rm) {
|
private void doInitialize(final RequestMonitor rm) {
|
||||||
register(new String[]{IRunControl.class.getName()}, new Hashtable<String,String>());
|
register(new String[]{IRunControl.class.getName(), IMIRunControl.class.getName()}, new Hashtable<String,String>());
|
||||||
fConnection = getServicesTracker().getService(ICommandControlService.class);
|
fConnection = getServicesTracker().getService(ICommandControlService.class);
|
||||||
getSession().addServiceEventListener(this, null);
|
getSession().addServiceEventListener(this, null);
|
||||||
rm.done();
|
rm.done();
|
||||||
|
@ -539,13 +566,11 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
// Run to line
|
// Run to line
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
// Later add support for Address and function.
|
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm) {
|
||||||
// skipBreakpoints is not used at the moment. Implement later
|
|
||||||
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm) {
|
|
||||||
|
|
||||||
assert context != null;
|
assert context != null;
|
||||||
|
|
||||||
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
final IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||||
if (dmc == null) {
|
if (dmc == null) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
|
||||||
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
@ -568,9 +593,44 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
threadState.fResumePending = true;
|
final String location = fileName + ":" + lineNo; //$NON-NLS-1$
|
||||||
fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class);
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
fConnection.queueCommand(
|
||||||
|
new MIBreakInsert(bpDmc, true, false, null, 0,
|
||||||
|
location, dmc.getThreadId()),
|
||||||
|
new DataRequestMonitor<MIBreakInsertInfo>(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleSuccess() {
|
||||||
|
// We must set are RunToLineActiveOperation *before* we do the resume
|
||||||
|
// or else we may get the stopped event, before we have set this variable.
|
||||||
|
int bpId = getData().getMIBreakpoints()[0].getNumber();
|
||||||
|
|
||||||
|
// It would have been nice to use the address returned by the break-insert as our location,
|
||||||
|
// but that does not always work because sometimes the address is <MULTIPLE>
|
||||||
|
//
|
||||||
|
// Also, we could have used the breakpoint id to know if we hit the proper breakpoint,
|
||||||
|
// but that also doesn't always work because if there are many bp at that location,
|
||||||
|
// GDB will report hitting one of them but not all of them (although GDB does consider
|
||||||
|
// that all those bps did hit.)
|
||||||
|
fRunToLineActiveOperation = new RunToLineActiveOperation(dmc, bpId, location, skipBreakpoints);
|
||||||
|
|
||||||
|
resume(dmc, new RequestMonitor(getExecutor(), rm) {
|
||||||
|
@Override
|
||||||
|
public void handleFailure() {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
|
||||||
|
super.handleFailure();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -673,6 +733,37 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
*/
|
*/
|
||||||
@DsfServiceEventHandler
|
@DsfServiceEventHandler
|
||||||
public void eventDispatched(final MIStoppedEvent e) {
|
public void eventDispatched(final MIStoppedEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
// First check if it is the right thread that stopped
|
||||||
|
IMIExecutionDMContext threadDmc = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
|
||||||
|
if (fRunToLineActiveOperation.getThreadContext().equals(threadDmc)) {
|
||||||
|
String location = e.getFrame().getFile() + ":" + e.getFrame().getLine(); //$NON-NLS-1$
|
||||||
|
if (location.equals(fRunToLineActiveOperation.getLocation())) {
|
||||||
|
// We stopped on our temporary breakpoint. All is well.
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
} else {
|
||||||
|
// The right thread stopped but not at the right place yet
|
||||||
|
if (fRunToLineActiveOperation.shouldSkipBreakpoints() && e instanceof MIBreakpointHitEvent) {
|
||||||
|
fConnection.queueCommand(
|
||||||
|
new MIExecContinue(fRunToLineActiveOperation.getThreadContext()),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
|
||||||
|
// Don't send the stop event since we are resuming again.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Stopped for any other reasons. Just remove our temporary one
|
||||||
|
// since we don't want it to hit later
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
getSession().dispatchEvent(new SuspendedEvent(e.getDMContext(), e), getProperties());
|
getSession().dispatchEvent(new SuspendedEvent(e.getDMContext(), e), getProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +852,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
||||||
fTerminated = true;
|
fTerminated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @nooverride This method is not intended to be re-implemented or extended by clients.
|
||||||
|
* @noreference This method is not intended to be referenced by clients.
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
@DsfServiceEventHandler
|
||||||
|
public void eventDispatched(MIInferiorExitEvent e) {
|
||||||
|
if (fRunToLineActiveOperation != null) {
|
||||||
|
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(fRunToLineActiveOperation.getThreadContext(),
|
||||||
|
IBreakpointsTargetDMContext.class);
|
||||||
|
int bpId = fRunToLineActiveOperation.getBreakointId();
|
||||||
|
|
||||||
|
fConnection.queueCommand(new MIBreakDelete(bpDmc, new int[] {bpId}),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), null));
|
||||||
|
fRunToLineActiveOperation = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void flushCache(IDMContext context) {
|
public void flushCache(IDMContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Ericsson and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ericsson - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.mi.service;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface provides methods for RunControl that are not
|
||||||
|
* part of the standard DSF IRunControl
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
public interface IMIRunControl extends IRunControl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Request to run the program up to the specified location.
|
||||||
|
* If skipBreakpoints is false, any other breakpoint will stop this
|
||||||
|
* command; while if skipBreakpoints is true, the operation will ignore
|
||||||
|
* other breakpoints and continue until the specified location.
|
||||||
|
*/
|
||||||
|
void runToLine(IExecutionDMContext context, String fileName, String lineNo,
|
||||||
|
boolean skipBreakpoints, DataRequestMonitor<MIInfo> rm);
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
import org.eclipse.cdt.dsf.datamodel.IDMEvent;
|
||||||
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
import org.eclipse.cdt.dsf.debug.service.ICachingService;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl;
|
|
||||||
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||||
|
@ -73,7 +72,7 @@ import org.osgi.framework.BundleContext;
|
||||||
* events and track service state, to be perfectly in sync with the service
|
* events and track service state, to be perfectly in sync with the service
|
||||||
* state.
|
* state.
|
||||||
*/
|
*/
|
||||||
public class MIRunControl extends AbstractDsfService implements IRunControl, ICachingService
|
public class MIRunControl extends AbstractDsfService implements IMIRunControl, ICachingService
|
||||||
{
|
{
|
||||||
private static class MIExecutionDMC extends AbstractDMContext implements IMIExecutionDMContext
|
private static class MIExecutionDMC extends AbstractDMContext implements IMIExecutionDMContext
|
||||||
{
|
{
|
||||||
|
|
|
@ -242,6 +242,14 @@ public class MIRunControlEventProcessor_7_0
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
|
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
|
||||||
|
MIEvent<?> event = null;
|
||||||
|
|
||||||
|
if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
event = MIInferiorExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
|
||||||
|
} else if ("exited-signalled".equals(reason)) { //$NON-NLS-1$
|
||||||
|
event = MIInferiorSignalExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
|
||||||
|
} else {
|
||||||
|
|
||||||
String threadId = null;
|
String threadId = null;
|
||||||
String groupId = null;
|
String groupId = null;
|
||||||
|
|
||||||
|
@ -291,7 +299,6 @@ public class MIRunControlEventProcessor_7_0
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIEvent<?> event = null;
|
|
||||||
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
|
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
|
||||||
event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -309,10 +316,6 @@ public class MIRunControlEventProcessor_7_0
|
||||||
event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||||
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
|
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
|
||||||
event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||||
} else if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$
|
|
||||||
event = MIInferiorExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
|
|
||||||
} else if ("exited-signalled".equals(reason)) { //$NON-NLS-1$
|
|
||||||
event = MIInferiorSignalExitEvent.parse(fCommandControl.getContext(), exec.getToken(), exec.getMIResults());
|
|
||||||
} else if (STOPPED_REASON.equals(reason)) {
|
} else if (STOPPED_REASON.equals(reason)) {
|
||||||
event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||||
} else if (RUNNING_REASON.equals(reason)) {
|
} else if (RUNNING_REASON.equals(reason)) {
|
||||||
|
@ -324,6 +327,7 @@ public class MIRunControlEventProcessor_7_0
|
||||||
}
|
}
|
||||||
event = new MIRunningEvent(execDmc, exec.getToken(), type);
|
event = new MIRunningEvent(execDmc, exec.getToken(), type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue