mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
[236765] - [pda] Add multi-threading capability to PDA
This commit is contained in:
parent
e90dbc258a
commit
ee9c51a046
55 changed files with 2905 additions and 1475 deletions
|
@ -12,19 +12,21 @@ package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch;
|
|||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.StepQueueManager.ISteppingTimedOutEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
|
@ -40,14 +42,16 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
|||
public abstract class AbstractContainerVMNode extends AbstractDMVMNode implements IElementLabelProvider {
|
||||
|
||||
public AbstractContainerVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IRunControl.IExecutionDMContext.class);
|
||||
super(provider, session, IRunControl.IContainerDMContext.class);
|
||||
}
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateLabelInSessionThread(updates);
|
||||
for (final ILabelUpdate update : updates) {
|
||||
updateLabelInSessionThread(update);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
for (ILabelUpdate update : updates) {
|
||||
|
@ -62,26 +66,36 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement
|
|||
* @param updates the pending label updates
|
||||
* @see {@link #update(ILabelUpdate[])
|
||||
*/
|
||||
protected abstract void updateLabelInSessionThread(ILabelUpdate[] updates);
|
||||
protected abstract void updateLabelInSessionThread(ILabelUpdate update);
|
||||
|
||||
@Override
|
||||
public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
|
||||
super.getContextsForEvent(parentDelta, e, rm);
|
||||
}
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof IContainerResumedDMEvent &&
|
||||
((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
|
||||
|
||||
if (e instanceof IContainerResumedDMEvent) {
|
||||
if (((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
} else if (e instanceof IContainerSuspendedDMEvent) {
|
||||
// no change, update happens on FullStackRefreshEvent
|
||||
return IModelDelta.NO_CHANGE;
|
||||
} else if (e instanceof FullStackRefreshEvent) {
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
return IModelDelta.CONTENT;
|
||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
||||
}
|
||||
} else if (e instanceof ISteppingTimedOutEvent) {
|
||||
if (dmc instanceof IContainerDMContext)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
}
|
||||
} else if (e instanceof IExitedDMEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
} else if (e instanceof IStartedDMEvent) {
|
||||
if (((IStartedDMEvent) e).getDMContext() instanceof IContainerDMContext) {
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
return IModelDelta.EXPAND | IModelDelta.SELECT;
|
||||
} else {
|
||||
return IModelDelta.CONTENT;
|
||||
|
@ -91,37 +105,63 @@ public abstract class AbstractContainerVMNode extends AbstractDMVMNode implement
|
|||
}
|
||||
|
||||
public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
|
||||
if(e instanceof IContainerResumedDMEvent &&
|
||||
((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
|
||||
|
||||
if(e instanceof IContainerResumedDMEvent) {
|
||||
// Container resumed:
|
||||
// - If not stepping, update the container and the execution
|
||||
// contexts under it.
|
||||
// - If stepping, do nothing to avoid too many updates. If a
|
||||
// time-out is reached before the step completes, the
|
||||
// ISteppingTimedOutEvent will trigger a full refresh.
|
||||
if (((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
{
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
}
|
||||
} else if (e instanceof IContainerSuspendedDMEvent) {
|
||||
// do nothing
|
||||
// Container suspended. Do nothing here to give the stack the
|
||||
// priority in updating. The container and threads will update as
|
||||
// a result of FullStackRefreshEvent.
|
||||
} else if (e instanceof FullStackRefreshEvent) {
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||
((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
|
||||
{
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
// Workaround for bug 233730: we need to add a separate delta node for the state flag in
|
||||
// order to trigger an update of the run control actions.
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.STATE);
|
||||
// Full-stack refresh event is generated following a suspended event
|
||||
// and a fixed delay. If the suspended event was generated for the
|
||||
// container refresh the whole container.
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
|
||||
}
|
||||
} else if (e instanceof ISteppingTimedOutEvent) {
|
||||
// Stepping time-out indicates that a step operation is taking
|
||||
// a long time, and the view needs to be refreshed to show
|
||||
// the user that the program is running.
|
||||
// If the step was issued for the whole container refresh
|
||||
// the whole container.
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
|
||||
}
|
||||
} else if (e instanceof IExitedDMEvent) {
|
||||
IExecutionDMContext exeContext= ((IExitedDMEvent) e).getDMContext();
|
||||
if (exeContext instanceof IContainerDMContext) {
|
||||
// An exited event could either be for a thread within a container
|
||||
// or for the container itself.
|
||||
// If a container exited, refresh the parent element so that the
|
||||
// container may be removed.
|
||||
// If a thread exited within a container, refresh that container.
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
|
||||
} else {
|
||||
IContainerDMContext containerCtx = DMContexts.getAncestorOfType(exeContext, IContainerDMContext.class);
|
||||
IContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
|
||||
if (containerCtx != null) {
|
||||
parentDelta.addNode(createVMContext(containerCtx), IModelDelta.CONTENT);
|
||||
}
|
||||
}
|
||||
} else if (e instanceof IStartedDMEvent) {
|
||||
IExecutionDMContext exeContext= ((IStartedDMEvent) e).getDMContext();
|
||||
if (exeContext instanceof IContainerDMContext) {
|
||||
parentDelta.addNode(createVMContext(exeContext), IModelDelta.EXPAND | IModelDelta.SELECT);
|
||||
// A started event could either be for a thread within a container
|
||||
// or for the container itself.
|
||||
// If a container started, issue an expand and select event to
|
||||
// show the threads in the new container.
|
||||
// Note: the EXPAND flag implies refreshing the parent element.
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.EXPAND | IModelDelta.SELECT);
|
||||
} else {
|
||||
IContainerDMContext containerCtx = DMContexts.getAncestorOfType(exeContext, IContainerDMContext.class);
|
||||
IContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
|
||||
if (containerCtx != null) {
|
||||
parentDelta.addNode(createVMContext(containerCtx), IModelDelta.CONTENT);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2008 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
|
||||
* Ericsson - Modified for new functionality
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.IDebugEventSetListener;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchesListener2;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class AbstractLaunchVMProvider extends AbstractDMVMProvider
|
||||
implements IDebugEventSetListener, ILaunchesListener2
|
||||
{
|
||||
/**
|
||||
* Delay (in milliseconds) before a full stack trace will be requested.
|
||||
*/
|
||||
private static final int FRAME_UPDATE_DELAY= 200;
|
||||
|
||||
private final Map<IExecutionDMContext,ScheduledFuture<?>> fRefreshStackFramesFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
|
||||
|
||||
@ThreadSafe
|
||||
public AbstractLaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
|
||||
{
|
||||
super(adapter, presentationContext, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new DelayedStackRefreshUpdatePolicy() };
|
||||
}
|
||||
|
||||
public void handleDebugEvents(final DebugEvent[] events) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// We're in session's executor thread. Re-dispach to VM Adapter
|
||||
// executor thread and then call root layout node.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
for (final DebugEvent event : events) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleEvent(IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
|
||||
super.handleEvent(proxyStrategy, event, rm);
|
||||
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
final IExecutionDMContext exeContext= ((IRunControl.ISuspendedDMEvent) event).getDMContext();
|
||||
ScheduledFuture<?> refreshStackFramesFuture = getRefreshFuture(exeContext);
|
||||
// trigger delayed full stack frame update
|
||||
if (refreshStackFramesFuture != null) {
|
||||
// cancel previously scheduled frame update
|
||||
refreshStackFramesFuture.cancel(false);
|
||||
}
|
||||
|
||||
refreshStackFramesFuture = getSession().getExecutor().schedule(
|
||||
new DsfRunnable() {
|
||||
public void run() {
|
||||
if (getSession().isActive()) {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
// trigger full stack frame update
|
||||
ScheduledFuture<?> future= fRefreshStackFramesFutures.get(exeContext);
|
||||
if (future != null && !isDisposed()) {
|
||||
fRefreshStackFramesFutures.remove(exeContext);
|
||||
handleEvent(new FullStackRefreshEvent(exeContext));
|
||||
}
|
||||
}});
|
||||
}
|
||||
}
|
||||
},
|
||||
FRAME_UPDATE_DELAY, TimeUnit.MILLISECONDS);
|
||||
fRefreshStackFramesFutures.put(exeContext, refreshStackFramesFuture);
|
||||
} else if (event instanceof IRunControl.IResumedDMEvent) {
|
||||
IExecutionDMContext exeContext= ((IRunControl.IResumedDMEvent) event).getDMContext();
|
||||
ScheduledFuture<?> refreshStackFramesFuture= fRefreshStackFramesFutures.get(exeContext);
|
||||
if (refreshStackFramesFuture != null) {
|
||||
// cancel previously scheduled frame update
|
||||
refreshStackFramesFuture.cancel(false);
|
||||
fRefreshStackFramesFutures.remove(exeContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the future for the given execution context or for any child of the
|
||||
* given execution context.
|
||||
*/
|
||||
private ScheduledFuture<?> getRefreshFuture(IExecutionDMContext execCtx) {
|
||||
for (IExecutionDMContext refreshCtx : fRefreshStackFramesFutures.keySet()) {
|
||||
if (refreshCtx.equals(execCtx) || DMContexts.isAncestorOf(refreshCtx, execCtx)) {
|
||||
return fRefreshStackFramesFutures.remove(refreshCtx);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
DebugPlugin.getDefault().removeDebugEventListener(this);
|
||||
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void launchesAdded(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.ADDED));
|
||||
}
|
||||
|
||||
public void launchesRemoved(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.REMOVED));
|
||||
}
|
||||
|
||||
public void launchesChanged(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.CHANGED));
|
||||
}
|
||||
|
||||
public void launchesTerminated(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.TERMINATED));
|
||||
}
|
||||
|
||||
private void handleLaunchesEvent(final LaunchesEvent event) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// We're in session's executor thread. Re-dispach to VM Adapter
|
||||
// executor thread and then call root layout node.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
IRootVMNode rootLayoutNode = getRootVMNode();
|
||||
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
|
||||
// To optimize view performance when stepping rapidly, skip events that came
|
||||
// before the last suspended events. However, the debug view can get suspended
|
||||
// events for different threads, so make sure to skip only the events if they
|
||||
// were in the same hierarchy as the last suspended event.
|
||||
if (newEvent instanceof ISuspendedDMEvent && eventToSkip instanceof IDMEvent<?>) {
|
||||
IDMContext newEventDmc = ((IDMEvent<?>)newEvent).getDMContext();
|
||||
IDMContext eventToSkipDmc = ((IDMEvent<?>)eventToSkip).getDMContext();
|
||||
|
||||
if (newEventDmc.equals(eventToSkipDmc) || DMContexts.isAncestorOf(eventToSkipDmc, newEventDmc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
|||
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
|
@ -219,24 +220,19 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode
|
|||
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof IContainerResumedDMEvent || e instanceof IContainerSuspendedDMEvent) {
|
||||
// No need to react to container events, because the container
|
||||
// nodes will deal with them. We need this if statement however,
|
||||
// because the these events extend IResumedDMEvent and
|
||||
// ISuspendedDMEvent and would trigger the if statement below.
|
||||
IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
|
||||
|
||||
if (dmc instanceof IContainerDMContext) {
|
||||
return IModelDelta.NO_CHANGE;
|
||||
} else if (e instanceof IResumedDMEvent &&
|
||||
((IResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
{
|
||||
return IModelDelta.CONTENT;
|
||||
} else if (e instanceof ISuspendedDMEvent) {
|
||||
// no change, update happens on FullStackRefreshEvent
|
||||
return IModelDelta.NO_CHANGE;
|
||||
} else if (e instanceof FullStackRefreshEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||
!(((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) )
|
||||
{
|
||||
} else if (e instanceof ISteppingTimedOutEvent) {
|
||||
return IModelDelta.CONTENT;
|
||||
} else if (e instanceof ModelProxyInstalledEvent) {
|
||||
return IModelDelta.SELECT | IModelDelta.EXPAND;
|
||||
|
@ -245,32 +241,51 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode
|
|||
}
|
||||
|
||||
public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||
if(e instanceof IContainerResumedDMEvent || e instanceof IContainerSuspendedDMEvent) {
|
||||
// No need to react to container events, because the container
|
||||
// nodes will deal with them. We need this if statement however,
|
||||
// because the these events extend IResumedDMEvent and
|
||||
// ISuspendedDMEvent and would trigger the if statement below.
|
||||
IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
|
||||
|
||||
if(dmc instanceof IContainerDMContext) {
|
||||
// The IContainerDMContext sub-classes IExecutionDMContext.
|
||||
// Also IContainerResumedDMEvent sub-classes IResumedDMEvent and
|
||||
// IContainerSuspendedDMEvnet sub-classes ISuspendedEvent.
|
||||
// Because of this relationship, the thread VM node can be called
|
||||
// with data-model evnets for the containers. This statement
|
||||
// filters out those event.
|
||||
rm.done();
|
||||
} else if(e instanceof IResumedDMEvent &&
|
||||
((IResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
|
||||
{
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
} else if(e instanceof IResumedDMEvent) {
|
||||
// Resumed:
|
||||
// - If not stepping, update the thread and its content (its stack).
|
||||
// - If stepping, do nothing to avoid too many updates. If a
|
||||
// time-out is reached before the step completes, the
|
||||
// ISteppingTimedOutEvent will trigger a refresh.
|
||||
if (((IResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP) {
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
|
||||
rm.done();
|
||||
}
|
||||
} else if (e instanceof ISuspendedDMEvent) {
|
||||
// no change
|
||||
// Container suspended. Do nothing here to give the stack the
|
||||
// priority in updating. The thread will update as a result of
|
||||
// FullStackRefreshEvent.
|
||||
rm.done();
|
||||
} else if (e instanceof FullStackRefreshEvent) {
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
// Full-stack refresh event is generated following a suspended event
|
||||
// and a fixed delay. Refresh the whole thread upon this event.
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
|
||||
rm.done();
|
||||
} else if (e instanceof ISteppingTimedOutEvent &&
|
||||
!(((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext) )
|
||||
{
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
|
||||
// Workaround for bug 233730: we need to add a separate delta node for the state flag in
|
||||
// order to trigger an update of the run control actions.
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.STATE);
|
||||
} else if (e instanceof ISteppingTimedOutEvent) {
|
||||
// Stepping time-out indicates that a step operation is taking
|
||||
// a long time, and the view needs to be refreshed to show
|
||||
// the user that the program is running.
|
||||
parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
|
||||
rm.done();
|
||||
} else if (e instanceof ModelProxyInstalledEvent) {
|
||||
// Model Proxy install event is generated when the model is first
|
||||
// populated into the view. This happens when a new debug session
|
||||
// is started or when the view is first opened.
|
||||
// In both cases, if there are already threads in the debug model,
|
||||
// the desired user behavior is to show the threads and to select
|
||||
// the first thread.
|
||||
// If the thread is suspended, do not select the thread, instead,
|
||||
// its top stack frame will be selected.
|
||||
getThreadVMCForModelProxyInstallEvent(
|
||||
parentDelta,
|
||||
new DataRequestMonitor<VMContextInfo>(getExecutor(), rm) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.eclipse.dd.dsf.service.DsfServicesTracker;
|
|||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDACommandControl;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
import org.eclipse.dd.examples.pda.ui.PDAUIPlugin;
|
||||
import org.eclipse.debug.core.commands.IDebugCommandRequest;
|
||||
import org.eclipse.debug.core.commands.IEnabledStateRequest;
|
||||
|
@ -64,7 +64,7 @@ public class PDATerminateCommand implements ITerminateHandler {
|
|||
// Find the PDA program context in the selected element. If one is not found,
|
||||
// the action should be disabled.
|
||||
IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
|
||||
final PDAProgramDMContext pdaProgramCtx = DMContexts.getAncestorOfType(vmc.getDMContext(), PDAProgramDMContext.class);
|
||||
final PDAVirtualMachineDMContext pdaProgramCtx = DMContexts.getAncestorOfType(vmc.getDMContext(), PDAVirtualMachineDMContext.class);
|
||||
if (pdaProgramCtx == null) {
|
||||
request.setEnabled(false);
|
||||
request.done();
|
||||
|
|
|
@ -11,39 +11,35 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.pda.ui.viewmodel.launch;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractLaunchVMProvider;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StandardProcessVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.IDebugEventSetListener;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchesListener2;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
|
||||
/**
|
||||
* View Model provider for the Launch (AKA Debug) view. The PDA debugger is
|
||||
* single-threaded, so there is no need for a debug target element to be visible
|
||||
* in the debug view. Therefore the launch VM provider is configured with three nodes:
|
||||
* View Model provider for the Launch (AKA Debug) view. The launch VM
|
||||
* provider is configured with three nodes:
|
||||
* <ul>
|
||||
* <li> LaunchRootVMNode - This is the root of the PDA view model.</li>
|
||||
* <li> ThreadVMNode - Supplies the PDA program element.</li>
|
||||
* <li> PDAVirtualMachineVMNode - Supplies the element representing PDA VM</li>
|
||||
* <li> PDAThreadsVMNode - Supplies the PDA thread elements</li>
|
||||
* <li> StackFramesVMNode - Supplies the stack frame elements.</li>
|
||||
* <li> StandardProcessVMNode - Supplies elements representing the PDA debugger process.</li>
|
||||
* <li> StandardProcessVMNode - Supplies elements representing the PDA
|
||||
* debugger process.</li>
|
||||
* </ul>
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class PDALaunchVMProvider extends AbstractDMVMProvider
|
||||
public class PDALaunchVMProvider extends AbstractLaunchVMProvider
|
||||
implements IDebugEventSetListener, ILaunchesListener2
|
||||
{
|
||||
@ThreadSafe
|
||||
|
@ -55,82 +51,21 @@ public class PDALaunchVMProvider extends AbstractDMVMProvider
|
|||
setRootNode(launchNode);
|
||||
|
||||
// Launch node is a parent to the processes and program nodes.
|
||||
IVMNode pdaProgramNode = new PDAProgramVMNode(this, getSession());
|
||||
IVMNode pdaVirtualMachineNode = new PDAVirtualMachineVMNode(this, getSession());
|
||||
IVMNode processesNode = new StandardProcessVMNode(this);
|
||||
addChildNodes(launchNode, new IVMNode[] { pdaProgramNode, processesNode});
|
||||
addChildNodes(launchNode, new IVMNode[] { pdaVirtualMachineNode, processesNode});
|
||||
|
||||
// Stack frames node is under the PDA program node.
|
||||
// Virtual machine node is under the PDA threads node.
|
||||
IVMNode threadsNode = new PDAThreadsVMNode(this, getSession());
|
||||
addChildNodes(pdaVirtualMachineNode, new IVMNode[] { threadsNode });
|
||||
|
||||
// Stack frames node is under the PDA threads node.
|
||||
IVMNode stackFramesNode = new StackFramesVMNode(this, getSession());
|
||||
addChildNodes(pdaProgramNode, new IVMNode[] { stackFramesNode });
|
||||
addChildNodes(threadsNode, new IVMNode[] { stackFramesNode });
|
||||
|
||||
// Register the LaunchVM provider as a listener to debug and launch
|
||||
// events. These events are used by the launch and processes nodes.
|
||||
DebugPlugin.getDefault().addDebugEventListener(this);
|
||||
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
|
||||
}
|
||||
|
||||
|
||||
public void handleDebugEvents(final DebugEvent[] events) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// This method may be called on any thread. Switch to the
|
||||
// view model executor thread before processing.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
for (final DebugEvent event : events) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the view model is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
DebugPlugin.getDefault().removeDebugEventListener(this);
|
||||
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public void launchesAdded(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.ADDED));
|
||||
}
|
||||
|
||||
public void launchesRemoved(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.REMOVED));
|
||||
}
|
||||
|
||||
public void launchesChanged(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.CHANGED));
|
||||
}
|
||||
|
||||
public void launchesTerminated(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.TERMINATED));
|
||||
}
|
||||
|
||||
private void handleLaunchesEvent(final LaunchesEvent event) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// This method also may be called on any thread. Switch to the
|
||||
// view model executor thread before processing.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
IRootVMNode rootLayoutNode = getRootVMNode();
|
||||
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the view model is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,354 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2008 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
|
||||
* Ericsson - Modified for multi threaded functionality
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.pda.ui.viewmodel.launch;
|
||||
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMData;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.eclipse.dd.examples.pda.launch.PDALaunch;
|
||||
import org.eclipse.dd.examples.pda.service.PDACommandControl;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAStartedEvent;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.jface.viewers.TreePath;
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
||||
/**
|
||||
* View Model node representing a PDA program.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class PDAProgramVMNode extends AbstractDMVMNode
|
||||
implements IElementLabelProvider, IElementMementoProvider
|
||||
{
|
||||
// View model context representing a terminated PDA program.
|
||||
// It's purpose is to show a terminated program in the debug view
|
||||
// even after the DSF session is terminated.
|
||||
//
|
||||
// Note: this context does not implement the IDMVMContext
|
||||
// interfaces, as it does not use an IDMContext as its root.
|
||||
//
|
||||
// To implement comparison methods, this contexts uses the
|
||||
// VM node object, such that two terminated program contexts
|
||||
// from the same instance of VM node will be equal.
|
||||
private static class TerminatedProgramVMContext extends AbstractVMContext {
|
||||
TerminatedProgramVMContext(IVMNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof TerminatedProgramVMContext) {
|
||||
TerminatedProgramVMContext context = (TerminatedProgramVMContext)obj;
|
||||
return getVMNode().equals(context.getVMNode());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getVMNode().hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public PDAProgramVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session, IExecutionDMContext.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IHasChildrenUpdate[] updates) {
|
||||
for (IHasChildrenUpdate update : updates) {
|
||||
// Check if the launch is initialized. PDA program element should
|
||||
// be shown only if the launch has completed initializing.
|
||||
PDALaunch launch = findLaunchInPath(update.getElementPath());
|
||||
update.setHasChilren(launch != null && launch.isInitialized());
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IChildrenCountUpdate[] updates) {
|
||||
for (IChildrenCountUpdate update : updates) {
|
||||
// Check if the launch is initialized. PDA program element should
|
||||
// be shown only if the launch has completed initializing.
|
||||
PDALaunch launch = findLaunchInPath(update.getElementPath());
|
||||
if (launch != null && launch.isInitialized()) {
|
||||
update.setChildCount(1);
|
||||
} else {
|
||||
update.setChildCount(0);
|
||||
}
|
||||
update.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(IChildrenUpdate[] updates) {
|
||||
for (IChildrenUpdate update : updates) {
|
||||
PDALaunch launch = findLaunchInPath(update.getElementPath());
|
||||
if (launch != null && launch.isInitialized() && launch.isShutDown()) {
|
||||
// If the debug session has been shut down, add a dummy
|
||||
// VM context representing the PDA thread.
|
||||
update.setChild(new TerminatedProgramVMContext(this), 0);
|
||||
update.done();
|
||||
} else {
|
||||
super.update(new IChildrenUpdate[] { update });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(final IChildrenUpdate update) {
|
||||
// Get the instance of the service. Note that there is no race condition
|
||||
// in getting the service since this method is called only in the
|
||||
// service executor thread.
|
||||
final PDACommandControl commandControl = getServicesTracker().getService(PDACommandControl.class);
|
||||
|
||||
// Check if the service is available. If it is not, no elements are
|
||||
// updated.
|
||||
if (commandControl == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setChild(createVMContext(commandControl.getProgramDMContext()), 0);
|
||||
update.done();
|
||||
}
|
||||
|
||||
public void update(final ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
if (update.getElement() instanceof TerminatedProgramVMContext) {
|
||||
// If the element is a terminated program, update the label
|
||||
// in the View Model thread.
|
||||
updateTerminatedThreadLabel(update);
|
||||
} else {
|
||||
// If the element is the PDA Program context, try to switch
|
||||
// to the DSF session thread before updating the label.
|
||||
try {
|
||||
getSession().getExecutor().execute(new DsfRunnable() {
|
||||
public void run() {
|
||||
updateProgramLabelInSessionThread(update);
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Acceptable race condition: DSF session terminated.
|
||||
handleFailedUpdate(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ConfinedToDsfExecutor("getSession().getExecutor()")
|
||||
private void updateProgramLabelInSessionThread(final ILabelUpdate update) {
|
||||
// Get a reference to the run control service.
|
||||
final IRunControl runControl = getServicesTracker().getService(IRunControl.class);
|
||||
if (runControl == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the PDA program context.
|
||||
final PDAProgramDMContext programCtx =
|
||||
findDmcInPath(update.getViewerInput(), update.getElementPath(), PDAProgramDMContext.class);
|
||||
|
||||
// Call service to get current program state
|
||||
final boolean isSuspended = runControl.isSuspended(programCtx);
|
||||
|
||||
// Set the program icon based on the running state of the program.
|
||||
String imageKey = null;
|
||||
if (isSuspended) {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
|
||||
} else {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
|
||||
}
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
|
||||
|
||||
// Retrieve the last state change reason
|
||||
runControl.getExecutionData(
|
||||
programCtx,
|
||||
new ViewerDataRequestMonitor<IExecutionDMData>(ImmediateExecutor.getInstance(), update)
|
||||
{
|
||||
@Override
|
||||
public void handleCompleted(){
|
||||
// If the request failed, fail the udpate.
|
||||
if (!isSuccess()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compose the thread name string.
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("PDA [");
|
||||
builder.append(programCtx.getProgram());
|
||||
builder.append("]");
|
||||
|
||||
if(isSuspended) {
|
||||
builder.append(" (Suspended");
|
||||
} else {
|
||||
builder.append(" (Running");
|
||||
}
|
||||
// Reason will be null before ContainerSuspendEvent is fired
|
||||
if(getData().getStateChangeReason() != null) {
|
||||
builder.append(" : ");
|
||||
builder.append(getData().getStateChangeReason());
|
||||
}
|
||||
builder.append(")");
|
||||
update.setLabel(builder.toString(), 0);
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateTerminatedThreadLabel(ILabelUpdate update) {
|
||||
update.setLabel("<terminated> PDA [" + getProgramName(update) + "]", 0);
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_TERMINATED), 0);
|
||||
update.done();
|
||||
}
|
||||
|
||||
private String getProgramName(IViewerUpdate update) {
|
||||
// Retrieve the program name from the launch object in the update path.
|
||||
String program = "unknown program";
|
||||
ILaunch launch = findLaunchInPath(update.getElementPath());
|
||||
if (launch != null) {
|
||||
try {
|
||||
program = launch.getLaunchConfiguration().getAttribute(PDAPlugin.ATTR_PDA_PROGRAM, program);
|
||||
} catch (CoreException e) {
|
||||
// Ignore, label will revert to default.
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
private PDALaunch findLaunchInPath(TreePath path) {
|
||||
for (int i = 0; i < path.getSegmentCount(); i++) {
|
||||
if (path.getSegment(i) instanceof PDALaunch) {
|
||||
return (PDALaunch)path.getSegment(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getDeltaFlags(Object e) {
|
||||
if(e instanceof IResumedDMEvent || e instanceof ISuspendedDMEvent) {
|
||||
return IModelDelta.STATE;
|
||||
}
|
||||
if (e instanceof PDAStartedEvent) {
|
||||
return IModelDelta.EXPAND | IModelDelta.SELECT;
|
||||
}
|
||||
return IModelDelta.NO_CHANGE;
|
||||
}
|
||||
|
||||
public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor rm) {
|
||||
if(e instanceof IResumedDMEvent || e instanceof ISuspendedDMEvent) {
|
||||
// If a suspended/resumed event is received, just update the
|
||||
// state of the program. StackFramesVMNode will take care of
|
||||
// refreshing the stack frames.
|
||||
parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.STATE);
|
||||
}
|
||||
if (e instanceof PDAStartedEvent) {
|
||||
// When debug session is started expand and select the program.
|
||||
// If the program hits a breakpoint, the top stack frame will then
|
||||
// be selected.
|
||||
parentDelta.addNode(createVMContext(((PDAStartedEvent)e).getDMContext()), IModelDelta.EXPAND | IModelDelta.SELECT);
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
|
||||
*/
|
||||
private String produceProgramElementName( String viewName , PDAProgramDMContext execCtx ) {
|
||||
return "PDA." + execCtx.getProgram(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private final String MEMENTO_NAME = "PDAPROGRAM_MEMENTO_NAME"; //$NON-NLS-1$
|
||||
|
||||
public void compareElements(IElementCompareRequest[] requests) {
|
||||
|
||||
for ( IElementCompareRequest request : requests ) {
|
||||
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
String mementoName = memento.getString(MEMENTO_NAME);
|
||||
|
||||
if (mementoName != null) {
|
||||
if (element instanceof IDMVMContext) {
|
||||
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
|
||||
if ( dmc instanceof PDAProgramDMContext) {
|
||||
|
||||
String elementName = produceProgramElementName( request.getPresentationContext().getId(), (PDAProgramDMContext) dmc );
|
||||
request.setEqual( elementName.equals( mementoName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
|
||||
*/
|
||||
public void encodeElements(IElementMementoRequest[] requests) {
|
||||
|
||||
for ( IElementMementoRequest request : requests ) {
|
||||
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
|
||||
if (element instanceof IDMVMContext) {
|
||||
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
|
||||
if ( dmc instanceof PDAProgramDMContext) {
|
||||
|
||||
String elementName = produceProgramElementName( request.getPresentationContext().getId(), (PDAProgramDMContext) dmc );
|
||||
memento.putString(MEMENTO_NAME, elementName);
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2008 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
|
||||
* Ericsson - Modified for multi threaded functionality
|
||||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.pda.ui.viewmodel.launch;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractThreadVMNode;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMData;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDARunControl;
|
||||
import org.eclipse.dd.examples.pda.service.PDAThreadDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
||||
|
||||
/**
|
||||
* View model node supplying the PDA thread elements. It extends
|
||||
* the base threads node and adds label and memento generation.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class PDAThreadsVMNode extends AbstractThreadVMNode
|
||||
implements IElementLabelProvider, IElementMementoProvider
|
||||
{
|
||||
public PDAThreadsVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
final PDARunControl runControl = getServicesTracker().getService(PDARunControl.class);
|
||||
if ( runControl == null ) {
|
||||
handleFailedUpdate(update);
|
||||
continue;
|
||||
}
|
||||
|
||||
final PDAThreadDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), PDAThreadDMContext.class);
|
||||
|
||||
String imageKey = null;
|
||||
if (getServicesTracker().getService(IRunControl.class).isSuspended(dmc)) {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
|
||||
} else {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
|
||||
}
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
|
||||
|
||||
// Find the Reason for the State
|
||||
runControl.getExecutionData(dmc,
|
||||
new ViewerDataRequestMonitor<IExecutionDMData>(getSession().getExecutor(), update) {
|
||||
@Override
|
||||
public void handleCompleted(){
|
||||
if (!isSuccess()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// We're in a new dispatch cycle, and we have to check whether the
|
||||
// service reference is still valid.
|
||||
final PDARunControl runControl = getServicesTracker().getService(PDARunControl.class);
|
||||
if ( runControl == null ) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
final StateChangeReason reason = getData().getStateChangeReason();
|
||||
|
||||
// Create Labels of type Thread[GDBthreadId]RealThreadID/Name (State: Reason)
|
||||
// Thread[1] 3457 (Suspended:BREAKPOINT)
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Thread ");
|
||||
builder.append(dmc.getID());
|
||||
if(getServicesTracker().getService(IRunControl.class).isSuspended(dmc))
|
||||
builder.append(" (Suspended");
|
||||
else
|
||||
builder.append(" (Running");
|
||||
// Reason will be null before ContainerSuspendEvent is fired
|
||||
if(reason != null) {
|
||||
builder.append(" : ");
|
||||
builder.append(reason);
|
||||
}
|
||||
builder.append(")");
|
||||
update.setLabel(builder.toString(), 0);
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String produceThreadElementName(String viewName, PDAThreadDMContext execCtx) {
|
||||
return "Thread." + execCtx.getID();
|
||||
}
|
||||
|
||||
private static final String MEMENTO_NAME = "THREAD_MEMENTO_NAME";
|
||||
|
||||
/*
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
|
||||
*/
|
||||
public void compareElements(IElementCompareRequest[] requests) {
|
||||
for ( IElementCompareRequest request : requests ) {
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
String mementoName = memento.getString(MEMENTO_NAME);
|
||||
if (mementoName != null) {
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
if ( dmc instanceof PDAThreadDMContext) {
|
||||
String elementName = produceThreadElementName(
|
||||
request.getPresentationContext().getId(), (PDAThreadDMContext) dmc );
|
||||
request.setEqual( elementName.equals( mementoName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
|
||||
*/
|
||||
public void encodeElements(IElementMementoRequest[] requests) {
|
||||
for ( IElementMementoRequest request : requests ) {
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
if (element instanceof IDMVMContext) {
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
if ( dmc instanceof PDAThreadDMContext) {
|
||||
String elementName = produceThreadElementName( request.getPresentationContext().getId(), (PDAThreadDMContext) dmc );
|
||||
memento.putString(MEMENTO_NAME, elementName);
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006, 2008 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
|
||||
* Wind River Systems - Factored out AbstractContainerVMNode
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.dd.examples.pda.ui.viewmodel.launch;
|
||||
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractContainerVMNode;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMData;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.concurrent.ViewerDataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDACommandControl;
|
||||
import org.eclipse.dd.examples.pda.service.PDAStartedEvent;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
|
||||
import org.eclipse.debug.ui.DebugUITools;
|
||||
import org.eclipse.debug.ui.IDebugUIConstants;
|
||||
import org.eclipse.ui.IMemento;
|
||||
|
||||
|
||||
/**
|
||||
* View Model node representing a PDA virtual machine. It extends
|
||||
* the base container node and adds label and memento generation.
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class PDAVirtualMachineVMNode extends AbstractContainerVMNode
|
||||
implements IElementMementoProvider
|
||||
{
|
||||
|
||||
|
||||
public PDAVirtualMachineVMNode(AbstractDMVMProvider provider, DsfSession session) {
|
||||
super(provider, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateElementsInSessionThread(IChildrenUpdate update) {
|
||||
// Get the instance of the service. Note that there is no race condition
|
||||
// in getting the service since this method is called only in the
|
||||
// service executor thread.
|
||||
final PDACommandControl commandControl = getServicesTracker().getService(PDACommandControl.class);
|
||||
|
||||
// Check if the service is available. If it is not, no elements are
|
||||
// updated.
|
||||
if (commandControl == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
update.setChild(createVMContext(commandControl.getVirtualMachineDMContext()), 0);
|
||||
update.done();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateLabelInSessionThread(final ILabelUpdate update) {
|
||||
// Get a reference to the run control service.
|
||||
final IRunControl runControl = getServicesTracker().getService(IRunControl.class);
|
||||
if (runControl == null) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the PDA program context.
|
||||
final PDAVirtualMachineDMContext programCtx =
|
||||
findDmcInPath(update.getViewerInput(), update.getElementPath(), PDAVirtualMachineDMContext.class);
|
||||
|
||||
// Call service to get current program state
|
||||
final boolean isSuspended = runControl.isSuspended(programCtx);
|
||||
|
||||
// Set the program icon based on the running state of the program.
|
||||
String imageKey = null;
|
||||
if (isSuspended) {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
|
||||
} else {
|
||||
imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
|
||||
}
|
||||
update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
|
||||
|
||||
// Retrieve the last state change reason
|
||||
runControl.getExecutionData(
|
||||
programCtx,
|
||||
new ViewerDataRequestMonitor<IExecutionDMData>(ImmediateExecutor.getInstance(), update)
|
||||
{
|
||||
@Override
|
||||
public void handleCompleted(){
|
||||
// If the request failed, fail the udpate.
|
||||
if (!isSuccess()) {
|
||||
handleFailedUpdate(update);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compose the thread name string.
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("PDA [");
|
||||
builder.append(programCtx.getProgram());
|
||||
builder.append("]");
|
||||
|
||||
if(isSuspended) {
|
||||
builder.append(" (Suspended");
|
||||
} else {
|
||||
builder.append(" (Running");
|
||||
}
|
||||
// Reason will be null before ContainerSuspendEvent is fired
|
||||
if(getData().getStateChangeReason() != null) {
|
||||
builder.append(" : ");
|
||||
builder.append(getData().getStateChangeReason());
|
||||
}
|
||||
builder.append(")");
|
||||
update.setLabel(builder.toString(), 0);
|
||||
update.done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
if (e instanceof PDAStartedEvent) {
|
||||
return IModelDelta.EXPAND | IModelDelta.SELECT;
|
||||
}
|
||||
return super.getDeltaFlags(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
|
||||
if (e instanceof PDAStartedEvent) {
|
||||
// When debug session is started expand and select the program.
|
||||
// If the program hits a breakpoint, the top stack frame will then
|
||||
// be selected.
|
||||
parentDelta.addNode(createVMContext(((PDAStartedEvent)e).getDMContext()), IModelDelta.EXPAND | IModelDelta.SELECT);
|
||||
rm.done();
|
||||
} else {
|
||||
super.buildDelta(e, parentDelta, nodeOffset, rm);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
private String produceProgramElementName( String viewName , PDAVirtualMachineDMContext execCtx ) {
|
||||
return "PDA." + execCtx.getProgram(); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private final String MEMENTO_NAME = "PDAPROGRAM_MEMENTO_NAME"; //$NON-NLS-1$
|
||||
|
||||
public void compareElements(IElementCompareRequest[] requests) {
|
||||
|
||||
for ( IElementCompareRequest request : requests ) {
|
||||
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
String mementoName = memento.getString(MEMENTO_NAME);
|
||||
|
||||
if (mementoName != null) {
|
||||
if (element instanceof IDMVMContext) {
|
||||
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
|
||||
if ( dmc instanceof PDAVirtualMachineDMContext) {
|
||||
|
||||
String elementName = produceProgramElementName( request.getPresentationContext().getId(), (PDAVirtualMachineDMContext) dmc );
|
||||
request.setEqual( elementName.equals( mementoName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
|
||||
public void encodeElements(IElementMementoRequest[] requests) {
|
||||
|
||||
for ( IElementMementoRequest request : requests ) {
|
||||
|
||||
Object element = request.getElement();
|
||||
IMemento memento = request.getMemento();
|
||||
|
||||
if (element instanceof IDMVMContext) {
|
||||
|
||||
IDMContext dmc = ((IDMVMContext)element).getDMContext();
|
||||
|
||||
if ( dmc instanceof PDAVirtualMachineDMContext) {
|
||||
|
||||
String elementName = produceProgramElementName( request.getPresentationContext().getId(), (PDAVirtualMachineDMContext) dmc );
|
||||
memento.putString(MEMENTO_NAME, elementName);
|
||||
}
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,8 +20,11 @@ Clears any breakpoint set on given line
|
|||
<h3>data</h3>
|
||||
Retrieves data stack information
|
||||
<pre>
|
||||
C: data
|
||||
C: data {thread_id}
|
||||
R: {value 1}|{value 2}|{value 3}|...|
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -29,10 +32,20 @@ Retrieves data stack information
|
|||
Returns from the current frame without executing the rest of instructions.
|
||||
|
||||
<pre>
|
||||
C: drop
|
||||
If VM running:
|
||||
C: drop {thread_id}
|
||||
R: ok
|
||||
E: resumed drop
|
||||
E: suspended drop
|
||||
E: resumed {thread_id} drop
|
||||
E: suspended {thread_id} drop
|
||||
|
||||
If VM suspended:
|
||||
C: drop {thread_id}
|
||||
R: ok
|
||||
E: vmresumed drop
|
||||
E: vmsuspended {thread_id} drop
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -40,11 +53,16 @@ Returns from the current frame without executing the rest of instructions.
|
|||
Sets what events cause the execution to stop.
|
||||
|
||||
<pre>
|
||||
C: eval {instruction}%20{parameter}|{instruction}%20{parameter}|...
|
||||
C: eval {thread_id} {instruction}%20{parameter}|{instruction}%20{parameter}|...
|
||||
R: ok
|
||||
E: resume client
|
||||
E: resumed {thread_id} client
|
||||
E: evalresult result
|
||||
E: suspended eval
|
||||
E: suspended {thread_id} eval
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
error: cannot evaluate while vm is suspended
|
||||
error: thread running
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -72,8 +90,11 @@ Instructs the debugger to exit.
|
|||
Pops the top value from the data stack
|
||||
|
||||
<pre>
|
||||
C: popdata
|
||||
C: popdata {thread_id}
|
||||
R: ok
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -81,18 +102,27 @@ Pops the top value from the data stack
|
|||
Pushes the given value on top of the data stack.
|
||||
|
||||
<pre>
|
||||
C: pushdata {value}
|
||||
C: pushdata {thread_id} {value}
|
||||
R: ok
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>resume</h3>
|
||||
Resumes the execution
|
||||
Resumes the execution of a single thread. Can be issued only if the virtual
|
||||
machine is running.
|
||||
|
||||
<pre>
|
||||
C: resume
|
||||
C: resume {thread_id}
|
||||
R: ok
|
||||
E: resumed client
|
||||
E: resumed {thread_id} client
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
error: cannot resume thread when vm is suspended
|
||||
error: thread already running
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -100,11 +130,19 @@ Resumes the execution
|
|||
Sets a breakpoint at given line
|
||||
|
||||
<pre>
|
||||
C: set {line_number}
|
||||
Suspend a single thread:
|
||||
C: set {line_number} 0
|
||||
R: ok
|
||||
C: resume
|
||||
E: resumed client
|
||||
E: suspended breakpoint line_number
|
||||
C: resume {thread_id}
|
||||
E: resumed {thread_id} client
|
||||
E: suspended {thread_id} breakpoint line_number
|
||||
|
||||
Suspend the VM:
|
||||
C: set {line_number} 1
|
||||
R: ok
|
||||
C: vmresume
|
||||
E: vmresumed client
|
||||
E: vmsuspended {thread_id} breakpoint line_number
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -112,8 +150,11 @@ Sets a breakpoint at given line
|
|||
Sets a data value in the data stack at the given location
|
||||
|
||||
<pre>
|
||||
C: setdata {index} {value}
|
||||
C: setdata {thread_id} {index} {value}
|
||||
R: ok
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -121,8 +162,11 @@ Sets a data value in the data stack at the given location
|
|||
Sets a variable value
|
||||
|
||||
<pre>
|
||||
C: setvar {frame_number} {variable} {value}
|
||||
C: setvar {thread_id} {frame_number} {variable} {value}
|
||||
R: ok
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -130,8 +174,11 @@ Sets a variable value
|
|||
Retrieves command stack information
|
||||
|
||||
<pre>
|
||||
C: stack
|
||||
R: {file}|{line}|{function}|{var_1}|{var_2}|...{file}|{line}|{function}|{var_1}|{var_2}|......
|
||||
C: stack {thread_id}
|
||||
R: {file}|{line}|{function}|{var_1}|{var_2}|...#{file}|{line}|{function}|{var_1}|{var_2}|...#...
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -139,10 +186,20 @@ Retrieves command stack information
|
|||
Executes next instruction
|
||||
|
||||
<pre>
|
||||
C: step
|
||||
If VM running:
|
||||
C: step {thread_id}
|
||||
R: ok
|
||||
E: resumed step
|
||||
E: suspended step
|
||||
E: resumed {thread_id} client
|
||||
E: suspended {thread_id} step
|
||||
|
||||
If VM suspended:
|
||||
C: step {thread_id}
|
||||
R: ok
|
||||
E: vmresumed client
|
||||
E: vmsuspended {thread_id} step
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -150,29 +207,56 @@ Executes next instruction
|
|||
Executes instructions until the current subroutine is finished
|
||||
|
||||
<pre>
|
||||
C: stepreturn
|
||||
If VM running:
|
||||
C: stepreturn {thread_id}
|
||||
R: ok
|
||||
E: resumed step
|
||||
E: suspended step
|
||||
E: resumed {thread_id} client
|
||||
E: suspended {thread_id} step
|
||||
|
||||
If VM suspended:
|
||||
C: stepreturn {thread_id}
|
||||
R: ok
|
||||
E: vmresumed client
|
||||
E: vmsuspended {thread_id} step
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>suspend</h3>
|
||||
Suspends execution
|
||||
Suspends execution of a single thread. Can be issued only if the virtual
|
||||
machine is running.
|
||||
|
||||
<pre>
|
||||
C: suspend
|
||||
C: suspend {thread_id}
|
||||
R: ok
|
||||
E: suspended client
|
||||
E: suspended {thread_id} client
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
error: vm already suspended
|
||||
error: thread already suspended
|
||||
</pre>
|
||||
|
||||
<h3>threads</h3>
|
||||
Retrieves the list of active threads
|
||||
|
||||
<pre>
|
||||
C: threads
|
||||
R: {thread id} {thread id} ...
|
||||
</pre>
|
||||
|
||||
<h3>var</h3>
|
||||
Retrieves variable value
|
||||
|
||||
<pre>
|
||||
C: var {frame_number} {variable_name}
|
||||
C: var {thread_id} {frame_number} {variable_name}
|
||||
R: {variable_value}
|
||||
|
||||
Errors:
|
||||
error: invalid thread
|
||||
error: variable undefined
|
||||
</pre>
|
||||
|
||||
|
||||
|
@ -194,5 +278,31 @@ The <code>watch_operation<code> value can be:
|
|||
<li>2 - write watch</li>
|
||||
<li>3 - both, etc.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>vmresume</h3>
|
||||
Resumes the execution of the whole virtual machine
|
||||
|
||||
<pre>
|
||||
C: vmresume
|
||||
R: ok
|
||||
E: vmresumed client
|
||||
|
||||
Errors:
|
||||
error: vm already running
|
||||
</pre>
|
||||
|
||||
<h3>vmsuspend</h3>
|
||||
Suspends the execution of the whole virtual machine
|
||||
|
||||
<pre>
|
||||
C: vmsuspend
|
||||
R: ok
|
||||
E: vmsuspended client
|
||||
|
||||
Errors:
|
||||
error: thread already suspended
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -8,4 +8,6 @@ add
|
|||
call zippy
|
||||
add
|
||||
output
|
||||
push 1
|
||||
branch_not_zero swishy
|
||||
halt
|
||||
|
|
23
plugins/org.eclipse.dd.examples.pda/pdavm/tests/vmtest9.pda
Normal file
23
plugins/org.eclipse.dd.examples.pda/pdavm/tests/vmtest9.pda
Normal file
|
@ -0,0 +1,23 @@
|
|||
push 5
|
||||
:thread_create
|
||||
exec foo
|
||||
dec
|
||||
dup
|
||||
branch_not_zero thread_create
|
||||
push finished
|
||||
output
|
||||
halt
|
||||
:foo
|
||||
push thread_created
|
||||
output
|
||||
call inner
|
||||
halt
|
||||
:inner
|
||||
var b
|
||||
call inner2
|
||||
push 2
|
||||
return
|
||||
:inner2
|
||||
var c
|
||||
push 3
|
||||
return
|
|
@ -78,7 +78,7 @@ public class PDAServicesInitSequence extends Sequence {
|
|||
bpmService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
bpmService.startTrackingBreakpoints(fCommandControl.getProgramDMContext(), requestMonitor);
|
||||
bpmService.startTrackingBreakpoints(fCommandControl.getVirtualMachineDMContext(), requestMonitor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class PDAServicesInitSequence extends Sequence {
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor requestMonitor) {
|
||||
fRunControl.resume(fCommandControl.getProgramDMContext(), requestMonitor);
|
||||
fRunControl.resume(fCommandControl.getVirtualMachineDMContext(), requestMonitor);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
|
||||
final Integer fLine;
|
||||
|
||||
public BreakpointDMContext(String sessionId, PDAProgramDMContext commandControlCtx, Integer line) {
|
||||
public BreakpointDMContext(String sessionId, PDAVirtualMachineDMContext commandControlCtx, Integer line) {
|
||||
super(sessionId, new IDMContext[] { commandControlCtx });
|
||||
fLine = line;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
final String fFunction;
|
||||
final String fVariable;
|
||||
|
||||
public WatchpointDMContext(String sessionId, PDAProgramDMContext commandControlCtx, String function,
|
||||
public WatchpointDMContext(String sessionId, PDAVirtualMachineDMContext commandControlCtx, String function,
|
||||
String variable)
|
||||
{
|
||||
super(sessionId, new IDMContext[] { commandControlCtx });
|
||||
|
@ -164,7 +164,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
|
||||
public void getBreakpoints(final IBreakpointsTargetDMContext context, final DataRequestMonitor<IBreakpointDMContext[]> rm) {
|
||||
// Validate the context
|
||||
if (!fCommandControl.getProgramDMContext().equals(context)) {
|
||||
if (!fCommandControl.getVirtualMachineDMContext().equals(context)) {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Invalid breakpoints target context");
|
||||
return;
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// breakpoints mediator, which was called with the program context
|
||||
// in the services initialization sequence. So checking if
|
||||
// programCtx != null is mostly a formality.
|
||||
PDAProgramDMContext programCtx = DMContexts.getAncestorOfType(context, PDAProgramDMContext.class);
|
||||
PDAVirtualMachineDMContext programCtx = DMContexts.getAncestorOfType(context, PDAVirtualMachineDMContext.class);
|
||||
if (programCtx != null) {
|
||||
doInsertBreakpoint(programCtx, attributes, rm);
|
||||
} else {
|
||||
|
@ -209,7 +209,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
}
|
||||
}
|
||||
|
||||
private void doInsertBreakpoint(PDAProgramDMContext programCtx, final Map<String, Object> attributes, final DataRequestMonitor<IBreakpointDMContext> rm)
|
||||
private void doInsertBreakpoint(PDAVirtualMachineDMContext programCtx, final Map<String, Object> attributes, final DataRequestMonitor<IBreakpointDMContext> rm)
|
||||
{
|
||||
// Compare the program path in the breakpoint with the path in the PDA
|
||||
// program context. Only insert the breakpoint if the program matches.
|
||||
|
@ -230,7 +230,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// installed already. PDA can only track a single breakpoint at a
|
||||
// given line, attempting to set the second breakpoint should fail.
|
||||
final BreakpointDMContext breakpointCtx =
|
||||
new BreakpointDMContext(getSession().getId(), fCommandControl.getProgramDMContext(), line);
|
||||
new BreakpointDMContext(getSession().getId(), fCommandControl.getVirtualMachineDMContext(), line);
|
||||
if (fBreakpoints.contains(breakpointCtx)) {
|
||||
PDAPlugin.failRequest(rm, REQUEST_FAILED, "Breakpoint already set");
|
||||
return;
|
||||
|
@ -244,7 +244,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// still being processed here.
|
||||
fBreakpoints.add(breakpointCtx);
|
||||
fCommandControl.queueCommand(
|
||||
new PDASetBreakpointCommand(fCommandControl.getProgramDMContext(), line),
|
||||
new PDASetBreakpointCommand(fCommandControl.getVirtualMachineDMContext(), line, false),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -286,7 +286,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// installed already. PDA can only track a single watchpoint for a given
|
||||
// function::variable, attempting to set the second breakpoint should fail.
|
||||
final WatchpointDMContext watchpointCtx =
|
||||
new WatchpointDMContext(getSession().getId(), fCommandControl.getProgramDMContext(), function, variable);
|
||||
new WatchpointDMContext(getSession().getId(), fCommandControl.getVirtualMachineDMContext(), function, variable);
|
||||
if (fBreakpoints.contains(watchpointCtx)) {
|
||||
PDAPlugin.failRequest(rm, REQUEST_FAILED, "Watchpoint already set");
|
||||
return;
|
||||
|
@ -310,7 +310,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// still being processed here.
|
||||
fBreakpoints.add(watchpointCtx);
|
||||
fCommandControl.queueCommand(
|
||||
new PDAWatchCommand(fCommandControl.getProgramDMContext(), function, variable, watchOperation),
|
||||
new PDAWatchCommand(fCommandControl.getVirtualMachineDMContext(), function, variable, watchOperation),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -350,7 +350,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
fBreakpoints.remove(bpCtx);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
new PDAClearBreakpointCommand(fCommandControl.getProgramDMContext(), bpCtx.fLine),
|
||||
new PDAClearBreakpointCommand(fCommandControl.getVirtualMachineDMContext(), bpCtx.fLine),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm));
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ public class PDABreakpoints extends AbstractDsfService implements IBreakpoints
|
|||
// Watchpoints are cleared using the same command, but with a "no watch" operation
|
||||
fCommandControl.queueCommand(
|
||||
new PDAWatchCommand(
|
||||
fCommandControl.getProgramDMContext(), bpCtx.fFunction, bpCtx.fVariable, PDAWatchCommand.WatchOperation.NONE),
|
||||
fCommandControl.getVirtualMachineDMContext(), bpCtx.fFunction, bpCtx.fVariable, PDAWatchCommand.WatchOperation.NONE),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm));
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ public class PDACommandControl extends AbstractDsfService implements ICommandCon
|
|||
private boolean fTerminated = false;
|
||||
|
||||
// Data Model context of this command control.
|
||||
private PDAProgramDMContext fDMContext;
|
||||
private PDAVirtualMachineDMContext fDMContext;
|
||||
|
||||
// Synchronous listeners for commands and events.
|
||||
private final List<ICommandListener> fCommandListeners = new ArrayList<ICommandListener>();
|
||||
|
@ -137,12 +137,12 @@ public class PDACommandControl extends AbstractDsfService implements ICommandCon
|
|||
|
||||
private void doInitialize(final RequestMonitor rm) {
|
||||
// Create the control's data model context.
|
||||
fDMContext = new PDAProgramDMContext(getSession().getId(), fProgram);
|
||||
fDMContext = new PDAVirtualMachineDMContext(getSession().getId(), fProgram);
|
||||
|
||||
// Add a listener for PDA events to track the started/terminated state.
|
||||
addEventListener(new IEventListener() {
|
||||
public void eventReceived(Object output) {
|
||||
if ("started".equals(output)) {
|
||||
if ("started 1".equals(output)) {
|
||||
setStarted();
|
||||
} else if ("terminated".equals(output)) {
|
||||
setTerminated();
|
||||
|
@ -483,10 +483,10 @@ public class PDACommandControl extends AbstractDsfService implements ICommandCon
|
|||
|
||||
/**
|
||||
* Return the PDA Debugger top-level Data Model context.
|
||||
* @see PDAProgramDMContext
|
||||
* @see PDAVirtualMachineDMContext
|
||||
*/
|
||||
@ThreadSafe
|
||||
public PDAProgramDMContext getProgramDMContext() {
|
||||
public PDAVirtualMachineDMContext getVirtualMachineDMContext() {
|
||||
return fDMContext;
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,7 @@ public class PDACommandControl extends AbstractDsfService implements ICommandCon
|
|||
processQueues();
|
||||
|
||||
// Issue a data model event.
|
||||
getSession().dispatchEvent(new PDAStartedEvent(getProgramDMContext()), getProperties());
|
||||
getSession().dispatchEvent(new PDAStartedEvent(getVirtualMachineDMContext()), getProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -520,7 +520,7 @@ public class PDACommandControl extends AbstractDsfService implements ICommandCon
|
|||
processQueues();
|
||||
|
||||
// Issue a data model event.
|
||||
getSession().dispatchEvent(new PDATerminatedEvent(getProgramDMContext()), getProperties());
|
||||
getSession().dispatchEvent(new PDATerminatedEvent(getVirtualMachineDMContext()), getProperties());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -214,11 +214,12 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
// Create an expression based on the given context and string expression.
|
||||
// The PDA debugger can only evaluate variables as expressions and only
|
||||
// in context of a frame.
|
||||
PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(ctx, PDAThreadDMContext.class);
|
||||
IFrameDMContext frameCtx = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
|
||||
if (frameCtx != null) {
|
||||
if (threadCtx != null && frameCtx != null) {
|
||||
return new ExpressionDMContext(getSession().getId(), frameCtx, expression);
|
||||
} else {
|
||||
// If a frame cannot be found in context, return an "invalid"
|
||||
// If the thread or a frame cannot be found in context, return an "invalid"
|
||||
// expression context, because a null return value is not allowed.
|
||||
// Evaluating an invalid expression context will always yield an
|
||||
// error.
|
||||
|
@ -276,6 +277,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
{
|
||||
final ExpressionDMContext exprCtx = DMContexts.getAncestorOfType(formattedCtx, ExpressionDMContext.class);
|
||||
if (exprCtx != null) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
|
||||
|
||||
// First retrieve the stack depth, needed to properly calculate
|
||||
|
@ -290,7 +292,11 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
|
||||
// Send the command to evaluate the variable.
|
||||
fCommandCache.execute(
|
||||
new PDAVarCommand(fCommandControl.getProgramDMContext(), frameId, exprCtx.getExpression()),
|
||||
new PDAVarCommand(
|
||||
fCommandControl.getVirtualMachineDMContext(),
|
||||
threadCtx.getID(),
|
||||
frameId,
|
||||
exprCtx.getExpression()),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -310,6 +316,7 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
final RequestMonitor rm)
|
||||
{
|
||||
if (exprCtx instanceof ExpressionDMContext) {
|
||||
final PDAThreadDMContext threadCtx = DMContexts.getAncestorOfType(exprCtx, PDAThreadDMContext.class);
|
||||
final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
|
||||
|
||||
// Similarly to retrieving the variable, retrieve the
|
||||
|
@ -324,7 +331,12 @@ public class PDAExpressions extends AbstractDsfService implements IExpressions {
|
|||
|
||||
// Send the "write" command to PDA debugger
|
||||
fCommandCache.execute(
|
||||
new PDASetVarCommand(fCommandControl.getProgramDMContext(), frameId, exprCtx.getExpression(), exprValue),
|
||||
new PDASetVarCommand(
|
||||
fCommandControl.getVirtualMachineDMContext(),
|
||||
threadCtx.getID(),
|
||||
frameId,
|
||||
exprCtx.getExpression(),
|
||||
exprValue),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
|
|
@ -101,7 +101,7 @@ public class PDARegisters extends AbstractDsfService implements IRegisters {
|
|||
* @see org.eclipse.dd.dsf.debug.service.IRegisters#getRegisterGroups(org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext, org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext, org.eclipse.dd.dsf.concurrent.DataRequestMonitor)
|
||||
*/
|
||||
public void getRegisterGroups(IDMContext ctx, DataRequestMonitor<IRegisterGroupDMContext[]> rm ) {
|
||||
PDAProgramDMContext execDmc = DMContexts.getAncestorOfType(ctx, PDAProgramDMContext.class);
|
||||
PDAVirtualMachineDMContext execDmc = DMContexts.getAncestorOfType(ctx, PDAVirtualMachineDMContext.class);
|
||||
if (execDmc == null) {
|
||||
rm.setStatus( new Status( IStatus.ERROR , PDAPlugin.PLUGIN_ID , INVALID_HANDLE , "Container context not found", null ) ) ; //$NON-NLS-1$
|
||||
rm.done();
|
||||
|
@ -738,7 +738,7 @@ public class PDARegisters extends AbstractDsfService implements IRegisters {
|
|||
private int fGroupNo;
|
||||
private String fGroupName;
|
||||
|
||||
public MIRegisterGroupDMC(PDARegisters service, PDAProgramDMContext execDmc, int groupNo, String groupName) {
|
||||
public MIRegisterGroupDMC(PDARegisters service, PDAVirtualMachineDMContext execDmc, int groupNo, String groupName) {
|
||||
super(service.getSession().getId(), new IDMContext[] { execDmc });
|
||||
fGroupNo = groupNo;
|
||||
fGroupName = groupName;
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.examples.pda.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
|
||||
|
@ -26,10 +30,13 @@ import org.eclipse.dd.dsf.service.AbstractDsfService;
|
|||
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.eclipse.dd.examples.pda.service.commands.AbstractPDACommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDACommandResult;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAResumeCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAStepCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDASuspendCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAStepReturnCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAVMResumeCommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDAVMSuspendCommand;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
|
||||
|
@ -56,6 +63,111 @@ public class PDARunControl extends AbstractDsfService
|
|||
// events and track service state, to be perfectly in sync with the service
|
||||
// state.
|
||||
|
||||
static final private IExecutionDMContext[] EMPTY_TRIGGERING_CONTEXTS_ARRAY = new IExecutionDMContext[0];
|
||||
|
||||
@Immutable
|
||||
private static class ThreadResumedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IResumedDMEvent
|
||||
{
|
||||
private final StateChangeReason fReason;
|
||||
|
||||
ThreadResumedEvent(PDAThreadDMContext ctx, StateChangeReason reason) {
|
||||
super(ctx);
|
||||
fReason = reason;
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
return fReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "THREAD RESUMED: " + getDMContext() + " (" + fReason + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class VMResumedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IContainerResumedDMEvent
|
||||
{
|
||||
private final StateChangeReason fReason;
|
||||
|
||||
VMResumedEvent(PDAVirtualMachineDMContext ctx, StateChangeReason reason) {
|
||||
super(ctx);
|
||||
fReason = reason;
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
return fReason;
|
||||
}
|
||||
|
||||
public IExecutionDMContext[] getTriggeringContexts() {
|
||||
return EMPTY_TRIGGERING_CONTEXTS_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VM RESUMED: (" + fReason + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class ThreadSuspendedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements ISuspendedDMEvent
|
||||
{
|
||||
private final StateChangeReason fReason;
|
||||
|
||||
ThreadSuspendedEvent(PDAThreadDMContext ctx, StateChangeReason reason) {
|
||||
super(ctx);
|
||||
fReason = reason;
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
return fReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "THREAD SUSPENDED: " + getDMContext() + " (" + fReason + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class VMSuspendedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IContainerSuspendedDMEvent
|
||||
{
|
||||
private final StateChangeReason fReason;
|
||||
|
||||
final private IExecutionDMContext[] fTriggeringThreads;
|
||||
|
||||
VMSuspendedEvent(PDAVirtualMachineDMContext ctx, PDAThreadDMContext threadCtx, StateChangeReason reason) {
|
||||
super(ctx);
|
||||
fReason = reason;
|
||||
if (threadCtx != null) {
|
||||
fTriggeringThreads = new IExecutionDMContext[] { threadCtx };
|
||||
} else {
|
||||
fTriggeringThreads = EMPTY_TRIGGERING_CONTEXTS_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
return fReason;
|
||||
}
|
||||
|
||||
public IExecutionDMContext[] getTriggeringContexts() {
|
||||
return fTriggeringThreads;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "THREAD SUSPENDED: " + getDMContext() +
|
||||
" (" + fReason +
|
||||
", trigger = " + Arrays.asList(fTriggeringThreads) +
|
||||
")";
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class ExecutionDMData implements IExecutionDMData {
|
||||
private final StateChangeReason fReason;
|
||||
|
@ -65,62 +177,63 @@ public class PDARunControl extends AbstractDsfService
|
|||
public StateChangeReason getStateChangeReason() { return fReason; }
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class ResumedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IResumedDMEvent
|
||||
private static class ThreadStartedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IStartedDMEvent
|
||||
{
|
||||
private final String fPDAEvent;
|
||||
|
||||
ResumedEvent(IExecutionDMContext ctx, String pdaEvent) {
|
||||
super(ctx);
|
||||
fPDAEvent = pdaEvent;
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
if (fPDAEvent.startsWith("resumed breakpoint") || fPDAEvent.startsWith("suspended watch")) {
|
||||
return StateChangeReason.BREAKPOINT;
|
||||
} else if (fPDAEvent.equals("resumed step") || fPDAEvent.equals("resumed drop")) {
|
||||
return StateChangeReason.STEP;
|
||||
} else if (fPDAEvent.equals("resumed client")) {
|
||||
return StateChangeReason.USER_REQUEST;
|
||||
} else {
|
||||
return StateChangeReason.UNKNOWN;
|
||||
}
|
||||
ThreadStartedEvent(PDAThreadDMContext threadCtx) {
|
||||
super(threadCtx);
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class SuspendedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements ISuspendedDMEvent
|
||||
private static class ThreadExitedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IExitedDMEvent
|
||||
{
|
||||
private final String fPDAEvent;
|
||||
|
||||
SuspendedEvent(IExecutionDMContext ctx, String pdaEvent) {
|
||||
super(ctx);
|
||||
fPDAEvent = pdaEvent;
|
||||
}
|
||||
|
||||
public StateChangeReason getReason() {
|
||||
if (fPDAEvent.startsWith("suspended breakpoint") || fPDAEvent.startsWith("suspended watch")) {
|
||||
return StateChangeReason.BREAKPOINT;
|
||||
} else if (fPDAEvent.equals("suspended step") || fPDAEvent.equals("suspended drop")) {
|
||||
return StateChangeReason.STEP;
|
||||
} else if (fPDAEvent.equals("suspended client")) {
|
||||
return StateChangeReason.USER_REQUEST;
|
||||
} else {
|
||||
return StateChangeReason.UNKNOWN;
|
||||
}
|
||||
ThreadExitedEvent(PDAThreadDMContext threadCtx) {
|
||||
super(threadCtx);
|
||||
}
|
||||
}
|
||||
|
||||
// Services
|
||||
private PDACommandControl fCommandControl;
|
||||
|
||||
// State flags
|
||||
private boolean fSuspended = true;
|
||||
private boolean fResumePending = false;
|
||||
private boolean fStepping = false;
|
||||
private StateChangeReason fStateChangeReason;
|
||||
// Reference to the virtual machine data model context
|
||||
private PDAVirtualMachineDMContext fDMContext;
|
||||
|
||||
// VM state flags
|
||||
private boolean fVMSuspended = true;
|
||||
private boolean fVMResumePending = false;
|
||||
private boolean fVMSuspendPending = false;
|
||||
private boolean fVMStepping = false;
|
||||
private StateChangeReason fVMStateChangeReason;
|
||||
|
||||
// Threads' state data
|
||||
private static class ThreadInfo {
|
||||
final PDAThreadDMContext fContext;
|
||||
boolean fSuspended = false;
|
||||
boolean fResumePending = false;
|
||||
boolean fSuspendPending = false;
|
||||
boolean fStepping = false;
|
||||
StateChangeReason fStateChangeReason = StateChangeReason.UNKNOWN;
|
||||
|
||||
ThreadInfo(PDAThreadDMContext context) {
|
||||
fContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fContext.toString() + " (" +
|
||||
(fSuspended ? "SUSPENDED, " : "SUSPENDED, ") +
|
||||
fStateChangeReason +
|
||||
(fResumePending ? ", RESUME_PENDING, " : "") +
|
||||
(fSuspendPending ? ", SUSPEND_PENDING, " : "") +
|
||||
(fStepping ? ", SUSPEND_PENDING, " : "") +
|
||||
")";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Integer, ThreadInfo> fThreads = new LinkedHashMap<Integer, ThreadInfo>();
|
||||
|
||||
|
||||
public PDARunControl(DsfSession session) {
|
||||
super(session);
|
||||
|
@ -142,14 +255,21 @@ public class PDARunControl extends AbstractDsfService
|
|||
}
|
||||
|
||||
private void doInitialize(final RequestMonitor rm) {
|
||||
// Cache a reference to the command control and the virtual machine context
|
||||
fCommandControl = getServicesTracker().getService(PDACommandControl.class);
|
||||
fDMContext = fCommandControl.getVirtualMachineDMContext();
|
||||
|
||||
// Add ourselves as a listener to PDA events, to catch suspended/resumed
|
||||
// events.
|
||||
// Create the main thread context.
|
||||
fThreads.put(
|
||||
1,
|
||||
new ThreadInfo(new PDAThreadDMContext(getSession().getId(), fDMContext, 1)));
|
||||
|
||||
// Add the run control service as a listener to PDA events, to catch
|
||||
// suspended/resumed/started/exited events from the command control.
|
||||
fCommandControl.addEventListener(this);
|
||||
|
||||
// Add ourselves as a listener to service events, in order to process
|
||||
// our own suspended/resumed events.
|
||||
// Add the run control service as a listener to service events as well,
|
||||
// in order to process our own suspended/resumed/started/exited events.
|
||||
getSession().addServiceEventListener(this, null);
|
||||
|
||||
// Register the service with OSGi
|
||||
|
@ -182,42 +302,137 @@ public class PDARunControl extends AbstractDsfService
|
|||
if (!(output instanceof String)) return;
|
||||
String event = (String)output;
|
||||
|
||||
int nameEnd = event.indexOf(' ');
|
||||
nameEnd = nameEnd == -1 ? event.length() : nameEnd;
|
||||
String eventName = event.substring(0, nameEnd);
|
||||
|
||||
PDAThreadDMContext thread = null;
|
||||
StateChangeReason reason = StateChangeReason.UNKNOWN;
|
||||
if (event.length() > nameEnd + 1) {
|
||||
if ( Character.isDigit(event.charAt(nameEnd + 1)) ) {
|
||||
int threadIdEnd = event.indexOf(' ', nameEnd + 1);
|
||||
threadIdEnd = threadIdEnd == -1 ? event.length() : threadIdEnd;
|
||||
try {
|
||||
int threadId = Integer.parseInt(event.substring(nameEnd + 1, threadIdEnd));
|
||||
if (fThreads.containsKey(threadId)) {
|
||||
thread = fThreads.get(threadId).fContext;
|
||||
} else {
|
||||
// In case where a suspended event follows directly a
|
||||
// started event, a thread may not be in the list of
|
||||
// known threads yet. In this case create the
|
||||
// thread context based on the ID.
|
||||
thread = new PDAThreadDMContext(getSession().getId(), fDMContext, threadId);
|
||||
}
|
||||
} catch (NumberFormatException e) {}
|
||||
if (threadIdEnd + 1 < event.length()) {
|
||||
reason = parseStateChangeReason(event.substring(threadIdEnd + 1));
|
||||
}
|
||||
} else {
|
||||
reason = parseStateChangeReason(event.substring(nameEnd + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle PDA debugger suspended/resumed events and issue the
|
||||
// corresponding Data Model events. Do not update the state
|
||||
// information until we start dispatching the service events.
|
||||
if (event.startsWith("suspended")) {
|
||||
IDMEvent<?> dmEvent = new SuspendedEvent(fCommandControl.getProgramDMContext(), event);
|
||||
getSession().dispatchEvent(dmEvent, getProperties());
|
||||
} else if (event.startsWith("resumed")) {
|
||||
IDMEvent<?> dmEvent = new ResumedEvent(fCommandControl.getProgramDMContext(), event);
|
||||
IDMEvent<?> dmEvent = null;
|
||||
if (eventName.equals("suspended") && thread != null) {
|
||||
dmEvent = new ThreadSuspendedEvent(thread, reason);
|
||||
} else if (eventName.equals("resumed") && thread != null) {
|
||||
dmEvent = new ThreadResumedEvent(thread, reason);
|
||||
} else if (event.startsWith("vmsuspended")) {
|
||||
dmEvent = new VMSuspendedEvent(fDMContext, thread, reason);
|
||||
} else if (event.startsWith("vmresumed")) {
|
||||
dmEvent = new VMResumedEvent(fDMContext, reason);
|
||||
} else if (event.startsWith("started") && thread != null) {
|
||||
dmEvent = new ThreadStartedEvent(thread);
|
||||
} else if (event.startsWith("exited") && thread != null) {
|
||||
dmEvent = new ThreadExitedEvent(thread);
|
||||
}
|
||||
|
||||
if (dmEvent != null) {
|
||||
getSession().dispatchEvent(dmEvent, getProperties());
|
||||
}
|
||||
}
|
||||
|
||||
private StateChangeReason parseStateChangeReason(String reasonString) {
|
||||
if (reasonString.startsWith("breakpoint") || reasonString.startsWith("watch")) {
|
||||
return StateChangeReason.BREAKPOINT;
|
||||
} else if (reasonString.equals("step") || reasonString.equals("drop")) {
|
||||
return StateChangeReason.STEP;
|
||||
} else if (reasonString.equals("client")) {
|
||||
return StateChangeReason.USER_REQUEST;
|
||||
} else if (reasonString.startsWith("event")) {
|
||||
return StateChangeReason.SIGNAL;
|
||||
} else {
|
||||
return StateChangeReason.UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ThreadResumedEvent e) {
|
||||
ThreadInfo info = fThreads.get(((PDAThreadDMContext)e.getDMContext()).getID());
|
||||
if (info != null) {
|
||||
info.fSuspended = false;
|
||||
info.fResumePending = false;
|
||||
info.fStateChangeReason = e.getReason();
|
||||
info.fStepping = e.getReason().equals(StateChangeReason.STEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ResumedEvent e) {
|
||||
// This service should be the first to receive the ResumedEvent,
|
||||
// (before any other listeners are called). Here, update the
|
||||
// service state information based on the the resumed event.
|
||||
fSuspended = false;
|
||||
fResumePending = false;
|
||||
fStateChangeReason = e.getReason();
|
||||
fStepping = e.getReason().equals(StateChangeReason.STEP);
|
||||
public void eventDispatched(VMResumedEvent e) {
|
||||
fVMSuspended = false;
|
||||
fVMResumePending = false;
|
||||
fVMStateChangeReason = e.getReason();
|
||||
fVMStepping = e.getReason().equals(StateChangeReason.STEP);
|
||||
for (ThreadInfo info : fThreads.values()) {
|
||||
info.fSuspended = false;
|
||||
info.fStateChangeReason = StateChangeReason.CONTAINER;
|
||||
info.fStepping = false;
|
||||
}
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ThreadSuspendedEvent e) {
|
||||
ThreadInfo info = fThreads.get(((PDAThreadDMContext)e.getDMContext()).getID());
|
||||
if (info != null) {
|
||||
info.fSuspended = true;
|
||||
info.fSuspendPending = false;
|
||||
info.fStateChangeReason = e.getReason();
|
||||
info.fStepping = e.getReason().equals(StateChangeReason.STEP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(SuspendedEvent e) {
|
||||
// This service should be the first to receive the SuspendedEvent also,
|
||||
// (before any other listeners are called). Here, update the
|
||||
// service state information based on the the suspended event.
|
||||
fStateChangeReason = e.getReason();
|
||||
fResumePending = false;
|
||||
fSuspended = true;
|
||||
fStepping = false;
|
||||
public void eventDispatched(VMSuspendedEvent e) {
|
||||
fVMStateChangeReason = e.getReason();
|
||||
fVMSuspendPending = false;
|
||||
fVMSuspended = true;
|
||||
fVMStepping = false;
|
||||
List<IExecutionDMContext> triggeringContexts = Arrays.asList(e.getTriggeringContexts());
|
||||
for (ThreadInfo info : fThreads.values()) {
|
||||
info.fSuspended = true;
|
||||
info.fStateChangeReason = triggeringContexts.contains(info.fContext)
|
||||
? StateChangeReason.STEP : StateChangeReason.CONTAINER;
|
||||
info.fStepping = false;
|
||||
}
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ThreadStartedEvent e) {
|
||||
PDAThreadDMContext threadCtx = (PDAThreadDMContext)e.getDMContext();
|
||||
fThreads.put(threadCtx.getID(), new ThreadInfo(threadCtx));
|
||||
}
|
||||
|
||||
@DsfServiceEventHandler
|
||||
public void eventDispatched(ThreadExitedEvent e) {
|
||||
PDAThreadDMContext threadCtx = (PDAThreadDMContext)e.getDMContext();
|
||||
fThreads.remove(threadCtx.getID());
|
||||
}
|
||||
|
||||
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||
rm.setData(doCanResume(context));
|
||||
|
@ -225,7 +440,34 @@ public class PDARunControl extends AbstractDsfService
|
|||
}
|
||||
|
||||
private boolean doCanResume(IExecutionDMContext context) {
|
||||
return isSuspended(context) && !fResumePending;
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||
// Threads can be resumed only if the VM is not suspended.
|
||||
if (!fVMSuspended) {
|
||||
ThreadInfo state = fThreads.get(threadContext.getID());
|
||||
if (state != null) {
|
||||
return state.fSuspended && !state.fResumePending;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fVMSuspended && !fVMResumePending;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean doCanStep(IExecutionDMContext context, StepType stepType) {
|
||||
if (stepType == StepType.STEP_OVER || stepType == StepType.STEP_RETURN) {
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||
// Only threads can be stepped. But they can be stepped
|
||||
// while the VM is suspended or when just the thread is suspended.
|
||||
ThreadInfo state = fThreads.get(threadContext.getID());
|
||||
if (state != null) {
|
||||
return state.fSuspended && !state.fResumePending;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
|
||||
|
@ -234,34 +476,85 @@ public class PDARunControl extends AbstractDsfService
|
|||
}
|
||||
|
||||
private boolean doCanSuspend(IExecutionDMContext context) {
|
||||
return !isSuspended(context);
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||
// Threads can be resumed only if the VM is not suspended.
|
||||
if (!fVMSuspended) {
|
||||
ThreadInfo state = fThreads.get(threadContext.getID());
|
||||
if (state != null) {
|
||||
return !state.fSuspended && state.fSuspendPending;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return !fVMSuspended && !fVMSuspendPending;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSuspended(IExecutionDMContext context) {
|
||||
return fSuspended;
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||
// Threads can be resumed only if the VM is not suspended.
|
||||
if (!fVMSuspended) {
|
||||
ThreadInfo state = fThreads.get(threadContext.getID());
|
||||
if (state != null) {
|
||||
return state.fSuspended;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fVMSuspended;
|
||||
}
|
||||
|
||||
public boolean isStepping(IExecutionDMContext context) {
|
||||
return !isSuspended(context) && fStepping;
|
||||
if (isSuspended(context)) {
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
PDAThreadDMContext threadContext = (PDAThreadDMContext)context;
|
||||
// Threads can be resumed only if the VM is not suspended.
|
||||
if (!fVMStepping) {
|
||||
ThreadInfo state = fThreads.get(threadContext.getID());
|
||||
if (state != null) {
|
||||
return state.fStepping;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fVMStepping;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resume(IExecutionDMContext context, final RequestMonitor rm) {
|
||||
assert context != null;
|
||||
|
||||
if (doCanResume(context)) {
|
||||
fResumePending = true;
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
final PDAThreadDMContext threadCtx = (PDAThreadDMContext)context;
|
||||
fThreads.get(threadCtx.getID()).fResumePending = true;
|
||||
fCommandControl.queueCommand(
|
||||
new PDAResumeCommand(fCommandControl.getProgramDMContext()),
|
||||
new PDAResumeCommand(fDMContext, threadCtx.getID()),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleFailure() {
|
||||
// If the resume command failed, we no longer
|
||||
// expect to receive a resumed event.
|
||||
fResumePending = false;
|
||||
ThreadInfo threadState = fThreads.get(threadCtx.getID());
|
||||
if (threadState != null) {
|
||||
threadState.fResumePending = false;
|
||||
}
|
||||
super.handleFailure();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
fVMResumePending = true;
|
||||
fCommandControl.queueCommand(
|
||||
new PDAVMResumeCommand(fDMContext),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleFailure() {
|
||||
fVMResumePending = false;
|
||||
super.handleFailure();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, INVALID_STATE, "Given context: " + context + ", is already running.");
|
||||
}
|
||||
|
@ -271,35 +564,79 @@ public class PDARunControl extends AbstractDsfService
|
|||
assert context != null;
|
||||
|
||||
if (doCanSuspend(context)) {
|
||||
if (context instanceof PDAThreadDMContext) {
|
||||
final PDAThreadDMContext threadCtx = (PDAThreadDMContext)context;
|
||||
fThreads.get(threadCtx.getID()).fSuspendPending = true;
|
||||
fCommandControl.queueCommand(
|
||||
new PDASuspendCommand(fCommandControl.getProgramDMContext()),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm));
|
||||
|
||||
new PDAVMSuspendCommand(fDMContext),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleFailure() {
|
||||
ThreadInfo threadState = fThreads.get(threadCtx.getID());
|
||||
if (threadState != null) {
|
||||
threadState.fSuspendPending = false;
|
||||
}
|
||||
super.handleFailure();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
fVMSuspendPending = true;
|
||||
fCommandControl.queueCommand(
|
||||
new PDAVMSuspendCommand(fDMContext),
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleFailure() {
|
||||
fVMSuspendPending = false;
|
||||
super.handleFailure();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_STATE, "Given context: " + context + ", is already suspended.");
|
||||
}
|
||||
}
|
||||
|
||||
public void canStep(IExecutionDMContext context, StepType stepType, DataRequestMonitor<Boolean> rm) {
|
||||
canResume(context, rm);
|
||||
rm.setData(doCanStep(context, stepType));
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void step(IExecutionDMContext context, StepType stepType, final RequestMonitor rm) {
|
||||
assert context != null;
|
||||
|
||||
if (doCanResume(context)) {
|
||||
fResumePending = true;
|
||||
fStepping = true;
|
||||
if (doCanStep(context, stepType)) {
|
||||
final PDAThreadDMContext threadCtx = (PDAThreadDMContext)context;
|
||||
final boolean vmWasSuspneded = fVMSuspended;
|
||||
|
||||
if (vmWasSuspneded) {
|
||||
fVMResumePending = true;
|
||||
} else {
|
||||
fThreads.get(threadCtx.getID()).fResumePending = true;
|
||||
}
|
||||
|
||||
AbstractPDACommand<PDACommandResult> stepCommand =
|
||||
stepType == StepType.STEP_RETURN
|
||||
? new PDAStepReturnCommand(fDMContext, threadCtx.getID())
|
||||
: new PDAStepCommand(fDMContext, threadCtx.getID());
|
||||
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
new PDAStepCommand(fCommandControl.getProgramDMContext()),
|
||||
stepCommand,
|
||||
new DataRequestMonitor<PDACommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleFailure() {
|
||||
// If the step command failed, we no longer
|
||||
// expect to receive a resumed event.
|
||||
fResumePending = false;
|
||||
fStepping = false;
|
||||
if (vmWasSuspneded) {
|
||||
fVMResumePending = false;
|
||||
} else {
|
||||
ThreadInfo threadState = fThreads.get(threadCtx.getID());
|
||||
if (threadState != null) {
|
||||
threadState.fResumePending = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -310,11 +647,26 @@ public class PDARunControl extends AbstractDsfService
|
|||
}
|
||||
|
||||
public void getExecutionContexts(final IContainerDMContext containerDmc, final DataRequestMonitor<IExecutionDMContext[]> rm) {
|
||||
PDAPlugin.failRequest(rm, NOT_SUPPORTED, "Operation not implemented");
|
||||
IExecutionDMContext[] threads = new IExecutionDMContext[fThreads.size()];
|
||||
int i = 0;
|
||||
for (ThreadInfo info : fThreads.values()) {
|
||||
threads[i++] = info.fContext;
|
||||
}
|
||||
rm.setData(threads);
|
||||
rm.done();
|
||||
}
|
||||
|
||||
public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm) {
|
||||
rm.setData( new ExecutionDMData(fStateChangeReason) );
|
||||
if (dmc instanceof PDAThreadDMContext) {
|
||||
ThreadInfo info = fThreads.get(((PDAThreadDMContext)dmc).getID());
|
||||
if (info == null) {
|
||||
PDAPlugin.failRequest(rm, INVALID_HANDLE, "Unknown DMC type");
|
||||
return;
|
||||
}
|
||||
rm.setData( new ExecutionDMData(info.fStateChangeReason) );
|
||||
} else {
|
||||
rm.setData( new ExecutionDMData(fVMStateChangeReason) );
|
||||
}
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@ package org.eclipse.dd.examples.pda.service;
|
|||
import java.util.Hashtable;
|
||||
|
||||
import org.eclipse.cdt.core.IAddress;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.IDsfStatusConstants;
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
|
@ -55,7 +57,7 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
|
||||
final private int fLevel;
|
||||
|
||||
FrameDMContext(String sessionId, IExecutionDMContext execDmc, int level) {
|
||||
FrameDMContext(String sessionId, PDAThreadDMContext execDmc, int level) {
|
||||
super(sessionId, new IDMContext[] { execDmc });
|
||||
fLevel = level;
|
||||
}
|
||||
|
@ -119,7 +121,7 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
|
||||
final private String fVariable;
|
||||
|
||||
VariableDMContext(String sessionId, IFrameDMContext frameCtx, String variable) {
|
||||
VariableDMContext(String sessionId, FrameDMContext frameCtx, String variable) {
|
||||
super(sessionId, new IDMContext[] { frameCtx });
|
||||
fVariable = variable;
|
||||
}
|
||||
|
@ -219,9 +221,18 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
}
|
||||
|
||||
public void getFrameData(final IFrameDMContext frameCtx, final DataRequestMonitor<IFrameDMData> rm) {
|
||||
PDAThreadDMContext threadCtx =
|
||||
DMContexts.getAncestorOfType(frameCtx, PDAThreadDMContext.class);
|
||||
|
||||
if (threadCtx == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + frameCtx, null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the PDA stack command, or retrieve the result from cache if already available.
|
||||
fCommandCache.execute(
|
||||
new PDAStackCommand(fCommandControl.getProgramDMContext()),
|
||||
new PDAStackCommand(fCommandControl.getVirtualMachineDMContext(), threadCtx.getID()),
|
||||
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -246,21 +257,24 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
// however the argument context is a generic context type, so it could
|
||||
// be an execution context, a frame, a variable, etc. Search the
|
||||
// hierarchy of the argument context to find the execution one.
|
||||
final IExecutionDMContext execCtx = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
|
||||
if (execCtx == null) {
|
||||
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_HANDLE, "Invalid context " + context);
|
||||
final PDAThreadDMContext threadCtx =
|
||||
DMContexts.getAncestorOfType(context, PDAThreadDMContext.class);
|
||||
|
||||
if (threadCtx == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + context, null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the stack command and create the corresponding frame contexts.
|
||||
fCommandCache.execute(
|
||||
new PDAStackCommand(fCommandControl.getProgramDMContext()),
|
||||
new PDAStackCommand(fCommandControl.getVirtualMachineDMContext(), threadCtx.getID()),
|
||||
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
IFrameDMContext[] frameCtxs = new IFrameDMContext[getData().fFrames.length];
|
||||
for (int i = 0; i < getData().fFrames.length; i++) {
|
||||
frameCtxs[i] = new FrameDMContext(getSession().getId(), execCtx, i);
|
||||
frameCtxs[i] = new FrameDMContext(getSession().getId(), threadCtx, i);
|
||||
}
|
||||
rm.setData(frameCtxs);
|
||||
rm.done();
|
||||
|
@ -268,10 +282,25 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
});
|
||||
}
|
||||
|
||||
public void getLocals(final IFrameDMContext frameCtx, final DataRequestMonitor<IVariableDMContext[]> rm) {
|
||||
// Execute the stack command again.
|
||||
public void getLocals(IFrameDMContext context, final DataRequestMonitor<IVariableDMContext[]> rm) {
|
||||
if (!(context instanceof FrameDMContext)) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + context, null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
final FrameDMContext frameCtx = (FrameDMContext)context;
|
||||
|
||||
final PDAThreadDMContext threadCtx =
|
||||
DMContexts.getAncestorOfType(frameCtx, PDAThreadDMContext.class);
|
||||
|
||||
if (threadCtx == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + frameCtx, null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
fCommandCache.execute(
|
||||
new PDAStackCommand(fCommandControl.getProgramDMContext()),
|
||||
new PDAStackCommand(fCommandControl.getVirtualMachineDMContext(), threadCtx.getID()),
|
||||
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -296,9 +325,18 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
}
|
||||
|
||||
public void getStackDepth(IDMContext context, int maxDepth, final DataRequestMonitor<Integer> rm) {
|
||||
final PDAThreadDMContext threadCtx =
|
||||
DMContexts.getAncestorOfType(context, PDAThreadDMContext.class);
|
||||
|
||||
if (threadCtx == null) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, PDAPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + context, null));
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute stack command and return the data's size.
|
||||
fCommandCache.execute(
|
||||
new PDAStackCommand(fCommandControl.getProgramDMContext()),
|
||||
new PDAStackCommand(fCommandControl.getVirtualMachineDMContext(), threadCtx.getID()),
|
||||
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
|
@ -313,7 +351,7 @@ public class PDAStack extends AbstractDsfService implements IStack {
|
|||
// however the argument context is a generic context type, so it could
|
||||
// be an execution context, a frame, a variable, etc. Search the
|
||||
// hierarchy of the argument context to find the execution one.
|
||||
final IExecutionDMContext execCtx = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
|
||||
final PDAThreadDMContext execCtx = DMContexts.getAncestorOfType(context, PDAThreadDMContext.class);
|
||||
if (execCtx == null) {
|
||||
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_HANDLE, "Invalid context " + context);
|
||||
return;
|
||||
|
|
|
@ -11,12 +11,16 @@
|
|||
package org.eclipse.dd.examples.pda.service;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IStartedDMEvent;
|
||||
|
||||
/**
|
||||
* Event issued when the PDA debugger is started.
|
||||
*/
|
||||
public class PDAStartedEvent extends AbstractDMEvent<PDAProgramDMContext> {
|
||||
PDAStartedEvent(PDAProgramDMContext context) {
|
||||
public class PDAStartedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IStartedDMEvent
|
||||
{
|
||||
PDAStartedEvent(PDAVirtualMachineDMContext context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,16 @@
|
|||
package org.eclipse.dd.examples.pda.service;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
|
||||
/**
|
||||
* Event issued when the PDA debugger exits.
|
||||
*/
|
||||
public class PDATerminatedEvent extends AbstractDMEvent<PDAProgramDMContext> {
|
||||
PDATerminatedEvent(PDAProgramDMContext context) {
|
||||
public class PDATerminatedEvent extends AbstractDMEvent<IExecutionDMContext>
|
||||
implements IExitedDMEvent
|
||||
{
|
||||
PDATerminatedEvent(PDAVirtualMachineDMContext context) {
|
||||
super(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007, 2008 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.dd.examples.pda.service;
|
||||
|
||||
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
|
||||
/**
|
||||
* Context representing a PDA thread.
|
||||
*/
|
||||
public class PDAThreadDMContext extends AbstractDMContext
|
||||
implements IExecutionDMContext
|
||||
{
|
||||
final private Integer fID;
|
||||
|
||||
public PDAThreadDMContext(String sessionId, PDAVirtualMachineDMContext vmCtx, int id) {
|
||||
super(sessionId, new IDMContext[] { vmCtx });
|
||||
fID = id;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return fID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.baseToString() + ".thread[" + fID + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return baseHashCode() + fID.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return baseEquals(obj) && ((PDAThreadDMContext)obj).fID.equals(fID);
|
||||
}
|
||||
}
|
|
@ -14,12 +14,12 @@ import org.eclipse.core.runtime.PlatformObject;
|
|||
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
|
||||
/**
|
||||
* Top-level Data Model context for the PDA debugger representing the PDA
|
||||
* program.
|
||||
* Top-level Data Model context for the PDA debugger representing the while PDA
|
||||
* virtual machine.
|
||||
* <p>
|
||||
* The PDA debugger is a single-threaded application. Therefore this
|
||||
* top level context implements IExecutionDMContext directly, hence this
|
||||
|
@ -32,20 +32,20 @@ import org.eclipse.dd.dsf.service.DsfSession;
|
|||
* service to install/remove breakpoints.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note: There should only be one instance of PDACommandControlDMContext created
|
||||
* by each PDA command control, so its equals method defaults to using
|
||||
* Note: There should only be one instance of PDAVirtualMachineDMContext
|
||||
* created by each PDA command control, so its equals method defaults to using
|
||||
* instance comparison.
|
||||
* </p>
|
||||
*/
|
||||
public class PDAProgramDMContext extends PlatformObject
|
||||
implements IExecutionDMContext, IBreakpointsTargetDMContext
|
||||
public class PDAVirtualMachineDMContext extends PlatformObject
|
||||
implements IContainerDMContext, IBreakpointsTargetDMContext
|
||||
{
|
||||
final static IDMContext[] EMPTY_PARENTS_ARRAY = new IDMContext[0];
|
||||
|
||||
final private String fSessionId;
|
||||
final private String fProgram;
|
||||
|
||||
public PDAProgramDMContext(String sessionId, String program) {
|
||||
public PDAVirtualMachineDMContext(String sessionId, String program) {
|
||||
fSessionId = sessionId;
|
||||
fProgram = program;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class PDAProgramDMContext extends PlatformObject
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PDA(" + getSessionId() + ")";
|
||||
return "pda[" + getSessionId() + "]";
|
||||
}
|
||||
|
||||
/**
|
|
@ -14,7 +14,7 @@ import org.eclipse.dd.dsf.concurrent.Immutable;
|
|||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.dd.dsf.debug.service.command.ICommandResult;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Base class for PDA commands. The PDA commands consist of a text request and
|
||||
|
@ -27,7 +27,7 @@ abstract public class AbstractPDACommand<V extends PDACommandResult> implements
|
|||
final private IDMContext fContext;
|
||||
final private String fRequest;
|
||||
|
||||
public AbstractPDACommand(PDAProgramDMContext context, String request) {
|
||||
public AbstractPDACommand(PDAVirtualMachineDMContext context, String request) {
|
||||
fContext = context;
|
||||
fRequest = request;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Clears any breakpoint set on given line
|
||||
|
@ -25,7 +25,7 @@ import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
|||
@Immutable
|
||||
public class PDAClearBreakpointCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAClearBreakpointCommand(PDAProgramDMContext context, int line) {
|
||||
public PDAClearBreakpointCommand(PDAVirtualMachineDMContext context, int line) {
|
||||
super(context, "clear " + (line - 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Retrieves data stack information
|
||||
*
|
||||
* <pre>
|
||||
* C: data
|
||||
* C: data {thread_id}
|
||||
* R: {value 1}|{value 2}|{value 3}|...|
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDADataCommand extends AbstractPDACommand<PDADataCommandResult> {
|
||||
|
||||
public PDADataCommand(PDAProgramDMContext context) {
|
||||
super(context, "data");
|
||||
public PDADataCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "data " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,24 +11,33 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Returns from the current frame without executing the rest of instructions.
|
||||
*
|
||||
* <pre>
|
||||
* C: drop
|
||||
* If VM running:
|
||||
* C: drop {thread_id}
|
||||
* R: ok
|
||||
* E: resumed drop
|
||||
* E: suspended drop
|
||||
* E: resumed {thread_id} drop
|
||||
* E: suspended {thread_id} drop
|
||||
*
|
||||
* If VM suspended:
|
||||
* C: drop {thread_id}
|
||||
* R: ok
|
||||
* E: vmresumed drop
|
||||
* E: vmsuspended {thread_id} drop
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
|
||||
*/
|
||||
@Immutable
|
||||
public class PDADropFrameCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDADropFrameCommand(PDAProgramDMContext context) {
|
||||
super(context, "drop");
|
||||
public PDADropFrameCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "drop " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,17 +11,22 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets what events cause the execution to stop.
|
||||
*
|
||||
* <pre>
|
||||
* C: eval {instruction}%20{parameter}|{instruction}%20{parameter}|...
|
||||
* C: eval {thread_id} {instruction}%20{parameter}|{instruction}%20{parameter}|...
|
||||
* R: ok
|
||||
* E: resume client
|
||||
* E: resumed {thread_id} client
|
||||
* E: evalresult result
|
||||
* E: suspended eval
|
||||
* E: suspended {thread_id} eval
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* error: cannot evaluate while vm is suspended
|
||||
* error: thread running
|
||||
* </pre>
|
||||
*
|
||||
* Where event_name could be <code>unimpinstr</code> or <code>nosuchlabel</code>.
|
||||
|
@ -29,8 +34,8 @@ import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
|||
@Immutable
|
||||
public class PDAEvalCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAEvalCommand(PDAProgramDMContext context, String operation) {
|
||||
super(context, "eval " + operation);
|
||||
public PDAEvalCommand(PDAVirtualMachineDMContext context, int threadId, String operation) {
|
||||
super(context, "eval " + threadId + " " + operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets what events cause the execution to stop.
|
||||
|
@ -30,7 +30,7 @@ public class PDAEventStopCommand extends AbstractPDACommand<PDACommandResult> {
|
|||
|
||||
public enum Event { UNIMPINSTR, NOSUCHLABEL };
|
||||
|
||||
public PDAEventStopCommand(PDAProgramDMContext context, Event event, boolean enable) {
|
||||
public PDAEventStopCommand(PDAVirtualMachineDMContext context, Event event, boolean enable) {
|
||||
super(context,
|
||||
"eventstop " +
|
||||
(event == Event.UNIMPINSTR ? "unimpinstr " : "nosuchlabel ") +
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Instructs the debugger to exit.
|
||||
|
@ -24,7 +24,7 @@ import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
|||
@Immutable
|
||||
public class PDAExitCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAExitCommand(PDAProgramDMContext context) {
|
||||
public PDAExitCommand(PDAVirtualMachineDMContext context) {
|
||||
super(context, "exit");
|
||||
}
|
||||
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Pops the top value from the data stack
|
||||
*
|
||||
* <pre>
|
||||
* C: popdata
|
||||
* C: popdata {thread_id}
|
||||
* R: ok
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAPopDataCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAPopDataCommand(PDAProgramDMContext context) {
|
||||
super(context, "popdata");
|
||||
public PDAPopDataCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "popdata " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Pushes the given value on top of the data stack.
|
||||
*
|
||||
* <pre>
|
||||
* C: pushdata {value}
|
||||
* C: pushdata {thread_id} {value}
|
||||
* R: ok
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAPushDataCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAPushDataCommand(PDAProgramDMContext context, int value) {
|
||||
super(context, "pushdata " + value);
|
||||
public PDAPushDataCommand(PDAVirtualMachineDMContext context, int threadId, int value) {
|
||||
super(context, "pushdata " + threadId + " " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,22 +11,28 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Resumes the execution
|
||||
* Resumes the execution of a single thread. Can be issued only if the virtual
|
||||
* machine is running.
|
||||
*
|
||||
* <pre>
|
||||
* C: resume
|
||||
* C: resume {thread_id}
|
||||
* R: ok
|
||||
* E: resumed client
|
||||
* E: resumed {thread_id} client
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* error: cannot resume thread when vm is suspended
|
||||
* error: thread already running
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAResumeCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAResumeCommand(PDAProgramDMContext context) {
|
||||
super(context, "resume");
|
||||
public PDAResumeCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "resume " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,24 +11,35 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets a breakpoint at given line
|
||||
*
|
||||
* <pre>
|
||||
* C: set {line_number}
|
||||
* Suspend a single thread:
|
||||
* C: set {line_number} 0
|
||||
* R: ok
|
||||
* C: resume
|
||||
* E: resumed client
|
||||
* E: suspended breakpoint line_number
|
||||
* C: resume {thread_id}
|
||||
* E: resumed {thread_id} client
|
||||
* E: suspended {thread_id} breakpoint line_number
|
||||
*
|
||||
* Suspend the VM:
|
||||
* C: set {line_number} 1
|
||||
* R: ok
|
||||
* C: vmresume
|
||||
* E: vmresumed client
|
||||
* E: vmsuspended {thread_id} breakpoint line_number
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDASetBreakpointCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDASetBreakpointCommand(PDAProgramDMContext context, int line) {
|
||||
super(context, "set " + (line - 1));
|
||||
public PDASetBreakpointCommand(PDAVirtualMachineDMContext context, int line, boolean stopVM) {
|
||||
super(context,
|
||||
"set " +
|
||||
(line - 1) + " " +
|
||||
(stopVM ? "1" : "0"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets a data value in the data stack at the given location
|
||||
*
|
||||
* <pre>
|
||||
* C: setdata {index} {value}
|
||||
* C: setdata {thread_id} {index} {value}
|
||||
* R: ok
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDASetDataCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDASetDataCommand(PDAProgramDMContext context, int index, String value) {
|
||||
super(context, "setdata " + index + " " + value);
|
||||
public PDASetDataCommand(PDAVirtualMachineDMContext context, int threadId, int index, String value) {
|
||||
super(context, "setdata " + threadId + " " + index + " " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets a variable value
|
||||
*
|
||||
* <pre>
|
||||
* C: setvar {frame_number} {variable} {value}
|
||||
* C: setvar {thread_id} {frame_number} {variable} {value}
|
||||
* R: ok
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDASetVarCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDASetVarCommand(PDAProgramDMContext context, int frame, String variable, String value) {
|
||||
super(context, "setvar " + frame + " " + variable + " " + value);
|
||||
public PDASetVarCommand(PDAVirtualMachineDMContext context, int threadId, int frame, String variable, String value) {
|
||||
super(context, "setvar " + threadId + " " + frame + " " + variable + " " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,21 +11,24 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Retrieves command stack information
|
||||
*
|
||||
* <pre>
|
||||
* C: stack
|
||||
* C: stack {thread_id}
|
||||
* R: {file}|{line}|{function}|{var_1}|{var_2}|...#{file}|{line}|{function}|{var_1}|{var_2}|...#...
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAStackCommand extends AbstractPDACommand<PDAStackCommandResult> {
|
||||
|
||||
public PDAStackCommand(PDAProgramDMContext context) {
|
||||
super(context, "stack");
|
||||
public PDAStackCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "stack " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,23 +11,33 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Executes next instruction
|
||||
*
|
||||
* <pre>
|
||||
* C: step
|
||||
* If VM running:
|
||||
* C: step {thread_id}
|
||||
* R: ok
|
||||
* E: resumed client
|
||||
* E: suspended step
|
||||
* E: resumed {thread_id} client
|
||||
* E: suspended {thread_id} step
|
||||
*
|
||||
* If VM suspended:
|
||||
* C: step {thread_id}
|
||||
* R: ok
|
||||
* E: vmresumed client
|
||||
* E: vmsuspended {thread_id} step
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAStepCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAStepCommand(PDAProgramDMContext context) {
|
||||
super(context, "step");
|
||||
public PDAStepCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "step " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,23 +11,33 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Executes instructions until the current subroutine is finished
|
||||
*
|
||||
* <pre>
|
||||
* C: stepreturn
|
||||
* If VM running:
|
||||
* C: stepreturn {thread_id}
|
||||
* R: ok
|
||||
* E: resumed step
|
||||
* E: suspended step
|
||||
* E: resumed {thread_id} client
|
||||
* E: suspended {thread_id} step
|
||||
*
|
||||
* If VM suspended:
|
||||
* C: stepreturn {thread_id}
|
||||
* R: ok
|
||||
* E: vmresumed client
|
||||
* E: vmsuspended {thread_id} step
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAStepReturnCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAStepReturnCommand(PDAProgramDMContext context) {
|
||||
super(context, "stepreturn");
|
||||
public PDAStepReturnCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "stepreturn " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,22 +11,28 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Suspends execution
|
||||
* Suspends execution of a single thread. Can be issued only if the virtual
|
||||
* machine is running.
|
||||
*
|
||||
* <pre>
|
||||
* C: suspend
|
||||
* C: suspend {thread_id}
|
||||
* R: ok
|
||||
* E: suspended client
|
||||
* E: suspended {thread_id} client
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
error: vm already suspended
|
||||
* error: thread already suspended
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDASuspendCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDASuspendCommand(PDAProgramDMContext context) {
|
||||
super(context, "suspend");
|
||||
public PDASuspendCommand(PDAVirtualMachineDMContext context, int threadId) {
|
||||
super(context, "suspend " + threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Resumes the execution of the whole virtual machine
|
||||
*
|
||||
* <pre>
|
||||
* C: vmresume
|
||||
* R: ok
|
||||
* E: vmresumed client
|
||||
*
|
||||
* Errors:
|
||||
* error: vm already running
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAVMResumeCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAVMResumeCommand(PDAVirtualMachineDMContext context) {
|
||||
super(context, "vmresume");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDACommandResult createResult(String resultText) {
|
||||
return new PDACommandResult(resultText);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Suspends the execution of the whole virtual machine
|
||||
*
|
||||
* <pre>
|
||||
* C: vmsuspend
|
||||
* R: ok
|
||||
* E: vmsuspended client
|
||||
*
|
||||
* Errors:
|
||||
* error: thread already suspended
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAVMSuspendCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAVMSuspendCommand(PDAVirtualMachineDMContext context) {
|
||||
super(context, "vmsuspend");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDACommandResult createResult(String resultText) {
|
||||
return new PDACommandResult(resultText);
|
||||
}
|
||||
}
|
|
@ -11,21 +11,25 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Retrieves variable value
|
||||
*
|
||||
* <pre>
|
||||
* C: var {frame_number} {variable_name}
|
||||
* C: var {thread_id} {frame_number} {variable_name}
|
||||
* R: {variable_value}
|
||||
*
|
||||
* Errors:
|
||||
* error: invalid thread
|
||||
* error: variable undefined
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
public class PDAVarCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
|
||||
public PDAVarCommand(PDAProgramDMContext context, int frameId, String name) {
|
||||
super(context, "var " + frameId + " " + name);
|
||||
public PDAVarCommand(PDAVirtualMachineDMContext context, int threadId, int frameId, String name) {
|
||||
super(context, "var " + threadId + " " + frameId + " " + name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
package org.eclipse.dd.examples.pda.service.commands;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.Immutable;
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
|
||||
/**
|
||||
* Sets a watchpoint on a given variable
|
||||
|
@ -19,9 +19,9 @@ import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
|||
* <pre>
|
||||
* C: watch {function}::{variable_name} {watch_operation}
|
||||
* R: ok
|
||||
* C: resume
|
||||
* R: resume client
|
||||
* E: suspended watch {watch_operation} {function}::{variable_name}
|
||||
* C: vmresume
|
||||
* R: vmresumed client
|
||||
* E: vmsuspended {thread_id} watch {watch_operation} {function}::{variable_name}
|
||||
* </pre>
|
||||
*/
|
||||
@Immutable
|
||||
|
@ -42,7 +42,7 @@ public class PDAWatchCommand extends AbstractPDACommand<PDACommandResult> {
|
|||
}
|
||||
}
|
||||
|
||||
public PDAWatchCommand(PDAProgramDMContext context, String function, String variable, WatchOperation operation) {
|
||||
public PDAWatchCommand(PDAVirtualMachineDMContext context, String function, String variable, WatchOperation operation) {
|
||||
super(context, "watch " + function+ "::" + variable + " " + getWatchOperationCode(operation));
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public class BasicTests extends CommandControlTestsBase {
|
|||
}
|
||||
});
|
||||
|
||||
final PDATestCommand testCommand = new PDATestCommand(fCommandControl.getProgramDMContext(), "data");
|
||||
final PDATestCommand testCommand = new PDATestCommand(fCommandControl.getVirtualMachineDMContext(), "data 1");
|
||||
|
||||
// Test sending the command and checking all listeners were called.
|
||||
Query<PDACommandResult> sendCommandQuery = new Query<PDACommandResult>() {
|
||||
|
|
|
@ -105,7 +105,7 @@ public class CommandControlTestsBase {
|
|||
|
||||
protected void sendCommand(String command, String expectedResult) throws Throwable {
|
||||
|
||||
final PDATestCommand testCommand = new PDATestCommand(fCommandControl.getProgramDMContext(), command);
|
||||
final PDATestCommand testCommand = new PDATestCommand(fCommandControl.getVirtualMachineDMContext(), command);
|
||||
|
||||
// Test sending the command and checking all listeners were called.
|
||||
Query<PDACommandResult> sendCommandQuery = new Query<PDACommandResult>() {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.tests.pda.service.command;
|
||||
|
||||
import org.eclipse.dd.examples.pda.service.PDAProgramDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.PDAVirtualMachineDMContext;
|
||||
import org.eclipse.dd.examples.pda.service.commands.AbstractPDACommand;
|
||||
import org.eclipse.dd.examples.pda.service.commands.PDACommandResult;
|
||||
|
||||
|
@ -18,7 +18,7 @@ import org.eclipse.dd.examples.pda.service.commands.PDACommandResult;
|
|||
*
|
||||
*/
|
||||
class PDATestCommand extends AbstractPDACommand<PDACommandResult> {
|
||||
PDATestCommand(PDAProgramDMContext context, String command) {
|
||||
PDATestCommand(PDAVirtualMachineDMContext context, String command) {
|
||||
super(context, command);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ public class Test1 extends CommandControlTestsBase {
|
|||
|
||||
@Test
|
||||
public void testRun() throws Throwable {
|
||||
sendCommand("resume");
|
||||
sendCommand("vmresume");
|
||||
expectOutput("\"hello\"");
|
||||
expectOutput("\"barfoo\"");
|
||||
expectOutput("\"first\"");
|
||||
|
|
|
@ -31,79 +31,161 @@ public class Test2 extends CommandControlTestsBase {
|
|||
|
||||
@Test
|
||||
public void testCommonDebugCommands() throws Throwable {
|
||||
expectEvent("started");
|
||||
expectEvent("started 1");
|
||||
// test step
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
// test breakpoint
|
||||
sendCommand("set 4");
|
||||
sendCommand("data", "6|");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 4");
|
||||
sendCommand("set 4 1");
|
||||
sendCommand("data 1", "6|");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 4");
|
||||
// test data stack
|
||||
sendCommand("data", "6|7|8|9|");
|
||||
sendCommand("popdata");
|
||||
sendCommand("data", "6|7|8|");
|
||||
sendCommand("pushdata 11");
|
||||
sendCommand("data", "6|7|8|11|");
|
||||
sendCommand("setdata 1 2");
|
||||
sendCommand("data", "6|2|8|11|");
|
||||
sendCommand("data 1", "6|7|8|9|");
|
||||
sendCommand("popdata 1");
|
||||
sendCommand("data 1", "6|7|8|");
|
||||
sendCommand("pushdata 1 11");
|
||||
sendCommand("data 1", "6|7|8|11|");
|
||||
sendCommand("setdata 1 1 2");
|
||||
sendCommand("data 1", "6|2|8|11|");
|
||||
// test call stack
|
||||
sendCommand("set 12");
|
||||
sendCommand("set 19");
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 12");
|
||||
sendCommand("set 12 1");
|
||||
sendCommand("set 19 1");
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 breakpoint 12");
|
||||
sendCommand("clear 19");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|13|sub2" );
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|6|main#" + fProgram + "|22|sub1|m|n" );
|
||||
sendCommand("set 6");
|
||||
sendCommand("stepreturn");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 6");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|13|sub2" );
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|22|sub1|m|n" );
|
||||
sendCommand("set 6 1");
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 breakpoint 6");
|
||||
// test set and clear
|
||||
sendCommand("set 27");
|
||||
sendCommand("set 29");
|
||||
sendCommand("set 33");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 33");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 27");
|
||||
sendCommand("set 27 1");
|
||||
sendCommand("set 29 1");
|
||||
sendCommand("set 33 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 33");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 27");
|
||||
sendCommand("clear 33");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 29");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 29");
|
||||
// test var and setvar
|
||||
sendCommand("set 47");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 47");
|
||||
sendCommand("var 1 b", "4");
|
||||
sendCommand("var 2 b", "2");
|
||||
sendCommand("var 1 a", "0");
|
||||
sendCommand("setvar 1 a 99");
|
||||
sendCommand("data", "6|2|8|11|27|1|4|");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("var 1 a", "99");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("data", "6|2|8|11|27|1|4|99|");
|
||||
sendCommand("set 47 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 47");
|
||||
sendCommand("var 1 1 b", "4");
|
||||
sendCommand("var 1 2 b", "2");
|
||||
sendCommand("var 1 1 a", "0");
|
||||
sendCommand("setvar 1 1 a 99");
|
||||
sendCommand("data 1", "6|2|8|11|27|1|4|");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("var 1 1 a", "99");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("data 1", "6|2|8|11|27|1|4|99|");
|
||||
sendCommand("var 1 1 x", "error: variable undefined");
|
||||
sendCommand("setvar 1 1 x 100");
|
||||
sendCommand("var 1 1 x", "100");
|
||||
// test exit
|
||||
sendCommand("exit");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCommonDebugCommandsWithThreadRC() throws Throwable {
|
||||
expectEvent("started 1");
|
||||
// test breakpoint
|
||||
sendCommand("set 3 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("suspended 1 breakpoint 3");
|
||||
sendCommand("data 1", "6|7|8|");
|
||||
// test step
|
||||
sendCommand("step 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
// test data stack
|
||||
sendCommand("data 1", "6|7|8|9|");
|
||||
sendCommand("popdata 1");
|
||||
sendCommand("data 1", "6|7|8|");
|
||||
sendCommand("pushdata 1 11");
|
||||
sendCommand("data 1", "6|7|8|11|");
|
||||
sendCommand("setdata 1 1 2");
|
||||
sendCommand("data 1", "6|2|8|11|");
|
||||
// test call stack
|
||||
sendCommand("set 12 0");
|
||||
sendCommand("set 19 0");
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 breakpoint 12");
|
||||
sendCommand("clear 19");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|13|sub2" );
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|22|sub1|m|n" );
|
||||
sendCommand("set 6 0");
|
||||
sendCommand("stepreturn 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 breakpoint 6");
|
||||
// test set and clear
|
||||
sendCommand("set 27 0");
|
||||
sendCommand("set 29 0");
|
||||
sendCommand("set 33 0");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("suspended 1 breakpoint 33");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("suspended 1 breakpoint 27");
|
||||
sendCommand("clear 33");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("suspended 1 breakpoint 29");
|
||||
// test var and setvar
|
||||
sendCommand("set 47 0");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("suspended 1 breakpoint 47");
|
||||
sendCommand("var 1 1 b", "4");
|
||||
sendCommand("var 1 2 b", "2");
|
||||
sendCommand("var 1 1 a", "0");
|
||||
sendCommand("setvar 1 1 a 99");
|
||||
sendCommand("data 1", "6|2|8|11|27|1|4|");
|
||||
sendCommand("step 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("var 1 1 a", "99");
|
||||
sendCommand("step 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("data 1", "6|2|8|11|27|1|4|99|");
|
||||
// test exit
|
||||
sendCommand("exit");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,43 +31,59 @@ public class Test3 extends CommandControlTestsBase {
|
|||
|
||||
@Test
|
||||
public void testUncaughtEvents() throws Throwable {
|
||||
expectEvent("started");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("started 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("unimplemented instruction foobar");
|
||||
expectEvent("no such label zippy");
|
||||
expectEvent("no such label swishy");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaughtUnimpinstrEvents() throws Throwable {
|
||||
expectEvent("started");
|
||||
expectEvent("started 1");
|
||||
sendCommand("eventstop unimpinstr 1");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("unimplemented instruction foobar");
|
||||
expectEvent("suspended event unimpinstr");
|
||||
expectEvent("vmsuspended 1 event unimpinstr");
|
||||
sendCommand("eventstop unimpinstr 0");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("unimplemented instruction foobar");
|
||||
expectEvent("no such label zippy");
|
||||
expectEvent("no such label swishy");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaughtNosuchlabelEvents() throws Throwable {
|
||||
expectEvent("started");
|
||||
expectEvent("started 1");
|
||||
sendCommand("eventstop nosuchlabel 1");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("unimplemented instruction foobar");
|
||||
expectEvent("no such label zippy");
|
||||
expectEvent("suspended event nosuchlabel");
|
||||
expectEvent("vmsuspended 1 event nosuchlabel");
|
||||
sendCommand("eventstop nosuchlabel 0");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("set 11 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("no such label zippy");
|
||||
expectEvent("vmsuspended 1 breakpoint 11");
|
||||
sendCommand("eventstop nosuchlabel 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("no such label swishy");
|
||||
expectEvent("vmsuspended 1 event nosuchlabel");
|
||||
sendCommand("eventstop nosuchlabel 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("no such label swishy");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
|
|
|
@ -31,49 +31,54 @@ public class Test6 extends CommandControlTestsBase {
|
|||
|
||||
@Test
|
||||
public void testWatchPoints() throws Throwable {
|
||||
expectEvent("started");
|
||||
expectEvent("started 1");
|
||||
sendCommand("watch inner::a 1");
|
||||
sendCommand("watch main::a 2");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended watch write main::a");
|
||||
sendCommand("stack", fProgram + "|4|main|a|b");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended watch read inner::a");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|25|inner|a|c");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 watch write main::a");
|
||||
sendCommand("stack 1", fProgram + "|4|main|a|b");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 watch read inner::a");
|
||||
sendCommand("stack 1", fProgram + "|10|main|a|b#" + fProgram + "|25|inner|a|c");
|
||||
sendCommand("watch inner::a 0");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEval() throws Throwable {
|
||||
expectEvent("started");
|
||||
sendCommand("set 25");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended breakpoint 25");
|
||||
expectEvent("started 1");
|
||||
|
||||
sendCommand("eval push%204|push%205|add");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("eval 1 test_error", "error: cannot evaluate while vm is suspended");
|
||||
|
||||
sendCommand("set 25 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("suspended 1 breakpoint 25");
|
||||
|
||||
sendCommand("eval 1 push%204|push%205|add");
|
||||
expectEvent("resumed 1 eval");
|
||||
expectEvent("evalresult 9");
|
||||
expectEvent("suspended eval");
|
||||
expectEvent("suspended 1 eval");
|
||||
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data", "4|4|");
|
||||
sendCommand("eval call%20other");
|
||||
expectEvent("resumed client");
|
||||
sendCommand("step 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data 1", "4|4|");
|
||||
sendCommand("eval 1 call%20other");
|
||||
expectEvent("resumed 1 eval");
|
||||
expectEvent("evalresult 15");
|
||||
expectEvent("suspended eval");
|
||||
sendCommand("stack", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data", "4|4|");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("suspended 1 eval");
|
||||
sendCommand("stack 1", fProgram + "|10|main|a|b#" + fProgram + "|26|inner|a|c");
|
||||
sendCommand("data 1", "4|4|");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,39 +31,63 @@ public class Test8 extends CommandControlTestsBase {
|
|||
|
||||
@Test
|
||||
public void testDropFrame() throws Throwable {
|
||||
expectEvent("started");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|12|inner2|c");
|
||||
sendCommand("drop");
|
||||
expectEvent("resumed drop");
|
||||
expectEvent("suspended drop");
|
||||
sendCommand("stack", fProgram + "|2|main|a#" + fProgram + "|7|inner|b");
|
||||
sendCommand("step");
|
||||
expectEvent("resumed step");
|
||||
expectEvent("suspended step");
|
||||
sendCommand("stack", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|10|inner2");
|
||||
sendCommand("resume");
|
||||
expectEvent("resumed client");
|
||||
expectEvent("started 1");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|12|inner2|c");
|
||||
sendCommand("drop 1");
|
||||
expectEvent("vmresumed drop");
|
||||
expectEvent("vmsuspended 1 drop");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|7|inner|b");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|10|inner2");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDropFrameWithThreadRC() throws Throwable {
|
||||
expectEvent("started 1");
|
||||
sendCommand("set 12 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("suspended 1 breakpoint 12");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|12|inner2|c");
|
||||
sendCommand("drop 1");
|
||||
expectEvent("resumed 1 drop");
|
||||
expectEvent("suspended 1 drop");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|7|inner|b");
|
||||
sendCommand("step 1");
|
||||
expectEvent("resumed 1 step");
|
||||
expectEvent("suspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|2|main|a#" + fProgram + "|8|inner|b#" + fProgram + "|10|inner2");
|
||||
sendCommand("clear 12");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 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.dd.tests.pda.service.command;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.dd.examples.pda.PDAPlugin;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class Test9 extends CommandControlTestsBase {
|
||||
|
||||
@BeforeClass
|
||||
public static void setProgram() {
|
||||
File programFile = PDAPlugin.getFileInPlugin(new Path("pdavm/tests/vmtest9.pda"));
|
||||
|
||||
fProgram = programFile.getPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadsWithVMRC() throws Throwable {
|
||||
expectEvent("started 1");
|
||||
sendCommand("state", "client");
|
||||
sendCommand("state 1", "vm");
|
||||
|
||||
// Check error responses
|
||||
sendCommand("vmsuspend", "error: vm already suspended");
|
||||
sendCommand("resume 1", "error: cannot resume thread when vm is suspended");
|
||||
|
||||
// Run to thread create routine
|
||||
sendCommand("threads", "1");
|
||||
sendCommand("set 2 1");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("vmsuspended 1 breakpoint 2");
|
||||
sendCommand("state", "1 breakpoint 2");
|
||||
sendCommand("state 1", "vm");
|
||||
|
||||
// Step over first thread create
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("started 2");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("state", "1 step");
|
||||
sendCommand("state 1", "vm");
|
||||
sendCommand("threads", "1 2");
|
||||
sendCommand("stack 1", fProgram + "|3|main");
|
||||
sendCommand("stack 2", fProgram + "|9|foo");
|
||||
sendCommand("step 1");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 1 step");
|
||||
sendCommand("stack 1", fProgram + "|4|main");
|
||||
sendCommand("stack 2", fProgram + "|10|foo");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectOutput("thread_created");
|
||||
expectEvent("vmsuspended 1 breakpoint 2");
|
||||
|
||||
// Step over second thread create
|
||||
sendCommand("step 2");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("started 3");
|
||||
expectEvent("vmsuspended 2 step");
|
||||
sendCommand("threads", "1 2 3");
|
||||
sendCommand("stack 1", fProgram + "|3|main");
|
||||
sendCommand("stack 2", fProgram + "|13|foo#" + fProgram + "|15|inner");
|
||||
sendCommand("stack 3", fProgram + "|9|foo");
|
||||
sendCommand("step 3");
|
||||
expectEvent("vmresumed step");
|
||||
expectEvent("vmsuspended 3 step");
|
||||
sendCommand("stack 1", fProgram + "|4|main");
|
||||
sendCommand("stack 2", fProgram + "|13|foo#" + fProgram + "|16|inner|b");
|
||||
sendCommand("stack 3", fProgram + "|10|foo");
|
||||
|
||||
// Run to the end and watch threads starting/exiting.
|
||||
sendCommand("clear 2");
|
||||
sendCommand("vmresume");
|
||||
expectOutput("thread_created");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("started 4");
|
||||
expectEvent("exited 2");
|
||||
expectEvent("started 5");
|
||||
expectEvent("exited 3");
|
||||
expectEvent("started 6");
|
||||
expectEvent("exited 4");
|
||||
expectEvent("exited 1");
|
||||
expectEvent("exited 5");
|
||||
expectEvent("exited 6");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadsWithThreadRC() throws Throwable {
|
||||
expectEvent("started 1");
|
||||
|
||||
// Check error responses for thread run control
|
||||
sendCommand("set 1 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("suspended 1 breakpoint 1");
|
||||
sendCommand("state", "running");
|
||||
sendCommand("state 1", "breakpoint 1");
|
||||
|
||||
sendCommand("resume", "error: invalid thread");
|
||||
sendCommand("vmresume", "error: vm already running");
|
||||
sendCommand("clear 1");
|
||||
sendCommand("suspend 1", "error: thread already suspended");
|
||||
sendCommand("vmsuspend");
|
||||
expectEvent("vmsuspended client");
|
||||
sendCommand("state", "client");
|
||||
sendCommand("state 1", "vm");
|
||||
sendCommand("suspend 1", "error: vm already suspended");
|
||||
sendCommand("resume 1", "error: cannot resume thread when vm is suspended");
|
||||
|
||||
// Create breakpoints at thread create and thread entry point.
|
||||
sendCommand("set 2 0");
|
||||
sendCommand("set 10 0");
|
||||
sendCommand("vmresume");
|
||||
expectEvent("vmresumed client");
|
||||
expectEvent("suspended 1 breakpoint 2");
|
||||
|
||||
// Create first thread, and run it to completion
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("started 2");
|
||||
expectEvent("suspended 2 breakpoint 10");
|
||||
expectEvent("suspended 1 breakpoint 2");
|
||||
sendCommand("state 1", "breakpoint 2");
|
||||
sendCommand("state 2", "breakpoint 10");
|
||||
sendCommand("threads", "1 2");
|
||||
sendCommand("resume 2");
|
||||
expectEvent("resumed 2 client");
|
||||
expectEvent("exited 2");
|
||||
sendCommand("threads", "1");
|
||||
|
||||
// Create second thread, step it
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("started 3");
|
||||
expectEvent("suspended 3 breakpoint 10");
|
||||
expectEvent("suspended 1 breakpoint 2");
|
||||
sendCommand("threads", "1 3");
|
||||
sendCommand("stack 1", fProgram + "|2|main");
|
||||
sendCommand("stack 3", fProgram + "|10|foo");
|
||||
sendCommand("step 3");
|
||||
expectEvent("resumed 3 step");
|
||||
expectEvent("suspended 3 step");
|
||||
sendCommand("state 1", "breakpoint 2");
|
||||
sendCommand("state 3", "step");
|
||||
sendCommand("stack 1", fProgram + "|2|main");
|
||||
sendCommand("stack 3", fProgram + "|11|foo");
|
||||
|
||||
// Create the rest of threads
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("started 4");
|
||||
expectEvent("suspended 4 breakpoint 10");
|
||||
expectEvent("suspended 1 breakpoint 2");
|
||||
sendCommand("threads", "1 3 4");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
expectEvent("started 5");
|
||||
expectEvent("suspended 5 breakpoint 10");
|
||||
expectEvent("suspended 1 breakpoint 2");
|
||||
sendCommand("threads", "1 3 4 5");
|
||||
sendCommand("resume 1");
|
||||
expectEvent("resumed 1 client");
|
||||
|
||||
// Main thread exits
|
||||
expectEvent("started 6");
|
||||
expectEvent("suspended 6 breakpoint 10");
|
||||
expectEvent("exited 1");
|
||||
sendCommand("threads", "3 4 5 6");
|
||||
|
||||
// Exit
|
||||
sendCommand("exit");
|
||||
expectEvent("terminated");
|
||||
}
|
||||
|
||||
}
|
|
@ -68,12 +68,11 @@ public class ContainerVMNode extends AbstractContainerVMNode
|
|||
|
||||
|
||||
@Override
|
||||
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
|
||||
for (final ILabelUpdate update : updates) {
|
||||
protected void updateLabelInSessionThread(final ILabelUpdate update) {
|
||||
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
|
||||
if ( runControl == null ) {
|
||||
handleFailedUpdate(update);
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
final GDBControlDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), GDBControlDMContext.class);
|
||||
|
@ -100,7 +99,6 @@ public class ContainerVMNode extends AbstractContainerVMNode
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDeltaFlags(Object e) {
|
||||
|
|
|
@ -11,42 +11,21 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.dd.gdb.internal.ui.viewmodel.launch;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
|
||||
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
|
||||
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
|
||||
import org.eclipse.dd.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.dd.dsf.datamodel.IDMEvent;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.DelayedStackRefreshUpdatePolicy;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.FullStackRefreshEvent;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractLaunchVMProvider;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StandardProcessVMNode;
|
||||
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
|
||||
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
|
||||
import org.eclipse.dd.dsf.service.DsfSession;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IRootVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxy;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
|
||||
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
|
||||
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBExitedEvent;
|
||||
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.GDBStartedEvent;
|
||||
import org.eclipse.dd.mi.service.command.MIInferiorProcess.InferiorExitedDMEvent;
|
||||
import org.eclipse.dd.mi.service.command.MIInferiorProcess.InferiorStartedDMEvent;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.IDebugEventSetListener;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchesListener2;
|
||||
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
|
||||
|
||||
|
@ -55,16 +34,9 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
|
|||
*
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class LaunchVMProvider extends AbstractDMVMProvider
|
||||
public class LaunchVMProvider extends AbstractLaunchVMProvider
|
||||
implements IDebugEventSetListener, ILaunchesListener2
|
||||
{
|
||||
/**
|
||||
* Delay (in milliseconds) before a full stack trace will be requested.
|
||||
*/
|
||||
private static final int FRAME_UPDATE_DELAY= 200;
|
||||
|
||||
private final Map<IExecutionDMContext,ScheduledFuture<?>> fRefreshStackFramesFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
|
||||
|
||||
@ThreadSafe
|
||||
public LaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
|
||||
{
|
||||
|
@ -89,85 +61,6 @@ public class LaunchVMProvider extends AbstractDMVMProvider
|
|||
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IVMUpdatePolicy[] createUpdateModes() {
|
||||
return new IVMUpdatePolicy[] { new DelayedStackRefreshUpdatePolicy() };
|
||||
}
|
||||
|
||||
public void handleDebugEvents(final DebugEvent[] events) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// We're in session's executor thread. Re-dispach to VM Adapter
|
||||
// executor thread and then call root layout node.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
for (final DebugEvent event : events) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleEvent(IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
|
||||
super.handleEvent(proxyStrategy, event, rm);
|
||||
|
||||
if (event instanceof IRunControl.ISuspendedDMEvent) {
|
||||
final IExecutionDMContext exeContext= ((IRunControl.ISuspendedDMEvent) event).getDMContext();
|
||||
ScheduledFuture<?> refreshStackFramesFuture = getRefreshFuture(exeContext);
|
||||
// trigger delayed full stack frame update
|
||||
if (refreshStackFramesFuture != null) {
|
||||
// cancel previously scheduled frame update
|
||||
refreshStackFramesFuture.cancel(false);
|
||||
}
|
||||
|
||||
refreshStackFramesFuture = getSession().getExecutor().schedule(
|
||||
new DsfRunnable() {
|
||||
public void run() {
|
||||
if (getSession().isActive()) {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
// trigger full stack frame update
|
||||
ScheduledFuture<?> future= fRefreshStackFramesFutures.get(exeContext);
|
||||
if (future != null && !isDisposed()) {
|
||||
fRefreshStackFramesFutures.remove(exeContext);
|
||||
handleEvent(new FullStackRefreshEvent(exeContext));
|
||||
}
|
||||
}});
|
||||
}
|
||||
}
|
||||
},
|
||||
FRAME_UPDATE_DELAY, TimeUnit.MILLISECONDS);
|
||||
fRefreshStackFramesFutures.put(exeContext, refreshStackFramesFuture);
|
||||
} else if (event instanceof IRunControl.IResumedDMEvent) {
|
||||
IExecutionDMContext exeContext= ((IRunControl.IResumedDMEvent) event).getDMContext();
|
||||
ScheduledFuture<?> refreshStackFramesFuture= fRefreshStackFramesFutures.get(exeContext);
|
||||
if (refreshStackFramesFuture != null) {
|
||||
// cancel previously scheduled frame update
|
||||
refreshStackFramesFuture.cancel(false);
|
||||
fRefreshStackFramesFutures.remove(exeContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the future for the given execution context or for any child of the
|
||||
* given execution context.
|
||||
*/
|
||||
private ScheduledFuture<?> getRefreshFuture(IExecutionDMContext execCtx) {
|
||||
for (IExecutionDMContext refreshCtx : fRefreshStackFramesFutures.keySet()) {
|
||||
if (refreshCtx.equals(execCtx) || DMContexts.isAncestorOf(refreshCtx, execCtx)) {
|
||||
return fRefreshStackFramesFutures.remove(refreshCtx);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
|
@ -176,42 +69,6 @@ public class LaunchVMProvider extends AbstractDMVMProvider
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
public void launchesAdded(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.ADDED));
|
||||
}
|
||||
|
||||
public void launchesRemoved(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.REMOVED));
|
||||
}
|
||||
|
||||
public void launchesChanged(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.CHANGED));
|
||||
}
|
||||
|
||||
public void launchesTerminated(ILaunch[] launches) {
|
||||
handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.TERMINATED));
|
||||
}
|
||||
|
||||
private void handleLaunchesEvent(final LaunchesEvent event) {
|
||||
if (isDisposed()) return;
|
||||
|
||||
// We're in session's executor thread. Re-dispach to VM Adapter
|
||||
// executor thread and then call root layout node.
|
||||
try {
|
||||
getExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
if (isDisposed()) return;
|
||||
|
||||
IRootVMNode rootLayoutNode = getRootVMNode();
|
||||
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
|
||||
handleEvent(event);
|
||||
}
|
||||
}});
|
||||
} catch (RejectedExecutionException e) {
|
||||
// Ignore. This exception could be thrown if the provider is being
|
||||
// shut down.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
|
||||
|
@ -223,22 +80,7 @@ public class LaunchVMProvider extends AbstractDMVMProvider
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// To optimize view performance when stepping rapidly, skip events that came
|
||||
// before the last suspended events. However, the debug view can get suspended
|
||||
// events for different threads, so make sure to skip only the events if they
|
||||
// were in the same hierarchy as the last suspended event.
|
||||
if (newEvent instanceof ISuspendedDMEvent && eventToSkip instanceof IDMEvent<?>) {
|
||||
IDMContext newEventDmc = ((IDMEvent<?>)newEvent).getDMContext();
|
||||
IDMContext eventToSkipDmc = ((IDMEvent<?>)eventToSkip).getDMContext();
|
||||
|
||||
if (newEventDmc.equals(eventToSkipDmc) || DMContexts.isAncestorOf(eventToSkipDmc, newEventDmc)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return super.canSkipHandlingEvent(newEvent, eventToSkip);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue