1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 12:03:16 +02:00

[160041] - [debug view] Retrieving limited # of stack frames.

This commit is contained in:
Pawel Piech 2008-06-24 17:34:46 +00:00
parent f9b2f38049
commit fd5c004c84
25 changed files with 1225 additions and 65 deletions

View file

@ -41,4 +41,8 @@ action.setDefaultNumberFormatHex.label = Hex
action.setDefaultNumberFormatDecimal.label = Decimal
action.setDefaultNumberFormatOctal.label = Octal
action.setDefaultNumberFormatBinary.label = Binary
action.setDefaultNumberFormatNatural.label = Natural
action.setDefaultNumberFormatNatural.label = Natural
preferencePage.name = DSF Debugging
action.expandStack.label = E&xpand Stack

View file

@ -448,6 +448,12 @@
category="org.eclipse.debug.ui.DebugPreferencePage"
name="%disassemblyPreferencePage.name"
id="org.eclipse.dd.dsf.debug.ui.disassembly.preferencePage"/>
<page
category="org.eclipse.debug.ui.DebugPreferencePage"
class="org.eclipse.dd.dsf.debug.internal.ui.preferences.DsfDebugPreferencePage"
id="org.eclipse.dd.dsf.debug.ui.preferences"
name="%preferencePage.name">
</page>
</extension>
<extension
point="org.eclipse.ui.popupMenus">
@ -523,4 +529,18 @@
</viewContribution>
</extension>
<!-- Debug view context menu contributions -->
<extension point="org.eclipse.ui.popupMenus">
<viewerContribution
id="org.eclipse.dd.dsf.debug.ui.DebugView.context"
targetID="org.eclipse.debug.ui.DebugView">
<action
class="org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.actions.ExpandStackAction"
id="org.eclipse.dd.dsf.debug.ui.retrieveMoreFrames"
label="%action.expandStack.label"
menubarPath="renderGroup">
</action>
</viewerContribution>
</extension>
</plugin>

View file

@ -24,13 +24,17 @@ 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.internal.provisional.ui.viewmodel.launch.StackFramesVMNode.IncompleteStackVMContext;
import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin;
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.debug.ui.IDsfDebugUIConstants;
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.AutomaticUpdatePolicy;
import org.eclipse.dd.dsf.ui.viewmodel.update.IVMUpdatePolicy;
@ -41,6 +45,12 @@ 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;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
/**
@ -57,10 +67,36 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider
private final Map<IExecutionDMContext,ScheduledFuture<?>> fRefreshStackFramesFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
private IPropertyChangeListener fPreferencesListener;
@ThreadSafe
public AbstractLaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
{
super(adapter, presentationContext, session);
final IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore();
if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) {
getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT));
}
fPreferencesListener = new IPropertyChangeListener() {
public void propertyChange(final PropertyChangeEvent event) {
String property = event.getProperty();
if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
|| IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property)) {
if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) {
getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT));
} else {
getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, null);
}
getExecutor().execute(new DsfRunnable() {
public void run() {
handleEvent(event);
}
});
}
}};
store.addPropertyChangeListener(fPreferencesListener);
}
@Override
@ -91,6 +127,33 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider
}
}
@Override
public void handleEvent(Object event) {
if (event instanceof DoubleClickEvent && !isDisposed()) {
final ISelection selection= ((DoubleClickEvent) event).getSelection();
if (selection instanceof IStructuredSelection) {
Object element= ((IStructuredSelection) selection).getFirstElement();
if (element instanceof IncompleteStackVMContext) {
IncompleteStackVMContext incStackVmc = ((IncompleteStackVMContext) element);
IVMNode node = ((IncompleteStackVMContext) element).getVMNode();
if (incStackVmc.getVMNode() instanceof StackFramesVMNode) {
IExecutionDMContext exeCtx= incStackVmc.getExecutionDMContext();
((StackFramesVMNode) node).incrementStackFrameLimit(exeCtx);
// replace double click event with expand stack event
final ExpandStackEvent expandStackEvent = new ExpandStackEvent(exeCtx);
getExecutor().execute(new DsfRunnable() {
public void run() {
handleEvent(expandStackEvent);
}
});
}
}
}
return;
}
super.handleEvent(event);
}
@Override
protected void handleEvent(IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
super.handleEvent(proxyStrategy, event, rm);
@ -131,6 +194,7 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider
fRefreshStackFramesFutures.remove(exeContext);
}
}
}
/**
@ -150,6 +214,10 @@ public class AbstractLaunchVMProvider extends AbstractDMVMProvider
public void dispose() {
DebugPlugin.getDefault().removeDebugEventListener(this);
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
final IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore();
store.removePropertyChangeListener(fPreferencesListener);
super.dispose();
}

View file

@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.provisional.ui.viewmodel.launch;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
/**
* Event to increase the stack frame limit for an execution context.
*/
public class ExpandStackEvent extends AbstractDMEvent<IExecutionDMContext> {
public ExpandStackEvent(IExecutionDMContext execCtx) {
super(execCtx);
}
}

View file

@ -10,7 +10,10 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
@ -21,14 +24,19 @@ import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack;
import org.eclipse.dd.dsf.debug.service.IStack2;
import org.eclipse.dd.dsf.debug.service.StepQueueManager;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
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.ISuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData;
import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants;
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.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.ModelProxyInstalledEvent;
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
@ -47,6 +55,7 @@ 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.jface.util.PropertyChangeEvent;
import org.eclipse.ui.IMemento;
@SuppressWarnings("restriction")
@ -54,7 +63,42 @@ public class StackFramesVMNode extends AbstractDMVMNode
implements IElementLabelProvider, IElementMementoProvider
{
public StackFramesVMNode(AbstractDMVMProvider provider, DsfSession session) {
/**
* View model context representing the end of an incomplete stack.
*/
public class IncompleteStackVMContext extends AbstractVMContext {
private final int fLevel;
private final IExecutionDMContext fDmc;
public IncompleteStackVMContext(IExecutionDMContext dmc, int level) {
super(StackFramesVMNode.this);
fDmc = dmc;
fLevel = level;
}
public int getLevel() {
return fLevel;
}
public IExecutionDMContext getExecutionDMContext() {
return fDmc;
}
@Override
public boolean equals(Object obj) {
return obj instanceof IncompleteStackVMContext &&
((IncompleteStackVMContext)obj).fDmc.equals(fDmc);
}
@Override
public int hashCode() {
return fDmc.hashCode();
}
}
/**
* Temporary stack frame limit to allow incremental stack updates.
*/
private Map<IExecutionDMContext, Integer> fTemporaryLimits = new HashMap<IExecutionDMContext, Integer>();
public StackFramesVMNode(AbstractDMVMProvider provider, DsfSession session) {
super(provider, session, IStack.IFrameDMContext.class);
}
@ -89,8 +133,9 @@ public class StackFramesVMNode extends AbstractDMVMNode
return;
}
final int stackFrameLimit= getStackFrameLimit(execDmc);
stackService.getStackDepth(
execDmc, 0,
execDmc, stackFrameLimit == Integer.MAX_VALUE ? 0 : stackFrameLimit + 1,
new ViewerDataRequestMonitor<Integer>(getSession().getExecutor(), update) {
@Override
public void handleCompleted() {
@ -98,7 +143,11 @@ public class StackFramesVMNode extends AbstractDMVMNode
handleFailedUpdate(update);
return;
}
update.setChildCount(getData());
int stackDepth= getData();
if (stackFrameLimit < stackDepth) {
stackDepth = stackFrameLimit + 1;
}
update.setChildCount(stackDepth);
update.done();
}
});
@ -117,7 +166,10 @@ public class StackFramesVMNode extends AbstractDMVMNode
return;
}
if (update.getOffset() == 0 && update.getLength() == 1) {
final int stackFrameLimit= getStackFrameLimit(execDmc);
final int startIndex= update.getOffset();
if (startIndex == 0 && update.getLength() == 1) {
// Requesting top stack frame only
stackService.getTopFrame(
execDmc,
@ -134,24 +186,59 @@ public class StackFramesVMNode extends AbstractDMVMNode
});
} else {
// full stack dump
stackService.getFrames(
execDmc,
new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
handleFailedUpdate(update);
return;
if (startIndex >= 0 && update.getLength() > 0 && stackService instanceof IStack2) {
// partial stack dump
IStack2 stackService2= (IStack2) stackService;
int endIndex= startIndex + update.getLength() - 1;
if (startIndex < stackFrameLimit && endIndex >= stackFrameLimit) {
endIndex = stackFrameLimit - 1;
}
stackService2.getFrames(
execDmc,
startIndex,
endIndex,
new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
handleFailedUpdate(update);
return;
}
IFrameDMContext[] frames = getData();
fillUpdateWithVMCs(update, frames, startIndex);
if (startIndex + update.getLength() > stackFrameLimit) {
update.setChild(new IncompleteStackVMContext(execDmc, stackFrameLimit), stackFrameLimit);
}
update.done();
}
fillUpdateWithVMCs(update, getData());
update.done();
}
});
});
} else {
// full stack dump
stackService.getFrames(
execDmc,
new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
handleFailedUpdate(update);
return;
}
IFrameDMContext[] frames = getData();
if (frames.length > stackFrameLimit) {
IFrameDMContext[] tmpFrames = new IFrameDMContext[stackFrameLimit];
System.arraycopy(frames, 0, tmpFrames, 0, stackFrameLimit);
frames = tmpFrames;
update.setChild(new IncompleteStackVMContext(execDmc, stackFrameLimit), stackFrameLimit);
}
fillUpdateWithVMCs(update, frames);
update.done();
}
});
}
}
}
/*
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[])
*/
@ -171,13 +258,25 @@ public class StackFramesVMNode extends AbstractDMVMNode
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
for (final ILabelUpdate update : updates) {
IStack stackService = getServicesTracker().getService(IStack.class);
final IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
if (stackService == null || dmc == null) {
if (stackService == null) {
handleFailedUpdate(update);
continue;
}
if (update.getElement() instanceof IncompleteStackVMContext) {
update.setLabel("<...more frames...>", 0); //$NON-NLS-1$
update.setImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_STACKFRAME), 0);
update.done();
return;
}
final IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
if (dmc == null) {
handleFailedUpdate(update);
continue;
}
getDMVMProvider().getModelData(
this, update,
getServicesTracker().getService(IStack.class, null),
@ -314,7 +413,22 @@ public class StackFramesVMNode extends AbstractDMVMNode
return IModelDelta.CONTENT;
} else if (e instanceof ModelProxyInstalledEvent) {
return IModelDelta.SELECT | IModelDelta.EXPAND;
}
} else if (e instanceof ExpandStackEvent) {
return IModelDelta.CONTENT;
} else if (e instanceof IExitedDMEvent) {
// Do not generate a delta for this event, but do clear the
// internal stack frame limit to avoid a memory leak.
clearStackFrameLimit( ((IExitedDMEvent)e).getDMContext() );
return IModelDelta.NO_CHANGE;
} else if (e instanceof PropertyChangeEvent) {
String property = ((PropertyChangeEvent)e).getProperty();
if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
|| IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property))
{
return IModelDelta.CONTENT;
}
} else {
}
return IModelDelta.NO_CHANGE;
}
@ -325,6 +439,9 @@ public class StackFramesVMNode extends AbstractDMVMNode
*/
public void buildDelta(final Object e, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
if (e instanceof IContainerSuspendedDMEvent) {
// Clear the limit on the stack frames for all stack frames under a given container.
clearStackFrameLimit( ((IContainerSuspendedDMEvent)e).getDMContext() );
IContainerSuspendedDMEvent csEvent = (IContainerSuspendedDMEvent)e;
IExecutionDMContext triggeringCtx = csEvent.getTriggeringContexts().length != 0
@ -341,12 +458,23 @@ public class StackFramesVMNode extends AbstractDMVMNode
IExecutionDMContext execDmc = ((FullStackRefreshEvent)e).getDMContext();
buildDeltaForFullStackRefreshEvent(execDmc, execDmc, parent, nodeOffset, rm);
} else if (e instanceof ISuspendedDMEvent) {
clearStackFrameLimit( ((ISuspendedDMEvent)e).getDMContext() );
IExecutionDMContext execDmc = ((ISuspendedDMEvent)e).getDMContext();
buildDeltaForSuspendedEvent(execDmc, execDmc, parent, nodeOffset, rm);
} else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) {
buildDeltaForSteppingTimedOutEvent((StepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm);
} else if (e instanceof ModelProxyInstalledEvent) {
buildDeltaForModelProxyInstalledEvent(parent, nodeOffset, rm);
} else if (e instanceof ExpandStackEvent) {
IExecutionDMContext execDmc = ((ExpandStackEvent)e).getDMContext();
buildDeltaForExpandStackEvent(execDmc, parent, rm);
} else if (e instanceof PropertyChangeEvent) {
String property = ((PropertyChangeEvent)e).getProperty();
if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
|| IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property))
{
buildDeltaForStackFrameLimitPreferenceChangedEvent(parent, rm);
}
} else {
rm.done();
}
@ -443,6 +571,17 @@ public class StackFramesVMNode extends AbstractDMVMNode
);
}
private void buildDeltaForExpandStackEvent(IExecutionDMContext execDmc, final VMDelta parentDelta, final RequestMonitor rm) {
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
rm.done();
}
private void buildDeltaForStackFrameLimitPreferenceChangedEvent(final VMDelta parentDelta, final RequestMonitor rm) {
parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
rm.done();
}
private String produceFrameElementName( String viewName , IFrameDMContext frame ) {
/*
* We are addressing Bugzilla 211490 which wants the Register View to keep the same expanded
@ -516,4 +655,47 @@ public class StackFramesVMNode extends AbstractDMVMNode
request.done();
}
}
/**
* Get the current active stack frame limit. If no limit is applicable {@link Integer.MAX_VALUE} is returned.
*
* @return the current stack frame limit
*/
public int getStackFrameLimit(IExecutionDMContext execCtx) {
if (fTemporaryLimits.containsKey(execCtx)) {
return fTemporaryLimits.get(execCtx);
}
Object stackDepthLimit= getVMProvider().getPresentationContext().getProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT);
if (stackDepthLimit instanceof Integer) {
return (Integer)stackDepthLimit;
}
return Integer.MAX_VALUE;
}
private void clearStackFrameLimit(IExecutionDMContext execCtx) {
if (execCtx instanceof IContainerDMContext) {
for (Iterator<IExecutionDMContext> itr = fTemporaryLimits.keySet().iterator(); itr.hasNext();) {
IExecutionDMContext limitCtx = itr.next();
if (limitCtx.equals(execCtx) || DMContexts.isAncestorOf(limitCtx, execCtx)) {
itr.remove();
}
}
} else {
fTemporaryLimits.remove(execCtx);
}
}
/**
* Increment the stack frame limit by the default increment.
* This implementation doubles the current limit.
*/
public void incrementStackFrameLimit(IExecutionDMContext execCtx) {
final int stackFrameLimit= getStackFrameLimit(execCtx);
if (stackFrameLimit < Integer.MAX_VALUE / 2) {
fTemporaryLimits.put(execCtx, stackFrameLimit * 2);
} else {
fTemporaryLimits.put(execCtx, Integer.MAX_VALUE);
}
}
}

View file

@ -0,0 +1,79 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.provisional.ui.viewmodel.launch.actions;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.actions.AbstractVMProviderActionDelegate;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.AbstractLaunchVMProvider;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.ExpandStackEvent;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode;
import org.eclipse.dd.dsf.debug.internal.provisional.ui.viewmodel.launch.StackFramesVMNode.IncompleteStackVMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.ui.viewmodel.IVMNode;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ui.IViewPart;
/**
* Increment the (temporary) stack limit for the selected stack.
*/
public class ExpandStackAction extends AbstractVMProviderActionDelegate {
/*
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
*/
public void run(IAction action) {
Object element = getViewerInput();
if (element instanceof IncompleteStackVMContext) {
IncompleteStackVMContext incStackVmc = ((IncompleteStackVMContext) element);
IVMNode node = incStackVmc.getVMNode();
if (incStackVmc.getVMNode() instanceof StackFramesVMNode) {
final IExecutionDMContext exeCtx= incStackVmc.getExecutionDMContext();
((StackFramesVMNode) node).incrementStackFrameLimit(exeCtx);
final ExpandStackEvent event = new ExpandStackEvent(exeCtx);
final AbstractLaunchVMProvider vmProvider = (AbstractLaunchVMProvider) getVMProvider();
vmProvider.getExecutor().execute(new DsfRunnable() {
public void run() {
vmProvider.handleEvent(event);
}
});
}
}
}
@Override
public void init(IViewPart view) {
super.init(view);
updateEnablement();
}
@Override
public void debugContextChanged(DebugContextEvent event) {
super.debugContextChanged(event);
updateEnablement();
}
@Override
public void selectionChanged(IAction action, ISelection selection) {
super.selectionChanged(action, selection);
updateEnablement();
}
private void updateEnablement() {
boolean enabled = false;
if (getVMProvider() instanceof AbstractLaunchVMProvider) {
Object element = getViewerInput();
enabled = element instanceof IncompleteStackVMContext;
}
getAction().setEnabled(enabled);
}
}

View file

@ -0,0 +1,78 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.ui.preferences;
import org.eclipse.dd.dsf.debug.internal.ui.DsfDebugUIPlugin;
import org.eclipse.dd.dsf.debug.ui.IDsfDebugUIConstants;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
/**
* DSF debug preference page.
*/
public class DsfDebugPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
/**
* Mandatory default constructor (executable extension).
*/
public DsfDebugPreferencePage() {
super(GRID);
IPreferenceStore store= DsfDebugUIPlugin.getDefault().getPreferenceStore();
setPreferenceStore(store);
setDescription(MessagesForPreferences.DsfDebugPreferencePage_description);
}
/*
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IDsfDebugUIConstants.PREFERENCE_PAGE);
}
@Override
protected void createFieldEditors() {
Group performanceGroup= new Group(getFieldEditorParent(), SWT.NONE);
performanceGroup.setText(MessagesForPreferences.DsfDebugPreferencePage_performanceGroup_label);
performanceGroup.setLayout(new GridLayout());
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
gd.verticalIndent= 5;
performanceGroup.setLayoutData(gd);
Composite innerParent= new Composite(performanceGroup, SWT.NONE);
innerParent.setLayout(new GridLayout());
innerParent.setLayoutData(gd);
IntegerFieldEditor limitEditor= new IntegerWithBooleanFieldEditor(
IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE,
IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT,
MessagesForPreferences.DsfDebugPreferencePage_limitStackFrames_label,
innerParent);
limitEditor.setValidRange(1, Integer.MAX_VALUE);
limitEditor.fillIntoGrid(innerParent, 3);
addField(limitEditor);
}
}

View file

@ -0,0 +1,129 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.ui.preferences;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
/**
* An integer field editor with an enablement check box.
*/
public class IntegerWithBooleanFieldEditor extends IntegerFieldEditor {
private final String fEnableKey;
private Button fCheckbox;
private boolean fWasSelected;
public IntegerWithBooleanFieldEditor(String enableKey, String nameKey, String labelText, Composite parent) {
super(nameKey, labelText, parent);
fEnableKey= enableKey;
}
public IntegerWithBooleanFieldEditor(String enableKey, String nameKey, String labelText, Composite parent, int textLimit) {
super(nameKey, labelText, parent, textLimit);
fEnableKey= enableKey;
}
@Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
getCheckboxControl(parent);
super.doFillIntoGrid(parent, numColumns);
}
@Override
public int getNumberOfControls() {
return super.getNumberOfControls() + 1;
}
@Override
protected void adjustForNumColumns(int numColumns) {
// the checkbox uses one column
super.adjustForNumColumns(numColumns - 1);
}
private Button getCheckboxControl(Composite parent) {
if (fCheckbox == null) {
fCheckbox= new Button(parent, SWT.CHECK);
fCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean isSelected = fCheckbox.getSelection();
valueChanged(fWasSelected, isSelected);
fWasSelected = isSelected;
}
});
} else {
checkParent(fCheckbox, parent);
}
return fCheckbox;
}
protected void valueChanged(boolean oldValue, boolean newValue) {
setPresentsDefaultValue(false);
if (oldValue != newValue) {
fireStateChanged(VALUE, oldValue, newValue);
getTextControl().setEnabled(newValue);
getLabelControl().setEnabled(newValue);
}
}
@Override
protected boolean checkState() {
if (fCheckbox != null && !fCheckbox.getSelection()) {
return true;
}
return super.checkState();
}
@Override
protected void doLoad() {
super.doLoad();
if (fCheckbox != null) {
boolean value = getPreferenceStore().getBoolean(fEnableKey);
fCheckbox.setSelection(value);
fWasSelected = value;
getTextControl().setEnabled(value);
getLabelControl().setEnabled(value);
}
}
@Override
protected void doLoadDefault() {
super.doLoadDefault();
if (fCheckbox != null) {
boolean value = getPreferenceStore().getDefaultBoolean(fEnableKey);
fCheckbox.setSelection(value);
fWasSelected = value;
getTextControl().setEnabled(value);
getLabelControl().setEnabled(value);
}
}
@Override
protected void doStore() {
super.doStore();
getPreferenceStore().setValue(fEnableKey, fCheckbox.getSelection());
}
/**
* Returns this field editor's current boolean value.
*
* @return the value
*/
public boolean getBooleanValue() {
return fCheckbox.getSelection();
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.ui.preferences;
import org.eclipse.osgi.util.NLS;
/**
* Preference strings.
*/
class MessagesForPreferences extends NLS {
private static final String BUNDLE_NAME= "org.eclipse.dd.dsf.debug.internal.ui.preferences.messages"; //$NON-NLS-1$
public static String DsfDebugPreferencePage_description;
public static String DsfDebugPreferencePage_limitStackFrames_label;
public static String DsfDebugPreferencePage_performanceGroup_label;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, MessagesForPreferences.class);
}
private MessagesForPreferences() {
}
}

View file

@ -0,0 +1,134 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.internal.ui.preferences;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
/**
* A string field editor with an enablement check box.
*/
public class StringWithBooleanFieldEditor extends StringFieldEditor {
private final String fEnableKey;
private Button fCheckbox;
private boolean fWasSelected;
public StringWithBooleanFieldEditor(String enableKey, String nameKey, String labelText, Composite parent) {
super(nameKey, labelText, parent);
fEnableKey= enableKey;
}
public StringWithBooleanFieldEditor(String enableKey, String nameKey, String labelText, int width, Composite parent) {
super(nameKey, labelText, width, parent);
fEnableKey= enableKey;
}
public StringWithBooleanFieldEditor(String enableKey, String nameKey, String labelText, int width, int strategy, Composite parent) {
super(nameKey, labelText, width, strategy, parent);
fEnableKey= enableKey;
}
@Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
getCheckboxControl(parent);
super.doFillIntoGrid(parent, numColumns);
}
@Override
public int getNumberOfControls() {
return super.getNumberOfControls() + 1;
}
@Override
protected void adjustForNumColumns(int numColumns) {
// the checkbox uses one column
super.adjustForNumColumns(numColumns - 1);
}
private Button getCheckboxControl(Composite parent) {
if (fCheckbox == null) {
fCheckbox= new Button(parent, SWT.CHECK);
fCheckbox.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
boolean isSelected = fCheckbox.getSelection();
valueChanged(fWasSelected, isSelected);
fWasSelected = isSelected;
}
});
} else {
checkParent(fCheckbox, parent);
}
return fCheckbox;
}
protected void valueChanged(boolean oldValue, boolean newValue) {
setPresentsDefaultValue(false);
if (oldValue != newValue) {
fireStateChanged(VALUE, oldValue, newValue);
getTextControl().setEnabled(newValue);
getLabelControl().setEnabled(newValue);
}
}
@Override
protected boolean checkState() {
if (fCheckbox != null && !fCheckbox.getSelection()) {
return true;
}
return super.checkState();
}
@Override
protected void doLoad() {
super.doLoad();
if (fCheckbox != null) {
boolean value = getPreferenceStore().getBoolean(fEnableKey);
fCheckbox.setSelection(value);
fWasSelected = value;
getTextControl().setEnabled(value);
getLabelControl().setEnabled(value);
}
}
@Override
protected void doLoadDefault() {
super.doLoadDefault();
if (fCheckbox != null) {
boolean value = getPreferenceStore().getDefaultBoolean(fEnableKey);
fCheckbox.setSelection(value);
fWasSelected = value;
getTextControl().setEnabled(value);
getLabelControl().setEnabled(value);
}
}
@Override
protected void doStore() {
super.doStore();
getPreferenceStore().setValue(fEnableKey, fCheckbox.getSelection());
}
/**
* Returns this field editor's current boolean value.
*
* @return the value
*/
public boolean getBooleanValue() {
return fCheckbox.getSelection();
}
}

View file

@ -0,0 +1,14 @@
###############################################################################
# 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
###############################################################################
DsfDebugPreferencePage_description=General settings for debugging with DSF:
DsfDebugPreferencePage_limitStackFrames_label=Limit number of stack frames to
DsfDebugPreferencePage_performanceGroup_label=Performance

View file

@ -55,7 +55,20 @@ public interface IDsfDebugUIConstants {
* the workbench font preference page.
*/
public static final String DETAIL_PANE_FONT= PLUGIN_ID + "DetailPaneFont"; //$NON-NLS-1$
/**
* Integer preference to control the maximum amount of stack frames to
* retrieve from the backend. Default value is 100.
* @see {@link #PREF_STACK_FRAME_LIMIT_ENABLE}
*/
public static final String PREF_STACK_FRAME_LIMIT = "stackFrameLimit"; //$NON-NLS-1$
/**
* Boolean preference whether to apply the stack frame limit preference.
* @see {@link #PREF_STACK_FRAME_LIMIT}
*/
public static final String PREF_STACK_FRAME_LIMIT_ENABLE = "stackFrameLimitEnable"; //$NON-NLS-1$
/**
* Help prefixes.
*/
@ -71,4 +84,6 @@ public interface IDsfDebugUIConstants {
public static final String DETAIL_PANE_FIND_REPLACE_ACTION = PREFIX + "detail_pane_find_replace_action_context"; //$NON-NLS-1$
public static final String DETAIL_PANE_WORD_WRAP_ACTION = PREFIX + "detail_pane_word_wrap_action_context"; //$NON-NLS-1$
public static final String DETAIL_PANE_MAX_LENGTH_ACTION = PREFIX + "detail_pane_max_length_action_context"; //$NON-NLS-1$
public static final String PREFERENCE_PAGE= PREFIX + "preference_page_context"; //$NON-NLS-1$
}

View file

@ -52,5 +52,11 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer {
* Expressions View
*/
prefs.setDefault(IDsfDebugUIConstants.EXPRESSIONS_DETAIL_PANE_ORIENTATION, IDsfDebugUIConstants.VARIABLES_DETAIL_PANE_UNDERNEATH);
}
/*
* Debug View
*/
prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, 100);
prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE, true);
}
}

View file

@ -0,0 +1,49 @@
/*******************************************************************************
* Copyright (c) 2008 Wind River Systems, Inc. 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.dsf.debug.service;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.datamodel.IDMContext;
/**
* Stack service extension.
* <p>
* Adds the capability to retrieve a limited number of stack frames.
* </p>
*
* @since DSF 1.1
*/
public interface IStack2 extends IStack {
/**
* Convenience constant for use with {@link #getFrames(IDMContext, int, int, DataRequestMonitor)}
* to retrieve all stack frames.
*/
public final static int ALL_FRAMES = -1;
/**
* Retrieves list of stack frames for the given execution context. Request
* will fail if the stack frame data is not available.
* <p>The range of stack frames can be limited by the <code>startIndex</code> and <code>endIndex</code> arguments.
* It is no error to specify an <code>endIndex</code> exceeding the number of available stack frames.
* A negative value for <code>endIndex</code> means to retrieve all stack frames. <code>startIndex</code> must be a non-negative value.
* </p>
*
* @param execContext the execution context to retrieve stack frames for
* @param startIndex the index of the first frame to retrieve
* @param endIndex the index of the last frame to retrieve (inclusive) or {@link #ALL_FRAMES}
* @param rm the request monitor
*
* @see #getFrames(IDMContext, DataRequestMonitor)
*/
public abstract void getFrames(IDMContext execContext, int startIndex, int endIndex, DataRequestMonitor<IFrameDMContext[]> rm);
}

View file

@ -32,6 +32,9 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.Viewer;
@ -55,6 +58,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
private Viewer fViewer;
private boolean fDisposed = false;
private ListenerList fListeners = new ListenerList();
private IDoubleClickListener fDoubleClickListener;
/**
* Debug flag indicating whether the deltas should be traced in stdout.
@ -154,6 +158,10 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
*/
public void dispose() {
fDisposed = true;
if (fViewer instanceof StructuredViewer && fDoubleClickListener != null) {
((StructuredViewer) fViewer).removeDoubleClickListener(fDoubleClickListener);
fDoubleClickListener= null;
}
}
/* (non-Javadoc)
@ -187,9 +195,29 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
fProvider.handleEvent(new ModelProxyInstalledEvent(DefaultVMModelProxyStrategy.this, viewer, fRootElement));
}
});
if (fViewer instanceof StructuredViewer && fDoubleClickListener == null) {
((StructuredViewer) fViewer).addDoubleClickListener(fDoubleClickListener= new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent e) {
handleDoubleClick(e);
}
});
}
}
/**
* Handle viewer double click.
*
* @param e the event
*/
protected void handleDoubleClick(final DoubleClickEvent e) {
getVMProvider().getExecutor().execute( new DsfRunnable() {
public void run() {
getVMProvider().handleEvent(e);
}
});
}
/**
* Returns the viewer this proxy is installed in.
*
* @return viewer or <code>null</code> if not installed

View file

@ -323,13 +323,34 @@ abstract public class AbstractDMVMNode extends AbstractVMNode implements IVMNode
return vmContexts;
}
/**
* Fill update request with view model contexts based on given data model contexts.
* Assumes that data model context elements start at index 0.
*
* @param update the viewer update request
* @param dmcs the data model contexts
*/
protected void fillUpdateWithVMCs(IChildrenUpdate update, IDMContext[] dmcs) {
int startIdx = update.getOffset() != -1 ? update.getOffset() : 0;
int endIdx = update.getLength() != -1 ? startIdx + update.getLength() : dmcs.length;
// Ted: added bounds limitation of dmcs.length
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109
for (int i = startIdx; i < endIdx && i < dmcs.length; i++) {
update.setChild(createVMContext(dmcs[i]), i);
fillUpdateWithVMCs(update, dmcs, 0);
}
/**
* Fill update request with view model contexts based on given data model contexts.
*
* @param update the viewer update request
* @param dmcs the data model contexts
* @param firstIndex the index of the first data model context
*/
protected void fillUpdateWithVMCs(IChildrenUpdate update, IDMContext[] dmcs, int firstIndex) {
int updateIdx = update.getOffset() != -1 ? update.getOffset() : 0;
final int endIdx = updateIdx + (update.getLength() != -1 ? update.getLength() : dmcs.length);
int dmcIdx = updateIdx - firstIndex;
if (dmcIdx < 0) {
updateIdx -= dmcIdx;
dmcIdx = 0;
}
while (updateIdx < endIdx && dmcIdx < dmcs.length) {
update.setChild(createVMContext(dmcs[dmcIdx++]), updateIdx++);
}
}

View file

@ -577,6 +577,7 @@ public class PDAVirtualMachine {
else if ("eval".equals(command)) debugEval(args);
else if ("eventstop".equals(command)) debugEventStop(args);
else if ("exit".equals(command)) debugExit();
else if ("frame".equals(command)) debugFrame(args);
else if ("popdata".equals(command)) debugPop(args);
else if ("pushdata".equals(command)) debugPush(args);
else if ("resume".equals(command)) debugResume(args);
@ -584,6 +585,7 @@ public class PDAVirtualMachine {
else if ("setdata".equals(command)) debugSetData(args);
else if ("setvar".equals(command)) debugSetVariable(args);
else if ("stack".equals(command)) debugStack(args);
else if ("stackdepth".equals(command)) debugStackDepth(args);
else if ("state".equals(command)) debugState(args);
else if ("step".equals(command)) debugStep(args);
else if ("stepreturn".equals(command)) debugStepReturn(args);
@ -713,6 +715,23 @@ public class PDAVirtualMachine {
System.exit(0);
}
void debugFrame(Args args) {
PDAThread thread = args.getThreadArg();
if (thread == null) {
sendCommandResponse("error: invalid thread\n");
return;
}
int sfnumber = args.getNextIntArg();
Frame frame = null;
if (sfnumber >= thread.fFrames.size()) {
frame = thread.fCurrentFrame;
} else {
frame = thread.fFrames.get(sfnumber);
}
sendCommandResponse(printFrame(frame) + "\n");
}
void debugPop(Args args) {
PDAThread thread = args.getThreadArg();
if (thread == null) {
@ -819,6 +838,16 @@ public class PDAVirtualMachine {
sendCommandResponse(result.toString());
}
void debugStackDepth(Args args) {
PDAThread thread = args.getThreadArg();
if (thread == null) {
sendCommandResponse("error: invalid thread\n");
return;
}
sendCommandResponse( Integer.toString(thread.fFrames.size() + 1) + "\n" );
}
/**
* The stack frame output is: frame # frame # frame ... where each frame is:
* filename | line number | function name | var | var | var | var ...

View file

@ -24,6 +24,7 @@ import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack;
import org.eclipse.dd.dsf.debug.service.IStack2;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
@ -34,8 +35,12 @@ 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.PDAFrame;
import org.eclipse.dd.examples.pda.service.commands.PDAFrameCommand;
import org.eclipse.dd.examples.pda.service.commands.PDAFrameCommandResult;
import org.eclipse.dd.examples.pda.service.commands.PDAStackCommand;
import org.eclipse.dd.examples.pda.service.commands.PDAStackCommandResult;
import org.eclipse.dd.examples.pda.service.commands.PDAStackDepthCommand;
import org.eclipse.dd.examples.pda.service.commands.PDAStackDepthCommandResult;
import org.osgi.framework.BundleContext;
/**
@ -46,7 +51,7 @@ import org.osgi.framework.BundleContext;
* this service is initialized.
* </p>
*/
public class PDAStack extends AbstractDsfService implements IStack {
public class PDAStack extends AbstractDsfService implements IStack2 {
/**
* PDA stack frame contains only the stack frame level. It is only
@ -221,7 +226,7 @@ public class PDAStack extends AbstractDsfService implements IStack {
}
public void getFrameData(final IFrameDMContext frameCtx, final DataRequestMonitor<IFrameDMData> rm) {
PDAThreadDMContext threadCtx =
final PDAThreadDMContext threadCtx =
DMContexts.getAncestorOfType(frameCtx, PDAThreadDMContext.class);
if (threadCtx == null) {
@ -230,23 +235,30 @@ public class PDAStack extends AbstractDsfService implements IStack {
return;
}
// Execute the PDA stack command, or retrieve the result from cache if already available.
fCommandCache.execute(
new PDAStackCommand(threadCtx),
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
getStackDepth(
threadCtx, -1,
new DataRequestMonitor<Integer>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// PDAFrame array is ordered highest to lowest. We need to
// calculate the index based on frame level.
int frameId = getData().fFrames.length - frameCtx.getLevel() - 1;
if (frameId < 0) {
int frameNum = getData() - frameCtx.getLevel() - 1;
if (frameNum < 0) {
PDAPlugin.failRequest(rm, IDsfStatusConstants.INVALID_HANDLE, "Invalid frame level " + frameCtx);
return;
}
// Create the frame data object based on the corresponding PDAFrame
rm.setData(new FrameDMData(getData().fFrames[frameId]));
rm.done();
// Execute the PDA stack command, or retrieve the result from cache if already available.
fCommandCache.execute(
new PDAFrameCommand(threadCtx, frameNum),
new DataRequestMonitor<PDAFrameCommandResult>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Create the frame data object based on the corresponding PDAFrame
rm.setData(new FrameDMData(getData().fFrame));
rm.done();
}
});
}
});
}
@ -267,13 +279,13 @@ public class PDAStack extends AbstractDsfService implements IStack {
}
// Execute the stack command and create the corresponding frame contexts.
fCommandCache.execute(
new PDAStackCommand(threadCtx),
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
getStackDepth(
context, -1,
new DataRequestMonitor<Integer>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
IFrameDMContext[] frameCtxs = new IFrameDMContext[getData().fFrames.length];
for (int i = 0; i < getData().fFrames.length; i++) {
IFrameDMContext[] frameCtxs = new IFrameDMContext[getData()];
for (int i = 0; i < getData(); i++) {
frameCtxs[i] = new FrameDMContext(getSession().getId(), threadCtx, i);
}
rm.setData(frameCtxs);
@ -282,6 +294,38 @@ public class PDAStack extends AbstractDsfService implements IStack {
});
}
public void getFrames(IDMContext context, final int startIndex, final int endIndex, final DataRequestMonitor<IFrameDMContext[]> rm) {
// Validate index range.
assert startIndex >=0 && (endIndex < 0 || startIndex <= endIndex);
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.
getStackDepth(
context, -1,
new DataRequestMonitor<Integer>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
int numFrames = endIndex < 0
? (getData() - startIndex)
: Math.min(endIndex + 1, getData()) - startIndex;
IFrameDMContext[] frameCtxs = new IFrameDMContext[numFrames];
for (int i = 0; i < numFrames; i++) {
frameCtxs[i] = new FrameDMContext(getSession().getId(), threadCtx, startIndex + i);
}
rm.setData(frameCtxs);
rm.done();
}
});
}
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));
@ -324,7 +368,7 @@ public class PDAStack extends AbstractDsfService implements IStack {
}
public void getStackDepth(IDMContext context, int maxDepth, final DataRequestMonitor<Integer> rm) {
public void getStackDepth(IDMContext context, final int maxDepth, final DataRequestMonitor<Integer> rm) {
final PDAThreadDMContext threadCtx =
DMContexts.getAncestorOfType(context, PDAThreadDMContext.class);
@ -336,11 +380,15 @@ public class PDAStack extends AbstractDsfService implements IStack {
// Execute stack command and return the data's size.
fCommandCache.execute(
new PDAStackCommand(threadCtx),
new DataRequestMonitor<PDAStackCommandResult>(getExecutor(), rm) {
new PDAStackDepthCommand(threadCtx),
new DataRequestMonitor<PDAStackDepthCommandResult>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getData().fFrames.length);
int depth= getData().fDepth;
if (maxDepth > 0 && maxDepth < depth) {
depth = maxDepth;
}
rm.setData(depth);
rm.done();
}
});

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* 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.PDAThreadDMContext;
/**
* Retrieves command stack frame information
*
* <pre>
* C: stack {thread_id} {frame_number}
* R: {file}|{line}|{function}|{var_1}|{var_2}|...
*
* Errors:
* error: invalid thread
* </pre>
*/
@Immutable
public class PDAFrameCommand extends AbstractPDACommand<PDAFrameCommandResult> {
public PDAFrameCommand(PDAThreadDMContext thread, int frameNum) {
super(thread, "frame " + thread.getID() + " " + frameNum);
}
@Override
public PDAFrameCommandResult createResult(String resultText) {
return new PDAFrameCommandResult(resultText);
}
}

View file

@ -0,0 +1,31 @@
/*******************************************************************************
* 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;
/**
* @see PDAFrameCommand
*/
@Immutable
public class PDAFrameCommandResult extends PDACommandResult {
/**
* Frame data return by the frame command.
*/
final public PDAFrame fFrame;
PDAFrameCommandResult(String response) {
super(response);
fFrame = new PDAFrame(response);
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* 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.PDAThreadDMContext;
/**
* Retrieves command stack depth
*
* <pre>
* C: stackdepth {thread_id}
* R: {depth}
*
* Errors:
* error: invalid thread
* </pre>
*/
@Immutable
public class PDAStackDepthCommand extends AbstractPDACommand<PDAStackDepthCommandResult> {
public PDAStackDepthCommand(PDAThreadDMContext thread) {
super(thread, "stackdepth " + thread.getID());
}
@Override
public PDAStackDepthCommandResult createResult(String resultText) {
return new PDAStackDepthCommandResult(resultText);
}
}

View file

@ -0,0 +1,32 @@
/*******************************************************************************
* 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;
/**
* @see PDADataCommand
*/
@Immutable
public class PDAStackDepthCommandResult extends PDACommandResult {
final public int fDepth;
PDAStackDepthCommandResult(String response) {
super(response);
int depth = 1; // default to something that won't cause NPEs
try {
depth = Integer.parseInt(response);
} catch (NumberFormatException e) {}
fDepth = depth;
}
}

View file

@ -114,14 +114,21 @@ public class CommandControlTestsBase {
fCommandControl.queueCommand(testCommand, rm);
}
};
String responseText = null;
fExecutor.execute(sendCommandQuery);
try {
PDACommandResult result = sendCommandQuery.get();
Assert.assertEquals("Command returned an unexpected result", expectedResult, result.fResponseText);
responseText = result.fResponseText;
} catch (ExecutionException e) {
throw e.getCause();
if (e.getCause() instanceof CoreException) {
responseText = ((CoreException)e.getCause()).getStatus().getMessage();
} else {
throw e.getCause();
}
}
Assert.assertEquals("Command returned an unexpected result", expectedResult, responseText);
}
protected void clearEvents() {

View file

@ -58,6 +58,10 @@ public class Test2 extends CommandControlTestsBase {
expectEvent("vmsuspended 1 breakpoint 12");
sendCommand("clear 19");
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
sendCommand("stackdepth 1", "3");
sendCommand("frame 1 0", fProgram + "|6|main");
sendCommand("frame 1 1", fProgram + "|18|sub1|m|n");
sendCommand("frame 1 2", fProgram + "|12|sub2" );
sendCommand("stepreturn 1");
expectEvent("vmresumed step");
expectEvent("vmsuspended 1 step");
@ -139,6 +143,10 @@ public class Test2 extends CommandControlTestsBase {
expectEvent("suspended 1 breakpoint 12");
sendCommand("clear 19");
sendCommand("stack 1", fProgram + "|6|main#" + fProgram + "|18|sub1|m|n#" + fProgram + "|12|sub2" );
sendCommand("stackdepth 1", "3");
sendCommand("frame 1 0", fProgram + "|6|main");
sendCommand("frame 1 1", fProgram + "|18|sub1|m|n");
sendCommand("frame 1 2", fProgram + "|12|sub2" );
sendCommand("stepreturn 1");
expectEvent("resumed 1 step");
expectEvent("suspended 1 step");

View file

@ -28,6 +28,7 @@ import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.debug.service.IStack;
import org.eclipse.dd.dsf.debug.service.IStack2;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
@ -54,7 +55,7 @@ import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
import org.osgi.framework.BundleContext;
public class MIStack extends AbstractDsfService
implements IStack
implements IStack2
{
protected static class MIFrameDMC extends AbstractDMContext
implements IFrameDMContext
@ -194,22 +195,55 @@ public class MIStack extends AbstractDsfService
return new MIFrameDMC(getSession().getId(), execDmc, level);
}
public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) {
public void getFrames(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext[]> rm) {
getFrames(ctx, 0, ALL_FRAMES, rm);
}
public void getFrames(final IDMContext ctx, final int startIndex, final int endIndex, final DataRequestMonitor<IFrameDMContext[]> rm) {
if (startIndex < 0 || endIndex > 0 && endIndex < startIndex) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid stack frame range [" + startIndex + ',' + endIndex + ']', null)); //$NON-NLS-1$
rm.done();
return;
}
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
//rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "No frame context found in " + ctx, null)); //$NON-NLS-1$
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
fMICommandCache.execute(
new MIStackListFrames(execDmc),
if (startIndex == 0 && endIndex == 0) {
// Try to retrieve the top stack frame from the cached stopped event.
if (fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()))
{
rm.setData(new IFrameDMContext[] { createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()) });
rm.done();
return;
}
}
final MIStackListFrames miStackListCmd;
// firstIndex is the first index retrieved
final int firstIndex;
if (endIndex >= 0) {
miStackListCmd = new MIStackListFrames(execDmc, startIndex, endIndex);
firstIndex = startIndex;
} else {
miStackListCmd = new MIStackListFrames(execDmc);
firstIndex = 0;
}
fMICommandCache.execute(
miStackListCmd,
new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getFrames(execDmc, getData()));
rm.setData(getFrames(execDmc, getData(), firstIndex, endIndex, startIndex));
rm.done();
}
});
@ -234,9 +268,11 @@ public class MIStack extends AbstractDsfService
}
// If stopped event is not available or doesn't contain frame info,
// query the full list of frames.
// query top stack frame
getFrames(
ctx,
0,
0,
new DataRequestMonitor<IFrameDMContext[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
@ -247,11 +283,20 @@ public class MIStack extends AbstractDsfService
}
//private MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) {
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info) {
IFrameDMContext[] frameDMCs = new MIFrameDMC[info.getMIFrames().length];
for (int i = 0; i < info.getMIFrames().length; i++) {
private IFrameDMContext[] getFrames(IMIExecutionDMContext execDmc, MIStackListFramesInfo info, int firstIndex, int lastIndex, int startIndex) {
int length = info.getMIFrames().length;
if (lastIndex > 0) {
int limit= lastIndex - startIndex + 1;
if (limit < length) {
length = limit;
}
}
IFrameDMContext[] frameDMCs = new MIFrameDMC[length];
for (int i = 0; i < length; i++) {
//frameDMCs[i] = new MIFrameDMC(this, info.getMIFrames()[i].getLevel());
frameDMCs[i] = createFrameDMContext(execDmc, info.getMIFrames()[i].getLevel());
final MIFrame frame= info.getMIFrames()[i + startIndex - firstIndex];
assert startIndex + i == frame.getLevel();
frameDMCs[i] = createFrameDMContext(execDmc, frame.getLevel());
}
return frameDMCs;
}