mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-19 15:05:36 +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.internal.ui.viewers.model.provisional.IColumnPresentationFactory"/>
|
||||
</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 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.IDMContext;
|
||||
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.IThreadDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
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.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.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.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.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
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 IMIProcesses fProcService;
|
||||
|
||||
// Record list of execution contexts
|
||||
private IExecutionDMContext[] fOldExecutionCtxts;
|
||||
|
||||
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||
|
||||
|
||||
public GDBRunControl(DsfSession session) {
|
||||
super(session);
|
||||
|
@ -65,6 +99,7 @@ public class GDBRunControl extends MIRunControl {
|
|||
fProcService = getServicesTracker().getService(IMIProcesses.class);
|
||||
|
||||
register(new String[]{IRunControl.class.getName(),
|
||||
IMIRunControl.class.getName(),
|
||||
MIRunControl.class.getName(),
|
||||
GDBRunControl.class.getName()}, new Hashtable<String,String>());
|
||||
requestMonitor.done();
|
||||
|
@ -210,4 +245,108 @@ public class GDBRunControl extends MIRunControl {
|
|||
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.IDMContext;
|
||||
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.IThreadDMContext;
|
||||
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.mi.service.IMIExecutionDMContext;
|
||||
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.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.MIExecContinue;
|
||||
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.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.MIExecUncall;
|
||||
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.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
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 IMIProcesses fProcService;
|
||||
private boolean fReverseSupported = true;
|
||||
private boolean fReverseStepping = false;
|
||||
private boolean fReverseModeEnabled = false;
|
||||
|
||||
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||
|
||||
public GDBRunControl_7_0(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
@ -76,7 +109,9 @@ public class GDBRunControl_7_0 extends MIRunControl implements IReverseRunContro
|
|||
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()},
|
||||
new Hashtable<String,String>());
|
||||
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 */
|
||||
public void setReverseModeEnabled(boolean 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.debug.service.ICachingService;
|
||||
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.IThreadDMContext;
|
||||
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.mi.service.IMIExecutionDMContext;
|
||||
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.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.MIExecFinish;
|
||||
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.MIExecStep;
|
||||
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.MIBreakpointHitEvent;
|
||||
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.MIInferiorExitEvent;
|
||||
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.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.MIThreadExitEvent;
|
||||
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.service.AbstractDsfService;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
|
@ -75,7 +80,7 @@ import org.osgi.framework.BundleContext;
|
|||
* sync with the service state.
|
||||
* @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
|
||||
private static class ExecutionData implements IExecutionDMData {
|
||||
|
@ -192,6 +197,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
|||
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
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -203,6 +228,8 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
|||
// ThreadStates indexed by the execution context
|
||||
protected Map<IMIExecutionDMContext, MIThreadRunState> fThreadRunStates = new HashMap<IMIExecutionDMContext, MIThreadRunState>();
|
||||
|
||||
private RunToLineActiveOperation fRunToLineActiveOperation = null;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Initialization and shutdown
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -222,7 +249,7 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
|||
}
|
||||
|
||||
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);
|
||||
getSession().addServiceEventListener(this, null);
|
||||
rm.done();
|
||||
|
@ -539,13 +566,11 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
|||
// Run to line
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Later add support for Address and function.
|
||||
// skipBreakpoints is not used at the moment. Implement later
|
||||
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm) {
|
||||
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, final boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm) {
|
||||
|
||||
assert context != null;
|
||||
|
||||
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
|
||||
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 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;
|
||||
}
|
||||
|
||||
threadState.fResumePending = true;
|
||||
fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||
final String location = fileName + ":" + lineNo; //$NON-NLS-1$
|
||||
IBreakpointsTargetDMContext bpDmc = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class);
|
||||
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
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -761,6 +852,26 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont
|
|||
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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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.IDMEvent;
|
||||
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.command.CommandCache;
|
||||
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
|
||||
* 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
|
||||
{
|
||||
|
|
|
@ -242,87 +242,91 @@ public class MIRunControlEventProcessor_7_0
|
|||
}
|
||||
|
||||
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
|
||||
String threadId = null;
|
||||
String groupId = null;
|
||||
|
||||
MIResult[] results = exec.getMIResults();
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
String var = results[i].getVariable();
|
||||
MIValue val = results[i].getMIValue();
|
||||
|
||||
if (var.equals("thread-id")) { //$NON-NLS-1$
|
||||
if (val instanceof MIConst) {
|
||||
threadId = ((MIConst)val).getString();
|
||||
}
|
||||
} else if (var.equals("group-id")) { //$NON-NLS-1$
|
||||
if (val instanceof MIConst) {
|
||||
groupId = ((MIConst)val).getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
|
||||
if (procService == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IProcessDMContext procDmc = null;
|
||||
IContainerDMContext containerDmc = null;
|
||||
if (groupId == null) {
|
||||
// MI does not currently provide the group-id in these events
|
||||
if (threadId != null) {
|
||||
containerDmc = procService.createContainerContextFromThreadId(fControlDmc, threadId);
|
||||
procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
|
||||
}
|
||||
} else {
|
||||
// This code would only trigger if the groupId was provided by MI
|
||||
procDmc = procService.createProcessContext(fControlDmc, groupId);
|
||||
containerDmc = procService.createContainerContext(procDmc, groupId);
|
||||
}
|
||||
|
||||
IExecutionDMContext execDmc = containerDmc;
|
||||
if (threadId != null) {
|
||||
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
|
||||
execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId);
|
||||
}
|
||||
|
||||
if (execDmc == null) {
|
||||
// Badly formatted event
|
||||
return null;
|
||||
}
|
||||
|
||||
MIEvent<?> event = null;
|
||||
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if (
|
||||
"watchpoint-trigger".equals(reason) //$NON-NLS-1$
|
||||
|| "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$
|
||||
|| "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIWatchpointTriggerEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$
|
||||
event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("signal-received".equals(reason)) { //$NON-NLS-1$
|
||||
event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("location-reached".equals(reason)) { //$NON-NLS-1$
|
||||
event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("exited-normally".equals(reason) || "exited".equals(reason)) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
|
||||
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)) {
|
||||
event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if (RUNNING_REASON.equals(reason)) {
|
||||
// Retrieve the type of command from what we last stored
|
||||
int type = MIRunningEvent.CONTINUE;
|
||||
if (fLastRunningCmdType != null) {
|
||||
type = fLastRunningCmdType;
|
||||
fLastRunningCmdType = null;
|
||||
} else {
|
||||
|
||||
String threadId = null;
|
||||
String groupId = null;
|
||||
|
||||
MIResult[] results = exec.getMIResults();
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
String var = results[i].getVariable();
|
||||
MIValue val = results[i].getMIValue();
|
||||
|
||||
if (var.equals("thread-id")) { //$NON-NLS-1$
|
||||
if (val instanceof MIConst) {
|
||||
threadId = ((MIConst)val).getString();
|
||||
}
|
||||
} else if (var.equals("group-id")) { //$NON-NLS-1$
|
||||
if (val instanceof MIConst) {
|
||||
groupId = ((MIConst)val).getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
|
||||
if (procService == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IProcessDMContext procDmc = null;
|
||||
IContainerDMContext containerDmc = null;
|
||||
if (groupId == null) {
|
||||
// MI does not currently provide the group-id in these events
|
||||
if (threadId != null) {
|
||||
containerDmc = procService.createContainerContextFromThreadId(fControlDmc, threadId);
|
||||
procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
|
||||
}
|
||||
} else {
|
||||
// This code would only trigger if the groupId was provided by MI
|
||||
procDmc = procService.createProcessContext(fControlDmc, groupId);
|
||||
containerDmc = procService.createContainerContext(procDmc, groupId);
|
||||
}
|
||||
|
||||
IExecutionDMContext execDmc = containerDmc;
|
||||
if (threadId != null) {
|
||||
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
|
||||
execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId);
|
||||
}
|
||||
|
||||
if (execDmc == null) {
|
||||
// Badly formatted event
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if (
|
||||
"watchpoint-trigger".equals(reason) //$NON-NLS-1$
|
||||
|| "read-watchpoint-trigger".equals(reason) //$NON-NLS-1$
|
||||
|| "access-watchpoint-trigger".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIWatchpointTriggerEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("watchpoint-scope".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIWatchpointScopeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("end-stepping-range".equals(reason)) { //$NON-NLS-1$
|
||||
event = MISteppingRangeEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("signal-received".equals(reason)) { //$NON-NLS-1$
|
||||
event = MISignalEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("location-reached".equals(reason)) { //$NON-NLS-1$
|
||||
event = MILocationReachedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if ("function-finished".equals(reason)) { //$NON-NLS-1$
|
||||
event = MIFunctionFinishedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if (STOPPED_REASON.equals(reason)) {
|
||||
event = MIStoppedEvent.parse(execDmc, exec.getToken(), exec.getMIResults());
|
||||
} else if (RUNNING_REASON.equals(reason)) {
|
||||
// Retrieve the type of command from what we last stored
|
||||
int type = MIRunningEvent.CONTINUE;
|
||||
if (fLastRunningCmdType != null) {
|
||||
type = fLastRunningCmdType;
|
||||
fLastRunningCmdType = null;
|
||||
}
|
||||
event = new MIRunningEvent(execDmc, exec.getToken(), type);
|
||||
}
|
||||
event = new MIRunningEvent(execDmc, exec.getToken(), type);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue