1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Patch for non-stop multi-threading

This commit is contained in:
Francois Chouinard 2008-07-22 19:19:48 +00:00
parent 22e14ab218
commit 593106d158
55 changed files with 2808 additions and 417 deletions

View file

@ -379,8 +379,9 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
public IMemoryBlockExtension getExtendedMemoryBlock(String expression, Object context) throws DebugException {
// Drill for the actual DMC
IMemoryDMContext memoryDmc = null;
IDMContext dmc = null;
if (context instanceof IAdaptable) {
IDMContext dmc = (IDMContext)((IAdaptable)context).getAdapter(IDMContext.class);
dmc = (IDMContext)((IAdaptable)context).getAdapter(IDMContext.class);
if (dmc != null) {
memoryDmc = DMContexts.getAncestorOfType(dmc, IMemoryDMContext.class);
}
@ -425,7 +426,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
// In case of failure, simply return 'null'
// Resolve the expression
blockAddress = resolveMemoryAddress(memoryDmc, expression);
blockAddress = resolveMemoryAddress(dmc, expression);
if (blockAddress == null) {
return null;
}
@ -451,7 +452,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
// Helper functions
///////////////////////////////////////////////////////////////////////////
private BigInteger resolveMemoryAddress(final IDMContext idmContext, final String expression) throws DebugException {
private BigInteger resolveMemoryAddress(final IDMContext dmc, final String expression) throws DebugException {
// Use a Query to "synchronize" the downstream calls
Query<BigInteger> query = new Query<BigInteger>() {
@ -461,7 +462,7 @@ public class DsfMemoryBlockRetrieval extends PlatformObject implements IMemoryBl
final IExpressions expressionService = (IExpressions) fExpressionServiceTracker.getService();
if (expressionService != null) {
// Create the expression
final IExpressionDMContext expressionDMC = expressionService.createExpression(idmContext, expression);
final IExpressionDMContext expressionDMC = expressionService.createExpression(dmc, expression);
String formatId = IFormattedValues.HEX_FORMAT;
FormattedValueDMContext valueDmc = expressionService.getFormattedValueContext(expressionDMC, formatId);
expressionService.getFormattedExpressionValue(

View file

@ -37,7 +37,7 @@ public interface IRunControl extends IDMService
/**
* Context representing a process, kernel, or some other logical container
* for execution cotnexts, which by itself can perform run-control
* for execution contexts, which by itself can perform run-control
* operations.
*/

View file

@ -30,8 +30,8 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.provisional.breakpoints.CBreakpointGdbThreadsFilterExtension;
import org.eclipse.dd.gdb.internal.provisional.launching.GdbLaunch;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBThreadData;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
@ -493,12 +493,12 @@ public class GdbThreadFilterEditor {
return;
}
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), GDBRunControl.class
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IGDBRunControl.class
.getName(), null);
tracker.open();
GDBRunControl runControl = (GDBRunControl) tracker.getService();
IGDBRunControl runControl = (IGDBRunControl) tracker.getService();
if (runControl != null) {
runControl.getThreadData((IMIExecutionDMContext) thread, new DataRequestMonitor<GDBThreadData>(
runControl.getThreadData((IMIExecutionDMContext) thread, new DataRequestMonitor<IGDBThreadData>(
ImmediateExecutor.getInstance(), rm) {
@Override
protected void handleSuccess() {

View file

@ -45,6 +45,7 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
protected TabFolder fTabFolder;
protected Text fGDBCommandText;
protected Text fGDBInitText;
protected Button fNonStopCheckBox;
private IMILaunchConfigurationComponent fSolibBlock;
private boolean fIsInitializing = false;
@ -64,6 +65,9 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
if (fSolibBlock != null)
fSolibBlock.setDefaults(configuration);
}
@ -86,6 +90,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
setInitializing(true);
String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT;
String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT;
boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT;
try {
gdbCommand = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
@ -99,10 +105,18 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
catch(CoreException e) {
}
try {
nonStopMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
}
catch(CoreException e) {
}
if (fSolibBlock != null)
fSolibBlock.initializeFrom(configuration);
fGDBCommandText.setText(gdbCommand);
fGDBInitText.setText(gdbInit);
fNonStopCheckBox.setSelection(nonStopMode);
setInitializing(false);
}
@ -112,6 +126,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
fGDBCommandText.getText().trim());
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
fGDBInitText.getText().trim());
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
fNonStopCheckBox.getSelection());
if (fSolibBlock != null)
fSolibBlock.performApply(configuration);
@ -242,8 +258,23 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
fGDBInitText.setText(res);
}
});
// TODO: Fetch the string from LaunchUIMessages
// TODO: Ideally, this field should be disabled if the back-end doesn't support non-stop debugging
// TODO: Find a way to determine if non-stop is supported (i.e. find the GDB version) then grey out the check box if necessary
// Button fNonStopButton = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString( "GDBDebuggerPage.15") ); //$NON-NLS-1$
fNonStopCheckBox = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.13")); //$NON-NLS-1$
fNonStopCheckBox.setEnabled(false);
fNonStopCheckBox.addSelectionListener( new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
updateLaunchConfigurationDialog();
}
});
label = ControlFactory.createLabel(subComp, LaunchUIMessages.getString("GDBDebuggerPage.9"), //$NON-NLS-1$
200, SWT.DEFAULT, SWT.WRAP);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3;
gd.widthHint = 200;

View file

@ -24,6 +24,7 @@ GDBDebuggerPage.9=(Warning: Some commands in this file may interfere with the st
GDBDebuggerPage.10=Shared Libraries
GDBDebuggerPage.11=Protocol:
GDBDebuggerPage.12=Default
GDBDebuggerPage.13=Non-stop mode (Note: Requires non-stop GDB)
StandardGDBDebuggerPage.0=Debugger executable must be specified.
StandardGDBDebuggerPage.1=GDB Debugger Options
StandardGDBDebuggerPage.2=Main

View file

@ -25,8 +25,8 @@ 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.gdb.internal.provisional.service.GDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.command.MIInferiorProcess;
@ -72,7 +72,7 @@ public class ContainerVMNode extends AbstractContainerVMNode
@Override
protected void updateLabelInSessionThread(final ILabelUpdate update) {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) {
handleFailedUpdate(update);
return;
@ -90,7 +90,7 @@ public class ContainerVMNode extends AbstractContainerVMNode
runControl.getProcessData(
dmc,
new ViewerDataRequestMonitor<GDBProcessData>(getExecutor(), update) {
new ViewerDataRequestMonitor<IGDBProcessData>(getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
@ -151,11 +151,11 @@ public class ContainerVMNode extends AbstractContainerVMNode
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) {
runControl.getProcessData(
procDmc,
new ViewerDataRequestMonitor<GDBProcessData>(runControl.getExecutor(), request) {
new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {
@ -203,11 +203,11 @@ public class ContainerVMNode extends AbstractContainerVMNode
try {
getSession().getExecutor().execute(new DsfRunnable() {
public void run() {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) {
runControl.getProcessData(
procDmc,
new ViewerDataRequestMonitor<GDBProcessData>(runControl.getExecutor(), request) {
new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override
protected void handleCompleted() {
if ( getStatus().isOK() ) {

View file

@ -20,8 +20,8 @@ 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.gdb.internal.provisional.service.GDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBThreadData;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
@ -49,7 +49,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
@Override
protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
for (final ILabelUpdate update : updates) {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) {
handleFailedUpdate(update);
continue;
@ -78,7 +78,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
// We're in a new dispatch cycle, and we have to check whether the
// service reference is still valid.
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class);
final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) {
handleFailedUpdate(update);
return;
@ -89,7 +89,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
// Retrieve the rest of the thread information
runControl.getThreadData(
dmc,
new ViewerDataRequestMonitor<GDBThreadData>(getSession().getExecutor(), update) {
new ViewerDataRequestMonitor<IGDBThreadData>(getSession().getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {

View file

@ -48,6 +48,12 @@ public class IGDBLaunchConfigurationConstants {
*/
public static final String ATTR_GDB_INIT = GdbPlugin.PLUGIN_ID + ".GDB_INIT"; //$NON-NLS-1$
/**
* Launch configuration attribute key. Boolean value to set the non-stop mode
* Debuger/gdb/MI property.
*/
public static final String ATTR_DEBUGGER_NON_STOP = GdbPlugin.PLUGIN_ID + ".NON_STOP"; //$NON-NLS-1$
/**
* Launch configuration attribute key. Boolean value to set the 'automatically load shared library symbols' flag of the debugger.
*/
@ -78,6 +84,11 @@ public class IGDBLaunchConfigurationConstants {
*/
public static final String DEBUGGER_GDB_INIT_DEFAULT = ".gdbinit"; //$NON-NLS-1$
/**
* Launch configuration attribute value. The key is ATTR_DEBUGGER_NON_STOP.
*/
public static final boolean DEBUGGER_NON_STOP_DEFAULT = false;
/**
* Launch configuration attribute value. The key is ATTR_DEBUGGER_AUTO_SOLIB.
*/

View file

@ -37,6 +37,7 @@ import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.GdbPlugin;
import org.eclipse.dd.gdb.internal.provisional.IGDBLaunchConfigurationConstants;
import org.eclipse.dd.gdb.internal.provisional.service.GdbDebugServicesFactory;
import org.eclipse.dd.gdb.internal.provisional.service.GdbDebugServicesFactoryNS;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
@ -56,6 +57,8 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
{
public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
private boolean isNonStopSession = false;
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
if ( monitor == null ) {
monitor = new NullProgressMonitor();
@ -167,6 +170,16 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
return SessionType.LOCAL;
}
private boolean isNonStopSession(ILaunchConfiguration config) {
try {
boolean nonStopMode = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
return nonStopMode;
} catch (CoreException e) {
}
return false;
}
private boolean getIsAttach(ILaunchConfiguration config) {
try {
String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN );
@ -202,6 +215,8 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
// the adapters will be created for the whole session, including
// the source lookup adapter.
isNonStopSession = isNonStopSession(configuration);
GdbLaunch launch = new GdbLaunch(configuration, mode, null);
launch.initialize();
launch.setSourceLocator(getSourceLocator(configuration, launch.getSession()));
@ -314,6 +329,12 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
}
private IDsfDebugServicesFactory newServiceFactory(String version) {
// TODO: Fix version number once non-stop GDB is delivered
if (isNonStopSession && version.startsWith("6.8.50.20080327")) { //$NON-NLS-1$
return new GdbDebugServicesFactoryNS(version);
}
if (version.startsWith("6.6") || //$NON-NLS-1$
version.startsWith("6.7") || //$NON-NLS-1$
version.startsWith("6.8")) { //$NON-NLS-1$

View file

@ -29,19 +29,21 @@ import org.eclipse.dd.gdb.internal.GdbPlugin;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.command.commands.CLIInfoThreads;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent;
import org.eclipse.dd.mi.service.command.output.CLIInfoThreadsInfo;
public class GDBRunControl extends MIRunControl {
public class GDBRunControl extends MIRunControl implements IGDBRunControl {
/**
* Implement a custom execution data for threads in order to provide additional
* information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used.
*/
public static class GDBThreadData {
public static class GDBThreadData implements IGDBThreadData {
private final String fId;
private final String fName;
@ -63,7 +65,7 @@ public class GDBRunControl extends MIRunControl {
* information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used.
*/
public static class GDBProcessData {
public static class GDBProcessData implements IGDBProcessData {
private final String fName;
GDBProcessData(String name) {
@ -98,8 +100,9 @@ public class GDBRunControl extends MIRunControl {
private void doInitialize(final RequestMonitor requestMonitor) {
fGdb = getServicesTracker().getService(GDBControl.class);
register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName()}, new Hashtable<String,String>());
register(new String[]{IRunControl.class.getName(),
IMIRunControl.class.getName(), MIRunControl.class.getName(),
IGDBRunControl.class.getName(), GDBRunControl.class.getName()}, new Hashtable<String,String>());
requestMonitor.done();
}
@ -149,12 +152,12 @@ public class GDBRunControl extends MIRunControl {
super.getExecutionContexts(c, rm1);
}
public void getProcessData(GDBControlDMContext gdbDmc, DataRequestMonitor<GDBProcessData> rm) {
public void getProcessData(GDBControlDMContext gdbDmc, DataRequestMonitor<IGDBProcessData> rm) {
rm.setData( new GDBProcessData(fGdb.getExecutablePath().lastSegment()) );
rm.done();
}
public void getThreadData(final IMIExecutionDMContext execDmc, final DataRequestMonitor<GDBThreadData> rm) {
public void getThreadData(final IMIExecutionDMContext execDmc, final DataRequestMonitor<IGDBThreadData> rm) {
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class);
assert containerDmc != null; // Every exec context should have a container as an ancestor.
getCache().execute(new CLIInfoThreads(containerDmc),

View file

@ -0,0 +1,129 @@
/*******************************************************************************
* 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 AB - Modified for additional functionality
*******************************************************************************/
package org.eclipse.dd.gdb.internal.provisional.service;
import java.util.Hashtable;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.MIRunControlNS;
import org.eclipse.dd.mi.service.command.commands.MIThreadInfo;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
public class GDBRunControlNS extends MIRunControlNS implements IGDBRunControl
{
/**
* Implement a custom execution data for threads in order to provide additional
* information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used.
*/
private static class GDBThreadData implements IGDBThreadData {
private final String fId;
private final String fName;
GDBThreadData(String id, String name) {
fId = id;
fName = name;
}
public String getName() {
return fName;
}
public String getId() { return fId; }
public boolean isDebuggerAttached() { return true; }
}
/**
* Implement a custom execution data the process in order to provide additional
* information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used.
*/
private static class GDBProcessData implements IGDBProcessData {
private final String fName;
GDBProcessData(String name) {
fName = name;
}
public String getName() {
return fName;
}
}
private GDBControl fGdb;
public GDBRunControlNS(DsfSession session) {
super(session);
}
@Override
public void initialize(final RequestMonitor requestMonitor) {
super.initialize(
new RequestMonitor(getExecutor(), requestMonitor) {
@Override
public void handleSuccess() {
doInitialize(requestMonitor);
}});
}
private void doInitialize(final RequestMonitor requestMonitor) {
fGdb = getServicesTracker().getService(GDBControl.class);
register(new String[]{IRunControl.class.getName(), IMIRunControl.class.getName(), IGDBRunControl.class.getName()}, new Hashtable<String,String>());
requestMonitor.done();
}
@Override
public void shutdown(final RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
public void getProcessData(GDBControlDMContext gdbDmc, DataRequestMonitor<IGDBProcessData> rm) {
rm.setData( new GDBProcessData(fGdb.getExecutablePath().lastSegment()) );
rm.done();
}
public void getThreadData(final IMIExecutionDMContext execDmc, final DataRequestMonitor<IGDBThreadData> rm) {
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class);
getCache().execute(new MIThreadInfo(containerDmc, execDmc.getThreadId()),
new DataRequestMonitor<MIThreadInfoInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(createThreadInfo(execDmc, getData()));
rm.done();
}
});
}
private GDBThreadData createThreadInfo(IMIExecutionDMContext dmc, MIThreadInfoInfo info) {
// There should be only 1 thread in the result, but just in case...
for (MIThreadInfoInfo.ThreadInfo thread : info.getThreadInfoList()) {
if (Integer.parseInt(thread.getGdbId()) == dmc.getThreadId()){
return new GDBThreadData(thread.getOsId(), ""); //$NON-NLS-1$
}
}
return new GDBThreadData("", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 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
*******************************************************************************/
package org.eclipse.dd.gdb.internal.provisional.service;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.mi.service.MIStackNS;
public class GdbDebugServicesFactoryNS extends GdbDebugServicesFactory {
public GdbDebugServicesFactoryNS(String version) {
super(version);
}
@Override
protected IStack createStackService(DsfSession session) {
return new MIStackNS(session);
}
@Override
protected IRunControl createRunControlService(DsfSession session) {
return new GDBRunControlNS(session);
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* 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 additional functionality
*******************************************************************************/
package org.eclipse.dd.gdb.internal.provisional.service;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIRunControl;
/**
* This interface provides access to controlling and monitoring the execution
* state of a process being debugged. This interface does not actually
* provide methods for creating or destroying execution contexts, it doesn't
* even have methods for getting labels. That's because it is expected that
* higher level services, ones that deal with processes, kernels, or target
* features will provide that functionality.
*/
public interface IGDBRunControl extends IMIRunControl
{
public interface IGDBThreadData {
public String getName();
public String getId();
public boolean isDebuggerAttached();
}
public interface IGDBProcessData {
public String getName();
}
public void getProcessData(GDBControlDMContext gdbDmc, DataRequestMonitor<IGDBProcessData> rm);
public void getThreadData(final IMIExecutionDMContext execDmc, final DataRequestMonitor<IGDBThreadData> dataRequestMonitor);
}

View file

@ -179,7 +179,7 @@ public class GDBControl extends AbstractMIControl {
* More strongly typed version of {@link #getControlDMContext()}.
*/
public GDBControlDMContext getGDBDMContext() {
return (GDBControlDMContext)getControlDMContext();
return (GDBControlDMContext) getControlDMContext();
}
public SessionType getSessionType() {

View file

@ -13,6 +13,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.debug.core,
org.eclipse.cdt.core
Export-Package:
org.eclipse.dd.mi.internal,
org.eclipse.dd.mi.service,
org.eclipse.dd.mi.service.command,
org.eclipse.dd.mi.service.command.commands,

View file

@ -893,7 +893,6 @@ public class ExpressionService extends AbstractDsfService implements IExpression
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) {
fExpressionCache.setContextAvailable(e.getDMContext(), false);

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* 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 additional functionality
*******************************************************************************/
package org.eclipse.dd.mi.service;
import org.eclipse.dd.dsf.debug.service.IRunControl;
/**
* This interface provides access to controlling and monitoring the execution
* state of a process being debugged. This interface does not actually
* provide methods for creating or destroying execution contexts, it doesn't
* even have methods for getting labels. That's because it is expected that
* higher level services, ones that deal with processes, kernels, or target
* features will provide that functionality.
*/
public interface IMIRunControl extends IRunControl
{
public IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, int threadId);
}

View file

@ -71,7 +71,6 @@ import org.eclipse.dd.mi.service.MIBreakpoints.BreakpointAddedEvent;
import org.eclipse.dd.mi.service.MIBreakpoints.BreakpointRemovedEvent;
import org.eclipse.dd.mi.service.MIBreakpoints.BreakpointUpdatedEvent;
import org.eclipse.dd.mi.service.MIBreakpoints.MIBreakpointDMContext;
import org.eclipse.dd.mi.service.MIRunControl.MIExecutionDMC;
import org.eclipse.dd.mi.service.breakpoint.actions.BreakpointActionAdapter;
import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.dd.mi.service.command.events.MIGDBExitEvent;
@ -1516,8 +1515,8 @@ public class MIBreakpointsManager extends AbstractDsfService implements IBreakpo
Set<String> results = new HashSet<String>();
if ((threads != null) && (supportsThreads(breakpoint))) {
for (IExecutionDMContext thread : threads) {
if (thread instanceof MIExecutionDMC) {
MIExecutionDMC dmc = (MIExecutionDMC) thread;
if (thread instanceof IMIExecutionDMContext) {
IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
results.add(((Integer) dmc.getThreadId()).toString());
}
}

View file

@ -69,8 +69,6 @@ public class MIMemory extends AbstractDsfService implements IMemory {
}
}
@SuppressWarnings("unused")
private MIRunControl fRunControl;
private MIMemoryCache fMemoryCache;
/**
@ -113,9 +111,6 @@ public class MIMemory extends AbstractDsfService implements IMemory {
// Register this service
register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>());
// Get the RunControl so we can retrieve the current Execution context
fRunControl = getServicesTracker().getService(MIRunControl.class);
// Create the memory requests cache
fMemoryCache = new MIMemoryCache();
@ -279,7 +274,7 @@ public class MIMemory extends AbstractDsfService implements IMemory {
//////////////////////////////////////////////////////////////////////////
@DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) {
public void eventDispatched(IRunControl.IContainerResumedDMEvent e) {
fMemoryCache.setTargetAvailable(e.getDMContext(), false);
if (e.getReason() != StateChangeReason.STEP) {
fMemoryCache.reset();
@ -287,7 +282,7 @@ public class MIMemory extends AbstractDsfService implements IMemory {
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
public void eventDispatched(IRunControl.IContainerSuspendedDMEvent e) {
fMemoryCache.setTargetAvailable(e.getDMContext(), true);
fMemoryCache.reset();
}

View file

@ -21,7 +21,6 @@ import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
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.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.service.AbstractDsfService;
@ -71,10 +70,9 @@ import org.osgi.framework.BundleContext;
* events and track service state, to be perfectly in sync with the service
* state.
*/
public class MIRunControl extends AbstractDsfService implements IRunControl
public class MIRunControl extends AbstractDsfService implements IMIRunControl
{
protected class MIExecutionDMC extends AbstractDMContext
implements IMIExecutionDMContext
class MIExecutionDMC extends AbstractDMContext implements IMIExecutionDMContext
{
/**
* Integer ID that is used to identify the thread in the GDB/MI protocol.
@ -119,7 +117,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
private static class ExecutionData implements IExecutionDMData {
static class ExecutionData implements IExecutionDMData {
private final StateChangeReason fReason;
ExecutionData(StateChangeReason reason) {
fReason = reason;
@ -137,7 +135,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
* @see MIRunControl
*/
@Immutable
protected static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
implements IDMEvent<V>, IMIDMEvent
{
final private T fMIInfo;
@ -153,7 +151,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
* Indicates that the given thread has been suspended.
*/
@Immutable
protected static class SuspendedEvent extends RunControlEvent<IExecutionDMContext, MIStoppedEvent>
static class SuspendedEvent extends RunControlEvent<IExecutionDMContext, MIStoppedEvent>
implements ISuspendedDMEvent
{
SuspendedEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo) {
@ -180,7 +178,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
protected static class ContainerSuspendedEvent extends SuspendedEvent
static class ContainerSuspendedEvent extends SuspendedEvent
implements IContainerSuspendedDMEvent
{
final IExecutionDMContext[] triggeringDmcs;
@ -196,7 +194,15 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
protected static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
static class ThreadSuspendedEvent extends SuspendedEvent
{
ThreadSuspendedEvent(IExecutionDMContext executionDmc, MIStoppedEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
implements IResumedDMEvent
{
ResumedEvent(IExecutionDMContext ctx, MIRunningEvent miInfo) {
@ -224,7 +230,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
protected static class ContainerResumedEvent extends ResumedEvent
static class ContainerResumedEvent extends ResumedEvent
implements IContainerResumedDMEvent
{
final IExecutionDMContext[] triggeringDmcs;
@ -241,7 +247,15 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
protected static class StartedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadCreatedEvent>
static class ThreadResumedEvent extends ResumedEvent
{
ThreadResumedEvent(IExecutionDMContext executionDmc, MIRunningEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
static class StartedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadCreatedEvent>
implements IStartedDMEvent
{
StartedDMEvent(IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) {
@ -250,7 +264,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
}
@Immutable
protected static class ExitedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadExitEvent>
static class ExitedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadExitEvent>
implements IExitedDMEvent
{
ExitedDMEvent(IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) {
@ -261,7 +275,7 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
private AbstractMIControl fConnection;
private CommandCache fMICommandCache;
// state flags
// State flags
private boolean fSuspended = true;
private boolean fResumePending = false;
private boolean fStepping = false;
@ -291,9 +305,6 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
fMICommandCache = new CommandCache(getSession(), fConnection);
fMICommandCache.setContextAvailable(fConnection.getControlDMContext(), true);
getSession().addServiceEventListener(this, null);
//register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName()}, new Hashtable<String,String>());
rm.done();
}

View file

@ -0,0 +1,897 @@
/*******************************************************************************
* 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 AB - Modified for handling of multiple threads
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.HashMap;
import java.util.Map;
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.Immutable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.datamodel.AbstractDMContext;
import org.eclipse.dd.dsf.datamodel.AbstractDMEvent;
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.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
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.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.AbstractMIControl;
import org.eclipse.dd.mi.service.command.commands.MIExecContinue;
import org.eclipse.dd.mi.service.command.commands.MIExecFinish;
import org.eclipse.dd.mi.service.command.commands.MIExecInterrupt;
import org.eclipse.dd.mi.service.command.commands.MIExecNext;
import org.eclipse.dd.mi.service.command.commands.MIExecNextInstruction;
import org.eclipse.dd.mi.service.command.commands.MIExecStep;
import org.eclipse.dd.mi.service.command.commands.MIExecStepInstruction;
import org.eclipse.dd.mi.service.command.commands.MIExecUntil;
import org.eclipse.dd.mi.service.command.commands.MIThreadListIds;
import org.eclipse.dd.mi.service.command.events.IMIDMEvent;
import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.dd.mi.service.command.events.MIErrorEvent;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIGDBExitEvent;
import org.eclipse.dd.mi.service.command.events.MIRunningEvent;
import org.eclipse.dd.mi.service.command.events.MISharedLibEvent;
import org.eclipse.dd.mi.service.command.events.MISignalEvent;
import org.eclipse.dd.mi.service.command.events.MISteppingRangeEvent;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIThreadListIdsInfo;
import org.osgi.framework.BundleContext;
/**
* Implementation note: This class implements event handlers for the events that
* are generated by this service itself. When the event is dispatched, these
* handlers will be called first, before any of the clients. These handlers
* update the service's internal state information to make them consistent with
* the events being issued. Doing this in the handlers as opposed to when the
* events are generated, guarantees that the state of the service will always be
* consistent with the events. The purpose of this pattern is to allow clients
* that listen to service events and track service state, to be perfectly in
* sync with the service state.
*/
public class MIRunControlNS extends AbstractDsfService implements IMIRunControl
{
// This is an exact copy of the structures in MIRunControl. In an ideal world,
// it would be declared only once in IMIRunControl but this is real life and
// it has to be duplicated for the sake of backward compatibility.
// It sucks and leads to bloated, error-prone code but that's the way it is.
class MIExecutionDMCNS extends AbstractDMContext implements IMIExecutionDMContext
{
/**
* Integer ID that is used to identify the thread in the GDB/MI protocol.
*/
private final int fThreadId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link MIRunControl#createMIExecutionContext(IContainerDMContext, int)}
* to create instances of this context based on the thread ID.
* <p/>
* Classes extending {@link MIRunControl} may also extend this class to include
* additional information in the context.
*
* @param sessionId Session that this context belongs to.
* @param containerDmc The container that this context belongs to.
* @param threadId GDB/MI thread identifier.
*/
protected MIExecutionDMCNS(String sessionId, IContainerDMContext containerDmc, int threadId) {
super(sessionId, containerDmc != null ? new IDMContext[] { containerDmc } : new IDMContext[0]);
fThreadId = threadId;
}
/**
* Returns the GDB/MI thread identifier of this context.
* @return
*/
public int getThreadId(){
return fThreadId;
}
@Override
public String toString() { return baseToString() + ".thread[" + fThreadId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
@Override
public boolean equals(Object obj) {
return super.baseEquals(obj) && ((MIExecutionDMCNS)obj).fThreadId == fThreadId;
}
@Override
public int hashCode() { return super.baseHashCode() ^ fThreadId; }
}
@Immutable
static class ExecutionData implements IExecutionDMData {
private final StateChangeReason fReason;
ExecutionData(StateChangeReason reason) {
fReason = reason;
}
public StateChangeReason getStateChangeReason() { return fReason; }
}
/**
* Base class for events generated by the MI Run Control service. Most events
* generated by the MI Run Control service are directly caused by some MI event.
* Other services may need access to the extended MI data carried in the event.
*
* @param <V> DMC that this event refers to
* @param <T> MIInfo object that is the direct cause of this event
* @see MIRunControl
*/
@Immutable
static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
implements IDMEvent<V>, IMIDMEvent
{
final private T fMIInfo;
public RunControlEvent(V dmc, T miInfo) {
super(dmc);
fMIInfo = miInfo;
}
public T getMIEvent() { return fMIInfo; }
}
/**
* Indicates that the given thread has been suspended.
*/
@Immutable
static class SuspendedEvent extends RunControlEvent<IExecutionDMContext, MIStoppedEvent>
implements ISuspendedDMEvent
{
SuspendedEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
if (getMIEvent() instanceof MIBreakpointHitEvent) {
return StateChangeReason.BREAKPOINT;
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
return StateChangeReason.STEP;
} else if (getMIEvent() instanceof MISharedLibEvent) {
return StateChangeReason.SHAREDLIB;
}else if (getMIEvent() instanceof MISignalEvent) {
return StateChangeReason.SIGNAL;
}else if (getMIEvent() instanceof MIWatchpointTriggerEvent) {
return StateChangeReason.WATCHPOINT;
}else if (getMIEvent() instanceof MIErrorEvent) {
return StateChangeReason.ERROR;
}else {
return StateChangeReason.USER_REQUEST;
}
}
}
@Immutable
static class ContainerSuspendedEvent extends SuspendedEvent
implements IContainerSuspendedDMEvent
{
final IExecutionDMContext[] triggeringDmcs;
ContainerSuspendedEvent(IContainerDMContext containerDmc, MIStoppedEvent miInfo, IExecutionDMContext triggeringDmc) {
super(containerDmc, miInfo);
this.triggeringDmcs = triggeringDmc != null
? new IExecutionDMContext[] { triggeringDmc } : new IExecutionDMContext[0];
}
public IExecutionDMContext[] getTriggeringContexts() {
return triggeringDmcs;
}
}
@Immutable
static class ThreadSuspendedEvent extends SuspendedEvent
{
ThreadSuspendedEvent(IExecutionDMContext executionDmc, MIStoppedEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
implements IResumedDMEvent
{
ResumedEvent(IExecutionDMContext ctx, MIRunningEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
switch(getMIEvent().getType()) {
case MIRunningEvent.CONTINUE:
return StateChangeReason.USER_REQUEST;
case MIRunningEvent.NEXT:
case MIRunningEvent.NEXTI:
return StateChangeReason.STEP;
case MIRunningEvent.STEP:
case MIRunningEvent.STEPI:
return StateChangeReason.STEP;
case MIRunningEvent.FINISH:
return StateChangeReason.STEP;
case MIRunningEvent.UNTIL:
case MIRunningEvent.RETURN:
break;
}
return StateChangeReason.UNKNOWN;
}
}
@Immutable
static class ContainerResumedEvent extends ResumedEvent
implements IContainerResumedDMEvent
{
final IExecutionDMContext[] triggeringDmcs;
ContainerResumedEvent(IContainerDMContext containerDmc, MIRunningEvent miInfo, IExecutionDMContext triggeringDmc) {
super(containerDmc, miInfo);
this.triggeringDmcs = triggeringDmc != null
? new IExecutionDMContext[] { triggeringDmc } : new IExecutionDMContext[0];
}
public IExecutionDMContext[] getTriggeringContexts() {
return triggeringDmcs;
}
}
@Immutable
static class ThreadResumedEvent extends ResumedEvent
{
ThreadResumedEvent(IExecutionDMContext executionDmc, MIRunningEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
static class StartedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadCreatedEvent>
implements IStartedDMEvent
{
StartedDMEvent(IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
static class ExitedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadExitEvent>
implements IExitedDMEvent
{
ExitedDMEvent(IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) {
super(executionDmc, miInfo);
}
}
protected class MIThreadRunState {
// State flags
boolean fSuspended = false;
boolean fResumePending = false;
boolean fStepping = false;
StateChangeReason fStateChangeReason;
}
///////////////////////////////////////////////////////////////////////////
// MIRunControlNS
///////////////////////////////////////////////////////////////////////////
private AbstractMIControl fConnection;
// The command cache applies only for the thread-info command at the
// container (process) level and is *always* available in non-stop mode.
// The only thing to do is to reset it every time a thread is created/
// terminated.
private CommandCache fMICommandCache;
private boolean fTerminated = false;
// ThreadStates indexed by the execution context
protected Map<IMIExecutionDMContext, MIThreadRunState> fThreadRunStates = new HashMap<IMIExecutionDMContext, MIThreadRunState>();
///////////////////////////////////////////////////////////////////////////
// Initialization and shutdown
///////////////////////////////////////////////////////////////////////////
public MIRunControlNS(DsfSession session) {
super(session);
}
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleSuccess() {
doInitialize(rm);
}
});
}
private void doInitialize(final RequestMonitor rm) {
fConnection = getServicesTracker().getService(AbstractMIControl.class);
fMICommandCache = new CommandCache(getSession(), fConnection);
fMICommandCache.setContextAvailable(fConnection.getControlDMContext(), true);
getSession().addServiceEventListener(this, null);
rm.done();
}
@Override
public void shutdown(final RequestMonitor rm) {
getSession().removeServiceEventListener(this);
fMICommandCache.reset();
super.shutdown(rm);
}
///////////////////////////////////////////////////////////////////////////
// AbstractDsfService
///////////////////////////////////////////////////////////////////////////
@Override
protected BundleContext getBundleContext() {
return MIPlugin.getBundleContext();
}
///////////////////////////////////////////////////////////////////////////
// IDMService
///////////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
if (dmc instanceof IExecutionDMContext) {
getExecutionData((IExecutionDMContext) dmc, (DataRequestMonitor<IExecutionDMData>) rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
///////////////////////////////////////////////////////////////////////////
// IRunControl
///////////////////////////////////////////////////////////////////////////
// ------------------------------------------------------------------------
// Suspend
// ------------------------------------------------------------------------
public boolean isSuspended(IExecutionDMContext context) {
// Thread case
if (context instanceof MIExecutionDMCNS) {
MIThreadRunState threadState = fThreadRunStates.get(context);
return (threadState == null) ? false : !fTerminated && threadState.fSuspended;
}
// Container case
if (context instanceof IContainerDMContext) {
boolean isSuspended = false;
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
if (DMContexts.isAncestorOf(threadContext, context)) {
isSuspended |= isSuspended(threadContext);
}
}
return isSuspended;
}
// Default case
return false;
}
public void canSuspend(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
// Thread case
if (context instanceof MIExecutionDMCNS) {
rm.setData(doCanSuspend(context));
rm.done();
return;
}
// Container case
if (context instanceof IContainerDMContext) {
boolean canSuspend = false;
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
if (DMContexts.isAncestorOf(threadContext, context)) {
canSuspend |= doCanSuspend(threadContext);
}
}
rm.setData(canSuspend);
rm.done();
return;
}
// Default case
rm.setData(false);
rm.done();
}
private boolean doCanSuspend(IExecutionDMContext context) {
MIThreadRunState threadState = fThreadRunStates.get(context);
return (threadState == null) ? false : !fTerminated && !threadState.fSuspended;
}
public void suspend(IExecutionDMContext context, final RequestMonitor rm) {
assert context != null;
// Thread case
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (thread != null) {
doSuspendThread(thread, rm);
return;
}
// Container case
IContainerDMContext container = DMContexts.getAncestorOfType(context, IContainerDMContext.class);
if (container != null) {
doSuspendContainer(container, rm);
return;
}
// Default case
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
rm.done();
}
private void doSuspendThread(IMIExecutionDMContext context, final RequestMonitor rm) {
if (!doCanSuspend(context)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED,
"Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
MIExecInterrupt cmd = new MIExecInterrupt(context, true);
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
private void doSuspendContainer(IExecutionDMContext context, final RequestMonitor rm) {
MIExecInterrupt cmd = new MIExecInterrupt(context, true);
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Resume
// ------------------------------------------------------------------------
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
// Thread case
if (context instanceof MIExecutionDMCNS) {
rm.setData(doCanResume(context));
rm.done();
return;
}
// Container case
if (context instanceof IContainerDMContext) {
boolean canSuspend = false;
for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
if (DMContexts.isAncestorOf(threadContext, context)) {
canSuspend |= doCanResume(threadContext);
}
}
rm.setData(canSuspend);
rm.done();
return;
}
// Default case
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
rm.done();
}
private boolean doCanResume(IExecutionDMContext context) {
MIThreadRunState threadState = fThreadRunStates.get(context);
return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending;
}
public void resume(IExecutionDMContext context, final RequestMonitor rm) {
assert context != null;
// Thread case
IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (thread != null) {
doResumeThread(thread, rm);
return;
}
// Container case
IContainerDMContext container = DMContexts.getAncestorOfType(context, IContainerDMContext.class);
if (container != null) {
doResumeContainer(container, rm);
return;
}
// Default case
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
rm.done();
}
private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) {
if (!doCanResume(context)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
MIThreadRunState threadState = fThreadRunStates.get(context);
if (threadState == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
threadState.fResumePending = true;
MIExecContinue cmd = new MIExecContinue(context, context.getThreadId());
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
private void doResumeContainer(IContainerDMContext context, final RequestMonitor rm) {
MIExecContinue cmd = new MIExecContinue(context, false);
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Step
// ------------------------------------------------------------------------
public boolean isStepping(IExecutionDMContext context) {
// If it's a thread, just look it up
if (context instanceof MIExecutionDMCNS) {
MIThreadRunState threadState = fThreadRunStates.get(context);
return (threadState == null) ? false : !fTerminated && threadState.fStepping;
}
// Default case
return false;
}
public void canStep(IExecutionDMContext context, StepType stepType, DataRequestMonitor<Boolean> rm) {
// If it's a thread, just look it up
if (context instanceof MIExecutionDMCNS) {
canResume(context, rm);
return;
}
// If it's a container, then we don't want to step it
rm.setData(false);
rm.done();
}
public void step(IExecutionDMContext context, StepType stepType, final RequestMonitor rm) {
assert context != null;
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED,
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
if (!doCanResume(context)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Cannot resume context", null)); //$NON-NLS-1$
rm.done();
return;
}
MIThreadRunState threadState = fThreadRunStates.get(context);
if (threadState == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Given context: " + context + " can't be found.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
threadState.fResumePending = true;
threadState.fStepping = true;
switch (stepType) {
case STEP_INTO:
fConnection.queueCommand(new MIExecStep(dmc, true),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
break;
case STEP_OVER:
fConnection.queueCommand(new MIExecNext(dmc, true),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
break;
case STEP_RETURN:
// The -exec-finish command operates on the selected stack frame, but here we always
// want it to operate on the stop stack frame. So we manually create a top-frame
// context to use with the MI command.
// We get a local instance of the stack service because the stack service can be shut
// down before the run control service is shut down. So it is possible for the
// getService() request below to return null.
MIStack stackService = getServicesTracker().getService(MIStack.class);
if (stackService != null) {
IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
fConnection.queueCommand(new MIExecFinish(topFrameDmc),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED,
"Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$
rm.done();
}
break;
case INSTRUCTION_STEP_INTO:
fConnection.queueCommand(new MIExecStepInstruction(dmc, true),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
break;
case INSTRUCTION_STEP_OVER:
fConnection.queueCommand(new MIExecNextInstruction(dmc, true),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
break;
default:
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,
INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$
rm.done();
}
}
// ------------------------------------------------------------------------
// Run to line
// ------------------------------------------------------------------------
// Later add support for Address and function.
// skipBreakpoints is not used at the moment. Implement later
public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor<MIInfo> rm) {
assert context != null;
IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
if (dmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, NOT_SUPPORTED,
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
if (!doCanResume(context)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Cannot resume context", null)); //$NON-NLS-1$
rm.done();
return;
}
MIThreadRunState threadState = fThreadRunStates.get(context);
if (threadState == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE,
"Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
threadState.fResumePending = true;
fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Support functions
// ------------------------------------------------------------------------
public void getExecutionContexts(final IContainerDMContext containerDmc, final DataRequestMonitor<IExecutionDMContext[]> rm) {
fMICommandCache.execute(new MIThreadListIds(containerDmc),
new DataRequestMonitor<MIThreadListIdsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(makeExecutionDMCs(containerDmc, getData()));
rm.done();
}
});
}
private IExecutionDMContext[] makeExecutionDMCs(IContainerDMContext containerCtx, MIThreadListIdsInfo info) {
IExecutionDMContext[] executionDmcs = new IMIExecutionDMContext[info.getThreadIds().length];
for (int i = 0; i < info.getThreadIds().length; i++) {
executionDmcs[i] = createMIExecutionContext(containerCtx, info.getThreadIds()[i]);
}
return executionDmcs;
}
public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm) {
MIThreadRunState threadState = fThreadRunStates.get(dmc);
if (threadState == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID,INVALID_HANDLE,
"Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
rm.done();
return;
}
if (dmc instanceof IMIExecutionDMContext) {
rm.setData(new ExecutionData(threadState.fSuspended ? threadState.fStateChangeReason : null));
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE,
"Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
}
rm.done();
}
///////////////////////////////////////////////////////////////////////////
// IMIRunControl
///////////////////////////////////////////////////////////////////////////
public IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, int threadId) {
return new MIExecutionDMCNS(getSession().getId(), container, threadId);
}
///////////////////////////////////////////////////////////////////////////
// IMIRunControl
///////////////////////////////////////////////////////////////////////////
public CommandCache getCache() {
return fMICommandCache;
}
protected AbstractMIControl getConnection() {
return fConnection;
}
///////////////////////////////////////////////////////////////////////////
// Event handlers
///////////////////////////////////////////////////////////////////////////
@DsfServiceEventHandler
public void eventDispatched(final MIRunningEvent e) {
IDMEvent<?> event = null;
// If it's not an execution context (what else could it be?!?), just propagate it
IMIExecutionDMContext executionDmc = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (executionDmc == null) {
event = new ResumedEvent(e.getDMContext(), e);
getSession().dispatchEvent(event, getProperties());
return;
}
// It's a thread execution context (since we are in non-stop mode)
event = new ThreadResumedEvent(e.getDMContext(), e);
updateThreadState(executionDmc, (ThreadResumedEvent) event);
getSession().dispatchEvent(event, getProperties());
fMICommandCache.reset();
// Find the container context, which is used in multi-threaded debugging.
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class);
if (containerDmc != null) {
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
event = new ContainerResumedEvent(containerDmc, e, triggeringCtx);
getSession().dispatchEvent(event, getProperties());
}
}
private void updateThreadState(IMIExecutionDMContext context, ThreadResumedEvent event) {
StateChangeReason reason = event.getReason();
boolean isStepping = reason.equals(StateChangeReason.STEP);
MIThreadRunState threadState = fThreadRunStates.get(context);
if (threadState == null) {
threadState = new MIThreadRunState();
fThreadRunStates.put(context, threadState);
}
threadState.fSuspended = false;
threadState.fResumePending = false;
threadState.fStateChangeReason = reason;
threadState.fStepping = isStepping;
}
@DsfServiceEventHandler
public void eventDispatched(final MIStoppedEvent e) {
IDMEvent<?> event = null;
// If it's not an execution context (what else could it be?!?), just propagate it
IMIExecutionDMContext executionDmc = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (executionDmc == null) {
event = new SuspendedEvent(e.getDMContext(), e);
getSession().dispatchEvent(event, getProperties());
return;
}
// It's a thread execution context (since we are in non-stop mode)
event = new ThreadSuspendedEvent(e.getDMContext(), e);
updateThreadState(executionDmc, (ThreadSuspendedEvent) event);
getSession().dispatchEvent(event, getProperties());
fMICommandCache.reset();
// Find the container context, which is used in multi-threaded debugging.
IContainerDMContext containerDmc = DMContexts.getAncestorOfType(e.getDMContext(), IContainerDMContext.class);
if (containerDmc != null) {
IExecutionDMContext triggeringCtx = !e.getDMContext().equals(containerDmc) ? e.getDMContext() : null;
event = new ContainerSuspendedEvent(containerDmc, e, triggeringCtx);
getSession().dispatchEvent(event, getProperties());
}
}
private void updateThreadState(IMIExecutionDMContext context, ThreadSuspendedEvent event) {
StateChangeReason reason = event.getReason();
MIThreadRunState threadState = fThreadRunStates.get(context);
if (threadState == null) {
threadState = new MIThreadRunState();
fThreadRunStates.put(context, threadState);
}
threadState.fSuspended = true;
threadState.fResumePending = false;
threadState.fStepping = false;
threadState.fStateChangeReason = reason;
}
@DsfServiceEventHandler
public void eventDispatched(final MIThreadCreatedEvent e) {
IContainerDMContext containerDmc = e.getDMContext();
IMIExecutionDMContext executionCtx = null;
if (e.getId() != -1) {
executionCtx = createMIExecutionContext(containerDmc, e.getId());
if (fThreadRunStates.get(executionCtx) == null) {
fThreadRunStates.put(executionCtx, new MIThreadRunState());
}
}
getSession().dispatchEvent(new StartedDMEvent(executionCtx, e), getProperties());
}
@DsfServiceEventHandler
public void eventDispatched(final MIThreadExitEvent e) {
IContainerDMContext containerDmc = e.getDMContext();
IMIExecutionDMContext executionCtx = null;
if (e.getId() != -1) {
executionCtx = createMIExecutionContext(containerDmc, e.getId());
fThreadRunStates.remove(executionCtx);
}
getSession().dispatchEvent(new ExitedDMEvent(executionCtx, e), getProperties());
}
@DsfServiceEventHandler
public void eventDispatched(ThreadResumedEvent e) {
IMIExecutionDMContext context = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (context == null) {
return;
}
}
@DsfServiceEventHandler
public void eventDispatched(ThreadSuspendedEvent e) {
IMIExecutionDMContext context = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (context == null) {
return;
}
}
@DsfServiceEventHandler
public void eventDispatched(ContainerResumedEvent e) {
IMIExecutionDMContext context = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (context == null) {
return;
}
}
@DsfServiceEventHandler
public void eventDispatched(ContainerSuspendedEvent e) {
IMIExecutionDMContext context = DMContexts.getAncestorOfType(e.getDMContext(), IMIExecutionDMContext.class);
if (context == null) {
return;
}
}
@DsfServiceEventHandler
public void eventDispatched(MIGDBExitEvent e) {
fTerminated = true;
}
}

View file

@ -0,0 +1,677 @@
/*******************************************************************************
* 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 handling of multiple execution contexts
*******************************************************************************/
package org.eclipse.dd.mi.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.utils.Addr32;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
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;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
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.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.command.AbstractMIControl;
import org.eclipse.dd.mi.service.command.commands.MIStackInfoDepth;
import org.eclipse.dd.mi.service.command.commands.MIStackListArguments;
import org.eclipse.dd.mi.service.command.commands.MIStackListFrames;
import org.eclipse.dd.mi.service.command.commands.MIStackListLocals;
import org.eclipse.dd.mi.service.command.events.IMIDMEvent;
import org.eclipse.dd.mi.service.command.events.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.output.MIArg;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIStackInfoDepthInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListArgumentsInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListFramesInfo;
import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
import org.osgi.framework.BundleContext;
public class MIStackNS extends AbstractDsfService
implements IStack2
{
protected static class MIFrameDMC extends AbstractDMContext
implements IFrameDMContext
{
private final int fLevel;
// public MIFrameDMC(MIStack service, int level) {
public MIFrameDMC(String sessionId, IExecutionDMContext execDmc, int level) {
super(sessionId, new IDMContext[] { execDmc });
fLevel = level;
}
public int getLevel() { return fLevel; }
@Override
public boolean equals(Object other) {
return super.baseEquals(other) && ((MIFrameDMC)other).fLevel == fLevel;
}
@Override
public int hashCode() {
return super.baseHashCode() ^ fLevel;
}
@Override
public String toString() {
return baseToString() + ".frame[" + fLevel + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
protected static class MIVariableDMC extends AbstractDMContext
implements IVariableDMContext
{
public enum Type { ARGUMENT, LOCAL }
final private Type fType;
final private int fIndex;
public MIVariableDMC(MIStackNS service, IFrameDMContext frame, Type type, int index) {
super(service, new IDMContext[] { frame });
fIndex = index;
fType = type;
}
public int getIndex() { return fIndex; }
public Type getType() { return fType; }
@Override
public boolean equals(Object other) {
return super.baseEquals(other) &&
((MIVariableDMC)other).fType == fType &&
((MIVariableDMC)other).fIndex == fIndex;
}
@Override
public int hashCode() {
int typeFactor = 0;
if (fType == Type.LOCAL) typeFactor = 2;
else if (fType == Type.ARGUMENT) typeFactor = 3;
return super.baseHashCode() ^ typeFactor ^ fIndex;
}
@Override
public String toString() {
return baseToString() + ".variable(" + fType + ")[" + fIndex + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
private CommandCache fMICommandCache;
private MIStoppedEvent fCachedStoppedEvent;
private IMIRunControl fMIRunControl;
public MIStackNS(DsfSession session)
{
super(session);
}
@Override
protected BundleContext getBundleContext()
{
return MIPlugin.getBundleContext();
}
@Override
public void initialize(final RequestMonitor rm) {
super.initialize(
new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleSuccess() {
doInitialize(rm);
}
});
}
private void doInitialize(RequestMonitor rm) {
AbstractMIControl miControl = getServicesTracker().getService(AbstractMIControl.class);
fMICommandCache = new CommandCache(getSession(), miControl);
fMICommandCache.setContextAvailable(miControl.getControlDMContext(), true);
fMIRunControl = getServicesTracker().getService(IMIRunControl.class);
getSession().addServiceEventListener(this, null);
register(new String[]{IStack.class.getName(), MIStackNS.class.getName()}, new Hashtable<String,String>());
rm.done();
}
@Override
public void shutdown(RequestMonitor rm)
{
unregister();
getSession().removeServiceEventListener(this);
fMICommandCache.reset();
super.shutdown(rm);
}
@SuppressWarnings("unchecked")
public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) {
if (dmc instanceof MIFrameDMC) {
getFrameData((MIFrameDMC)dmc, (DataRequestMonitor<IFrameDMData>)rm);
// getFrameData invokes rm
} else if (dmc instanceof MIVariableDMC) {
getVariableData((MIVariableDMC)dmc, (DataRequestMonitor<IVariableDMData>)rm);
// getVariablesData invokes rm
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
rm.done();
}
}
/**
* Creates a frame context. This method is intended to be used by other MI
* services and sub-classes which need to create a frame context directly.
* <p>
* Sub-classes can override this method to provide custom stack frame
* context implementation.
* </p>
* @param execDmc Execution context that this frame is to be a child of.
* @param level Level of the new context.
* @return A new frame context.
*/
public IFrameDMContext createFrameDMContext(IExecutionDMContext execDmc, int level) {
return new MIFrameDMC(getSession().getId(), execDmc, level);
}
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) {
// Make sure we have an execution context (ideally a thread)
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context " + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
// Make sure the indices are OK
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;
}
// Make sure the thread is stopped
if (!fMIRunControl.isSuspended(execDmc)) {
rm.setData(new IFrameDMContext[0]);
rm.done();
return;
}
// Case of retrieving the top stack frame from the cached stopped event.
if (startIndex == 0 && endIndex == 0) {
if (fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()))
{
rm.setData(new IFrameDMContext[] { createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()) });
rm.done();
return;
}
}
// Select the proper MI command variant
final MIStackListFrames miStackListCmd;
final int firstIndex;
if (endIndex >= 0) {
miStackListCmd = new MIStackListFrames(execDmc, true, startIndex, endIndex);
firstIndex = startIndex;
} else {
miStackListCmd = new MIStackListFrames(execDmc, true);
firstIndex = 0;
}
// And go...
fMICommandCache.execute(
miStackListCmd,
new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getFrames(execDmc, getData(), firstIndex, endIndex, startIndex));
rm.done();
}
});
}
public void getTopFrame(final IDMContext ctx, final DataRequestMonitor<IFrameDMContext> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context" + ctx, null)); //$NON-NLS-1$
rm.done();
return;
}
// Try to retrieve the top stack frame from the cached stopped event.
if (fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()))
{
rm.setData(createFrameDMContext(execDmc, fCachedStoppedEvent.getFrame().getLevel()));
rm.done();
return;
}
// If stopped event is not available or doesn't contain frame info,
// query top stack frame
getFrames(
ctx,
0,
0,
new DataRequestMonitor<IFrameDMContext[]>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getData()[0]);
rm.done();
}
});
}
//private MIFrameDMC[] getFrames(DsfMIStackListFramesInfo info) {
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());
final MIFrame frame= info.getMIFrames()[i + startIndex - firstIndex];
assert startIndex + i == frame.getLevel();
frameDMCs[i] = createFrameDMContext(execDmc, frame.getLevel());
}
return frameDMCs;
}
public void getFrameData(final IFrameDMContext frameDmc, final DataRequestMonitor<IFrameDMData> rm) {
if (!(frameDmc instanceof MIFrameDMC)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final MIFrameDMC miFrameDmc = (MIFrameDMC)frameDmc;
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
/**
* Base class for the IFrameDMData object that uses an MIFrame object to
* provide the data. Sub-classes must provide the MIFrame object
*/
abstract class FrameData implements IFrameDMData
{
abstract protected MIFrame getMIFrame();
public IAddress getAddress() {
String addr = getMIFrame().getAddress();
if (addr.startsWith("0x")) { //$NON-NLS-1$
addr = addr.substring(2);
}
if (addr.length() <= 8) {
return new Addr32(getMIFrame().getAddress());
} else {
return new Addr64(getMIFrame().getAddress());
}
}
public int getColumn() { return 0; }
public String getFile() { return getMIFrame().getFile(); }
public int getLine() { return getMIFrame().getLine(); }
public String getFunction() { return getMIFrame().getFunction(); }
@Override
public String toString() { return getMIFrame().toString(); }
}
// If requested frame is the top stack frame, try to retrieve it from
// the stopped event data.
class FrameDataFromStoppedEvent extends FrameData {
private final MIStoppedEvent fEvent;
FrameDataFromStoppedEvent(MIStoppedEvent event) { fEvent = event; }
@Override
protected MIFrame getMIFrame() { return fEvent.getFrame(); }
}
// Retrieve the top stack frame from the stopped event only if the selected thread is the one on which stopped event
// is raised
if (fCachedStoppedEvent != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
miFrameDmc.fLevel == 0 &&
fCachedStoppedEvent.getFrame() != null)
{
rm.setData(new FrameDataFromStoppedEvent(fCachedStoppedEvent));
rm.done();
return;
}
// If not, retrieve the full list of frame data.
class FrameDataFromMIStackFrameListInfo extends FrameData {
private MIStackListFramesInfo fFrameDataCacheInfo;
private int fFrameIndex;
FrameDataFromMIStackFrameListInfo(MIStackListFramesInfo info, int index) {
fFrameDataCacheInfo = info;
fFrameIndex = index;
}
@Override
protected MIFrame getMIFrame() { return fFrameDataCacheInfo.getMIFrames()[fFrameIndex]; }
}
fMICommandCache.execute(
new MIStackListFrames(execDmc, true),
new DataRequestMonitor<MIStackListFramesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Find the index to the correct MI frame object.
int idx = findFrameIndex(getData().getMIFrames(), miFrameDmc.fLevel);
if (idx == -1) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the data object.
rm.setData(new FrameDataFromMIStackFrameListInfo(getData(), idx));
rm.done();
}
});
}
public void getArguments(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// If requested frame is the top stack frame, try to retrieve it from
// the stopped event data.
if (frameDmc.getLevel() == 0 &&
fCachedStoppedEvent != null &&
fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
fCachedStoppedEvent.getFrame().getArgs() != null)
{
rm.setData(makeVariableDMCs(
frameDmc, MIVariableDMC.Type.ARGUMENT, fCachedStoppedEvent.getFrame().getArgs().length));
rm.done();
return;
}
// If not, retrieve the full list of frame data.
fMICommandCache.execute(
new MIStackListArguments(execDmc, true, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Find the index to the correct MI frame object.
// Note: this is a short-cut, but it won't work once we implement retrieving
// partial lists of stack frames.
int idx = frameDmc.getLevel();
if (idx == -1 || idx >= getData().getMIFrames().length) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_STATE, "Invalid frame " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the variable array out of MIArg array.
MIArg[] args = getData().getMIFrames()[idx].getArgs();
if (args == null) args = new MIArg[0];
rm.setData(makeVariableDMCs(frameDmc, MIVariableDMC.Type.ARGUMENT, args.length));
rm.done();
}
});
}
public void getVariableData(IVariableDMContext variableDmc, final DataRequestMonitor<IVariableDMData> rm) {
if (!(variableDmc instanceof MIVariableDMC)) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context type " + variableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final MIVariableDMC miVariableDmc = (MIVariableDMC)variableDmc;
// Extract the frame DMC from the variable DMC.
final MIFrameDMC frameDmc = DMContexts.getAncestorOfType(variableDmc, MIFrameDMC.class);
if (frameDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No frame context found in " + variableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameDmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "No execution context found in " + frameDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
/**
* Same as with frame objects, this is a base class for the IVariableDMData object that uses an MIArg object to
* provide the data. Sub-classes must supply the MIArg object.
*/
class VariableData implements IVariableDMData {
private MIArg dsfMIArg;
VariableData(MIArg arg){
dsfMIArg = arg;
}
public String getName() { return dsfMIArg.getName(); }
public String getValue() { return dsfMIArg.getValue(); }
@Override
public String toString() { return dsfMIArg.toString(); }
}
// Check if the stopped event can be used to extract the variable value.
if (execDmc != null && miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT &&
frameDmc.fLevel == 0 && fCachedStoppedEvent != null && fCachedStoppedEvent.getFrame() != null &&
execDmc.equals(fCachedStoppedEvent.getDMContext()) &&
fCachedStoppedEvent.getFrame().getArgs() != null)
{
if (miVariableDmc.fIndex >= fCachedStoppedEvent.getFrame().getArgs().length) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, -1, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
rm.setData(new VariableData(fCachedStoppedEvent.getFrame().getArgs()[miVariableDmc.fIndex]));
rm.done();
return;
}
if (miVariableDmc.fType == MIVariableDMC.Type.ARGUMENT){
fMICommandCache.execute(
new MIStackListArguments(execDmc, true, true),
new DataRequestMonitor<MIStackListArgumentsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Find the correct frame and argument
if ( frameDmc.fLevel >= getData().getMIFrames().length ||
miVariableDmc.fIndex >= getData().getMIFrames()[frameDmc.fLevel].getArgs().length )
{
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
rm.done();
return;
}
// Create the data object.
rm.setData(new VariableData(getData().getMIFrames()[frameDmc.fLevel].getArgs()[miVariableDmc.fIndex]));
rm.done();
}});
}//if
if (miVariableDmc.fType == MIVariableDMC.Type.LOCAL){
fMICommandCache.execute(
new MIStackListLocals(frameDmc, true, true),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// Create the data object.
MIArg[] locals = getData().getLocals();
if (locals.length > miVariableDmc.fIndex) {
rm.setData(new VariableData(locals[miVariableDmc.fIndex]));
} else {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid variable " + miVariableDmc, null)); //$NON-NLS-1$
}
rm.done();
}
});
}//if
}
private MIVariableDMC[] makeVariableDMCs(IFrameDMContext frame, MIVariableDMC.Type type, int count) {
MIVariableDMC[] variables = new MIVariableDMC[count];
for (int i = 0; i < count; i++) {
variables[i]= new MIVariableDMC(this, frame, type, i);
}
return variables;
}
private int findFrameIndex(MIFrame[] frames, int level) {
for (int idx = 0; idx < frames.length; idx++) {
if (frames[idx].getLevel() == level) {
return idx;
}
}
return -1;
}
public void getLocals(final IFrameDMContext frameDmc, final DataRequestMonitor<IVariableDMContext[]> rm) {
final List<IVariableDMContext> localsList = new ArrayList<IVariableDMContext>();
final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData( localsList.toArray(new IVariableDMContext[localsList.size()]) );
rm.done();
}
};
countingRm.setDoneCount(2);
getArguments(
frameDmc,
new DataRequestMonitor<IVariableDMContext[]>(getExecutor(), countingRm) {
@Override
protected void handleSuccess() {
localsList.addAll( Arrays.asList(getData()) );
countingRm.done();
}
});
fMICommandCache.execute(
new MIStackListLocals(frameDmc, true, true),
new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) {
@Override
protected void handleSuccess() {
localsList.addAll( Arrays.asList(
makeVariableDMCs(frameDmc, MIVariableDMC.Type.LOCAL, getData().getLocals().length)) );
countingRm.done();
}
});
}
public void getStackDepth(IDMContext dmc, final int maxDepth, final DataRequestMonitor<Integer> rm) {
// Make sure we have an execution context (ideally a thread)
final IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IMIExecutionDMContext.class);
if (execDmc == null) {
rm.setStatus(new Status(IStatus.ERROR, MIPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
rm.done();
return;
}
// Make sure the thread is stopped
if (!fMIRunControl.isSuspended(execDmc)) {
rm.setData(0);
rm.done();
return;
}
// Select the proper MI command variant
MIStackInfoDepth depthCommand = null;
if (maxDepth > 0) {
depthCommand = new MIStackInfoDepth(execDmc, true, maxDepth);
}
else {
depthCommand = new MIStackInfoDepth(execDmc);
}
// And go...
fMICommandCache.execute(
depthCommand,
new DataRequestMonitor<MIStackInfoDepthInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getData().getDepth());
rm.done();
}
});
}
// IServiceEventListener
@DsfServiceEventHandler
public void eventDispatched(IResumedDMEvent e) {
fMICommandCache.setContextAvailable(e.getDMContext(), false);
if (e.getReason() != StateChangeReason.STEP) {
fCachedStoppedEvent = null;
fMICommandCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(ISuspendedDMEvent e) {
fMICommandCache.setContextAvailable(e.getDMContext(), true);
fMICommandCache.reset();
}
@DsfServiceEventHandler
public void eventDispatched(IMIDMEvent e) {
MIEvent<? extends IDMContext> miEvent = e.getMIEvent();
if (miEvent instanceof MIStoppedEvent) {
fCachedStoppedEvent = (MIStoppedEvent)miEvent;
}
}
}

View file

@ -31,6 +31,8 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
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.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
@ -86,7 +88,6 @@ public abstract class AbstractMIControl extends AbstractDsfService
*/
private final CommandHandle fTerminatorHandle = new CommandHandle(null, null);
/*
* Various listener control variables used to keep track of listeners who want to monitor
* what the control object is doing.
@ -207,7 +208,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
// Cast the return token to match the result type of MI Command. This is checking
// against an erased type so it should never throw any exceptions.
@SuppressWarnings("unchecked")
DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>)rm;
DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>) rm;
final CommandHandle handle = new CommandHandle(miCommand, miDone);
@ -240,36 +241,41 @@ public abstract class AbstractMIControl extends AbstractDsfService
}
private void processNextQueuedCommand() {
if ( fCommandQueue.size() > 0 ) {
CommandHandle handle = fCommandQueue.remove(0);
if ( handle != null ) {
if (fCommandQueue.size() > 0) {
final CommandHandle handle = fCommandQueue.remove(0);
if (handle != null) {
processCommandSent(handle);
// Identify target thread/frame (we might have to update them at the target)
final IDMContext targetContext = handle.fCommand.getContext();
final int targetThread = (handle.getThreadId() != null) ? handle.getThreadId().intValue() : -1;
final int targetFrame = (handle.getStackFrameId() != null) ? handle.getStackFrameId().intValue() : -1;
// The thread-select and frame-select make sense only if the thread is stopped.
// Some non-stop commands don't require the thread to be stopped so we send the
// command anyway.
IRunControl runControl = getServicesTracker().getService(IRunControl.class);
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(targetContext, IMIExecutionDMContext.class);
if (runControl != null && execDmc != null && runControl.isSuspended(execDmc)) {
// Before the command is sent, Check the Thread Id and send it to
// the queue only if the id has been changed.
if( handle.getThreadId()!= null &&
handle.getThreadId().intValue() != fCurrentThreadId && handle.getThreadId().intValue() != 0)
{
// Re-set the level
fCurrentThreadId = handle.getThreadId().intValue();
CommandHandle cmdHandle = new CommandHandle(
new MIThreadSelect(handle.fCommand.getContext(), fCurrentThreadId), null);
if (targetThread != -1 && targetThread != fCurrentThreadId) {
fCurrentThreadId = targetThread;
resetCurrentStackLevel();
CommandHandle cmdHandle = new CommandHandle(new MIThreadSelect(execDmc), null);
cmdHandle.generateTokenId();
fTxCommands.add(cmdHandle);
}
// Before the command is sent, Check the Stack level and send it to
// the queue only if the level has been changed.
if( handle.getStackFrameId()!= null &&
handle.getStackFrameId().intValue() != fCurrentStackLevel)
{
// Re-set the level
fCurrentStackLevel = handle.getStackFrameId().intValue();
CommandHandle cmdHandle = new CommandHandle(
new MIStackSelectFrame(handle.fCommand.getContext(), fCurrentStackLevel), null);
if (targetFrame != -1 && targetFrame != fCurrentStackLevel) {
fCurrentStackLevel = targetFrame;
CommandHandle cmdHandle = new CommandHandle(new MIStackSelectFrame(execDmc, targetFrame), null);
cmdHandle.generateTokenId();
fTxCommands.add(cmdHandle);
}
}
handle.generateTokenId();
fTxCommands.add(handle);
}

View file

@ -57,7 +57,6 @@ public class CLIEventProcessor
// Last Thread ID created
private static int fLastThreadId;
public CLIEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc, MIInferiorProcess inferior) {
fCommandControl = connection;
fInferior = inferior;
@ -116,25 +115,9 @@ public class CLIEventProcessor
Pattern pattern = Pattern.compile("(^\\[New Thread.*LWP\\s*)(\\d*)", Pattern.MULTILINE); //$NON-NLS-1$
Matcher matcher = pattern.matcher(exec.getCString());
if (matcher.find()) {
//fMapThreadIds.put(matcher.group(2), Integer.valueOf(++fLastThreadId));
//DsfMIEvent e = new DsfMIThreadCreatedEvent(Integer.valueOf(matcher.group(2)));
MIEvent<?> e = new MIThreadCreatedEvent(fContainerDmc, ++fLastThreadId);
// Dispatch DsfMIThreadCreatedEvent
fCommandControl.getSession().dispatchEvent(e, fCommandControl.getProperties());
}
// HACK - For GDB thread exit events, we won't use the events generated by GDB. This event is
// raised in GDBRunControl class by polling and comparing the ExecutionContexts returned by
// -thread-list-ids command. This is done as threads reported by exit event are still reported till
// they completely exit the system.
// Look for Thread Exited Event with Pattern [Thread 1077300144 (LWP 23832) exited]\n
// See bug 200615 for details.
// pattern = Pattern.compile("(^\\[Thread.*LWP\\s)(\\d*)(.*exited.*$)", Pattern.MULTILINE); //$NON-NLS-1$
// matcher = pattern.matcher(exec.getCString());
// if (matcher.find()) {
// DsfMIEvent e = new DsfMIThreadExitEvent(fMapThreadIds.get(matcher.group(2)).intValue());
// // Dispatch DsfMIThreadExitEvent
// fConnection.getSession().dispatchEvent(e, fConnection.getProperties());
// }
}
}

View file

@ -22,7 +22,8 @@ import org.eclipse.dd.dsf.debug.service.command.ICommandToken;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.mi.internal.MIPlugin;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.commands.MIExecContinue;
import org.eclipse.dd.mi.service.command.commands.MIExecFinish;
import org.eclipse.dd.mi.service.command.commands.MIExecNext;
@ -41,6 +42,8 @@ import org.eclipse.dd.mi.service.command.events.MIRunningEvent;
import org.eclipse.dd.mi.service.command.events.MISignalEvent;
import org.eclipse.dd.mi.service.command.events.MISteppingRangeEvent;
import org.eclipse.dd.mi.service.command.events.MIStoppedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointScopeEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.dd.mi.service.command.output.MIConst;
@ -51,7 +54,6 @@ import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIResultRecord;
import org.eclipse.dd.mi.service.command.output.MIStatusAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
@ -103,6 +105,7 @@ public class MIRunControlEventProcessor
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
if (oobr instanceof MIExecAsyncOutput) {
MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr;
// Change of state.
@ -113,7 +116,6 @@ public class MIRunControlEventProcessor
fCommandControl.resetCurrentThreadLevel();
fCommandControl.resetCurrentStackLevel();
List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
@ -129,30 +131,68 @@ public class MIRunControlEventProcessor
}
}
}
// We were stopped for some unknown reason, for example
// GDB for temporary breakpoints will not send the
// "reason" ??? still fire a stopped event.
if (events.isEmpty()) {
MIEvent<?> e = MIStoppedEvent.parse(
fServicesTracker.getService(MIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults());
fServicesTracker.getService(IMIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults());
events.add(e);
}
for (MIEvent<?> event : events) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
else if ("running".equals(state)) { //$NON-NLS-1$
int token = exec.getToken();
MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("thread-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
String thread = ((MIConst) val).getString();
MIEvent<?> evt = null;
int threadId = 0;
try {
threadId = Integer.parseInt(thread);
IMIExecutionDMContext context = fServicesTracker.getService(IMIRunControl.class).createMIExecutionContext(fContainerDmc, threadId);
evt = new MIRunningEvent(context, token, MIRunningEvent.CONTINUE);
}
catch (NumberFormatException e) {
evt = new MIRunningEvent(fContainerDmc, token, MIRunningEvent.CONTINUE);
}
fCommandControl.getSession().dispatchEvent(evt, fCommandControl.getProperties());
}
}
}
}
}
else if (oobr instanceof MINotifyAsyncOutput) {
// Parse the string and dispatch the corresponding event
MINotifyAsyncOutput exec = (MINotifyAsyncOutput) oobr;
String miEvent = exec.getAsyncClass();
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
MIEvent<?> event = MIThreadCreatedEvent.parse(fContainerDmc, exec.getToken(), exec.getMIResults());
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
else if ("thread-exited".equals(miEvent)) { //$NON-NLS-1$
MIEvent<?> event = MIThreadExitEvent.parse(fContainerDmc, exec.getToken(), exec.getMIResults());
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
}
else if (oobr instanceof MIStatusAsyncOutput) {
// Nothing done .. but what about +download??
} else if (oobr instanceof MINotifyAsyncOutput) {
// Nothing
}
}
}
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
MIRunControl runControl = fServicesTracker.getService(MIRunControl.class);
IMIRunControl runControl = fServicesTracker.getService(IMIRunControl.class);
MIEvent<?> event = null;
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
event = MIBreakpointHitEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());

View file

@ -17,7 +17,7 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-continue
* -exec-continue [--thread <tid>]
*
* Asynchronous command. Resumes the execution of the inferior program
* until a breakpoint is encountered, or until the inferior exits.
@ -26,6 +26,17 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecContinue extends MICommand<MIInfo>
{
public MIExecContinue(IExecutionDMContext dmc) {
this(dmc, false);
}
public MIExecContinue(IExecutionDMContext dmc, boolean allThreads) {
super(dmc, "-exec-continue"); //$NON-NLS-1$
if (allThreads) {
setParameters(new String[] { "--all" }); //$NON-NLS-1$
}
}
public MIExecContinue(IExecutionDMContext dmc, int threadId) {
super(dmc, "-exec-continue", new String[] { "--thread", Integer.toString(threadId) }); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -14,11 +14,12 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-interrupt
* -exec-interrupt [ --thread <tid> | --all ]
*
* Asynchronous command. Interrupts the background execution of the
* target. Note how the token associated with the stop message is the one
@ -31,6 +32,20 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecInterrupt extends MICommand<MIInfo>
{
public MIExecInterrupt(IExecutionDMContext dmc) {
this(dmc, false);
}
public MIExecInterrupt(IExecutionDMContext dmc, boolean allThreads) {
super(dmc, "-exec-interrupt"); //$NON-NLS-1$
if (allThreads) {
setParameters(new String[] { "--all" }); //$NON-NLS-1$
}
}
public MIExecInterrupt(IMIExecutionDMContext dmc, boolean setThread) {
super(dmc, "-exec-interrupt"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()) }); //$NON-NLS-1$
}
}
}

View file

@ -14,11 +14,12 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-next
* -exec-next [--thread <tid>] [count]
*
* Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached.
@ -27,10 +28,23 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecNext extends MICommand<MIInfo>
{
public MIExecNext(IExecutionDMContext dmc) {
super(dmc, "-exec-next"); //$NON-NLS-1$
this(dmc, 1);
}
public MIExecNext(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
public MIExecNext(IMIExecutionDMContext dmc, boolean setThread) {
this(dmc, setThread, 1);
}
public MIExecNext(IMIExecutionDMContext dmc, boolean setThread, int count) {
super(dmc, "-exec-next"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()), Integer.toString(count) }); //$NON-NLS-1$
} else {
setParameters(new String[] { Integer.toString(count) });
}
}
}

View file

@ -13,6 +13,7 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
@ -28,10 +29,23 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecNextInstruction extends MICommand<MIInfo>
{
public MIExecNextInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-next-instruction"); //$NON-NLS-1$
this(dmc, 1);
}
public MIExecNextInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
public MIExecNextInstruction(IMIExecutionDMContext dmc, boolean setThread) {
this(dmc, setThread, 1);
}
public MIExecNextInstruction(IMIExecutionDMContext dmc, boolean setThread, int count) {
super(dmc, "-exec-next-instruction"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()), Integer.toString(count) }); //$NON-NLS-1$
} else {
setParameters(new String[] { Integer.toString(count) });
}
}
}

View file

@ -17,7 +17,7 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* <code>-exec-return</code>
* -exec-return [args]
*
* <p>
* Makes current function return immediately. Doesn't execute the
@ -38,5 +38,4 @@ public class MIExecReturn extends MICommand<MIInfo>
public MIExecReturn(IFrameDMContext dmc, String arg) {
super(dmc, "-exec-return", new String[] { arg }); //$NON-NLS-1$
}
}

View file

@ -14,11 +14,12 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-step
* -exec-step [--thread <tid>] [count]
*
* Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached, if the
@ -29,10 +30,23 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecStep extends MICommand<MIInfo>
{
public MIExecStep(IExecutionDMContext dmc) {
super(dmc, "-exec-step"); //$NON-NLS-1$
this(dmc, 1);
}
public MIExecStep(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
public MIExecStep(IMIExecutionDMContext dmc, boolean setThread) {
this(dmc, setThread, 1);
}
public MIExecStep(IMIExecutionDMContext dmc, boolean setThread, int count) {
super(dmc, "-exec-step"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()), Integer.toString(count) }); //$NON-NLS-1$
} else {
setParameters(new String[] { Integer.toString(count) });
}
}
}

View file

@ -13,11 +13,12 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-step-instruction
* -exec-step-instruction [--thread <tid>] [count]
* Asynchronous command. Resumes the inferior which executes one
* machine instruction. The output, once GDB has stopped, will vary
@ -29,10 +30,23 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
public class MIExecStepInstruction extends MICommand<MIInfo>
{
public MIExecStepInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-step-instruction"); //$NON-NLS-1$
this(dmc, 1);
}
public MIExecStepInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$
}
public MIExecStepInstruction(IMIExecutionDMContext dmc, boolean setThread) {
this(dmc, setThread, 1);
}
public MIExecStepInstruction(IMIExecutionDMContext dmc, boolean setThread, int count) {
super(dmc, "-exec-step-instruction"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()), Integer.toString(count) }); //$NON-NLS-1$
} else {
setParameters(new String[] { Integer.toString(count) });
}
}
}

View file

@ -14,11 +14,12 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -exec-until [ LOCATION ]
* -exec-until [--thread <tid>] [ LOCATION ]
*
* Asynchronous command. Executes the inferior until the LOCATION
* specified in the argument is reached. If there is no argument, the
@ -34,6 +35,22 @@ public class MIExecUntil extends MICommand<MIInfo>
}
public MIExecUntil(IExecutionDMContext dmc, String loc) {
super(dmc, "-exec-until", new String[]{loc}); //$NON-NLS-1$
super(dmc, "-exec-until", new String[] { loc }); //$NON-NLS-1$
}
public MIExecUntil(IMIExecutionDMContext dmc, boolean setThread) {
super(dmc, "-exec-until"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()) }); //$NON-NLS-1$
}
}
public MIExecUntil(IMIExecutionDMContext dmc, boolean setThread, String loc) {
super(dmc, "-exec-until"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(dmc.getThreadId()), loc }); //$NON-NLS-1$
} else {
setParameters(new String[] { loc });
}
}
}

View file

@ -17,7 +17,7 @@ import org.eclipse.dd.mi.service.command.output.MIStackInfoDepthInfo;
/**
*
* -stack-info-depth [maxDepth]
* -stack-info-depth [--thread <tid>] [maxDepth]
*
*
*/
@ -25,11 +25,28 @@ public class MIStackInfoDepth extends MICommand<MIStackInfoDepthInfo>
{
public MIStackInfoDepth(IMIExecutionDMContext ctx) {
this(ctx, false);
}
public MIStackInfoDepth(IMIExecutionDMContext ctx, boolean setThread) {
super(ctx, "-stack-info-depth"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(ctx.getThreadId()) }); //$NON-NLS-1$
}
}
public MIStackInfoDepth(IMIExecutionDMContext ctx, int maxDepth) {
super(ctx, "-stack-info-depth", new String[]{Integer.toString(maxDepth)}); //$NON-NLS-1$
this(ctx, false, maxDepth);
}
public MIStackInfoDepth(IMIExecutionDMContext ctx, boolean setThread, int maxDepth) {
super(ctx, "-stack-info-depth"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(ctx.getThreadId()), Integer.toString(maxDepth) }); //$NON-NLS-1$
}
else {
setParameters(new String[] { Integer.toString(maxDepth) });
}
}
@Override

View file

@ -20,7 +20,7 @@ import org.eclipse.dd.mi.service.command.output.MIStackListArgumentsInfo;
/**
*
* -stack-list-arguments SHOW-VALUES
* -stack-list-arguments [--thread <tid>] SHOW-VALUES
* [ LOW-FRAME HIGH-FRAME ]
*
* Display a list of the arguments for the frames between LOW-FRAME and
@ -35,34 +35,35 @@ import org.eclipse.dd.mi.service.command.output.MIStackListArgumentsInfo;
public class MIStackListArguments extends MICommand<MIStackListArgumentsInfo>
{
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues) {
this(execDmc, false, showValues);
}
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean setThread, boolean showValues) {
super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (showValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), showValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
setParameters(new String[] { showValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$
}
}
public MIStackListArguments(IFrameDMContext frameDmc, boolean showValues) {
super(frameDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (showValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
}
super(frameDmc, "-stack-list-arguments", new String[] { showValues ? "1" : "0" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues, int low, int high) {
super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
String[] params = new String[3];
if (showValues) {
params[0] = "1"; //$NON-NLS-1$
} else {
params[0] = "0"; //$NON-NLS-1$
this(execDmc, false, showValues, low, high);
}
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean setThread, boolean showValues, int low, int high) {
super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), //$NON-NLS-1$
showValues ? "1" : "0", Integer.toString(low), Integer.toString(high) } ); //$NON-NLS-1$ //$NON-NLS-2$
} else {
setParameters(new String[] {
showValues ? "1" : "0", Integer.toString(low), Integer.toString(high) } ); //$NON-NLS-1$ //$NON-NLS-2$
}
params[1] = Integer.toString(low);
params[2] = Integer.toString(high);
setParameters(params);
}
@Override

View file

@ -54,12 +54,27 @@ import org.eclipse.dd.mi.service.command.output.MIStackListFramesInfo;
public class MIStackListFrames extends MICommand<MIStackListFramesInfo>
{
public MIStackListFrames(IMIExecutionDMContext execDmc) {
this(execDmc, false);
}
public MIStackListFrames(IMIExecutionDMContext execDmc, boolean setThread) {
super(execDmc, "-stack-list-frames"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()) } ); //$NON-NLS-1$
}
}
public MIStackListFrames(IMIExecutionDMContext execDmc, int low, int high) {
super(execDmc, "-stack-list-frames", new String[]{Integer.toString(low), //$NON-NLS-1$
Integer.toString(high)});
this(execDmc, false, low, high);
}
public MIStackListFrames(IMIExecutionDMContext execDmc, boolean setThread, int low, int high) {
super(execDmc, "-stack-list-frames"); //$NON-NLS-1$
if (setThread) {
setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), Integer.toString(low), Integer.toString(high) } ); //$NON-NLS-1$
} else {
setParameters(new String[] { Integer.toString(low), Integer.toString(high) } );
}
}
@Override

View file

@ -13,7 +13,9 @@
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
@ -30,11 +32,16 @@ public class MIStackListLocals extends MICommand<MIStackListLocalsInfo>
{
public MIStackListLocals(IFrameDMContext frameCtx, boolean printValues) {
this(frameCtx, false, printValues);
}
public MIStackListLocals(IFrameDMContext frameCtx, boolean setThread, boolean printValues) {
super(frameCtx, "-stack-list-locals"); //$NON-NLS-1$
if (printValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(frameCtx, IMIExecutionDMContext.class);
if (setThread && execDmc != null) {
setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), printValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
setParameters(new String[] { printValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -15,8 +15,6 @@ package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo;
/**
*
* -stack-select-frame FRAMENUM
@ -30,4 +28,8 @@ public class MIStackSelectFrame extends MICommand<MIInfo> {
public MIStackSelectFrame(IDMContext ctx, int frameNum) {
super(ctx, "-stack-select-frame", new String[]{Integer.toString(frameNum)}, new String[0]); //$NON-NLS-1$
}
public MIStackSelectFrame(IDMContext ctx, int threadNum, int frameNum) {
super(ctx, "-stack-select-frame", new String[]{ "--thread", Integer.toString(threadNum), Integer.toString(frameNum) }); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software 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:
* QNX Software Systems - Initial API and implementation
* Ericsson - Modified for new DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
/**
*
* -thread-info [ thread-id ]
*
* Reports information about either a specific thread, if [thread-id] is present,
* or about all threads. When printing information about all threads, also reports
* the current thread.
*
*/
public class MIThreadInfo extends MICommand<MIThreadInfoInfo> {
public MIThreadInfo(IContainerDMContext dmc) {
super(dmc, "-thread-info"); //$NON-NLS-1$
}
public MIThreadInfo(IContainerDMContext dmc, int threadId) {
super(dmc, "-thread-info", new String[]{ Integer.toString(threadId) }); //$NON-NLS-1$
}
@Override
public MIThreadInfoInfo getResult(MIOutput out) {
return new MIThreadInfoInfo(out);
}
}

View file

@ -53,7 +53,7 @@ public class MIVarCreate extends MICommand<MIVarCreateInfo>
this(dmc, "-", "*", expression); //$NON-NLS-1$ //$NON-NLS-2$
}
public MIVarCreate(IExpressionDMContext dmc,String name, String expression) {
public MIVarCreate(IExpressionDMContext dmc, String name, String expression) {
this(dmc, name, "*", expression); //$NON-NLS-1$
}

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -40,7 +40,7 @@ public class MIBreakpointHitEvent extends MIStoppedEvent {
}
public static MIBreakpointHitEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
int bkptno = -1;

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -54,7 +54,7 @@ public class MIFunctionFinishedEvent extends MIStoppedEvent {
}
public static MIFunctionFinishedEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
String gdbResult = ""; //$NON-NLS-1$
String returnValue = ""; //$NON-NLS-1$

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -30,7 +30,7 @@ public class MILocationReachedEvent extends MIStoppedEvent {
}
public static MILocationReachedEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MILocationReachedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -30,7 +30,7 @@ public class MISharedLibEvent extends MIStoppedEvent {
}
public static MIStoppedEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -49,7 +49,7 @@ public class MISignalEvent extends MIStoppedEvent {
}
public static MISignalEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
String sigName = ""; //$NON-NLS-1$
String sigMeaning = ""; //$NON-NLS-1$

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -31,7 +31,7 @@ public class MISteppingRangeEvent extends MIStoppedEvent {
}
public static MISteppingRangeEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MISteppingRangeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame());

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -41,7 +41,7 @@ public class MIStoppedEvent extends MIEvent<IExecutionDMContext> {
}
public static MIStoppedEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
int threadId = -1;
MIFrame frame = null;

View file

@ -14,6 +14,9 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
@ -37,4 +40,25 @@ public class MIThreadCreatedEvent extends MIEvent<IContainerDMContext> {
public int getId() {
return tid;
}
public static MIThreadCreatedEvent parse(IContainerDMContext ctx, int token, MIResult[] results)
{
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
try {
int thread = Integer.parseInt(((MIConst) val).getString());
return new MIThreadCreatedEvent(ctx, token, thread);
}
catch (NumberFormatException e) {
return null;
}
}
}
}
return null;
}
}

View file

@ -14,6 +14,9 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIValue;
/**
@ -37,4 +40,25 @@ public class MIThreadExitEvent extends MIEvent<IContainerDMContext> {
public int getId() {
return tid;
}
public static MIThreadExitEvent parse(IContainerDMContext ctx, int token, MIResult[] results)
{
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
try {
int thread = Integer.parseInt(((MIConst) val).getString());
return new MIThreadExitEvent(ctx, token, thread);
}
catch (NumberFormatException e) {
return null;
}
}
}
}
return null;
}
}

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -42,7 +42,7 @@ public class MIWatchpointScopeEvent extends MIStoppedEvent {
}
public static MIWatchpointScopeEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
int number = 0;
for (int i = 0; i < results.length; i++) {

View file

@ -15,7 +15,7 @@ package org.eclipse.dd.mi.service.command.events;
import org.eclipse.dd.dsf.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.mi.service.MIRunControl;
import org.eclipse.dd.mi.service.IMIRunControl;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult;
@ -62,7 +62,7 @@ public class MIWatchpointTriggerEvent extends MIStoppedEvent {
}
public static MIWatchpointTriggerEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{
int number = 0;
String exp = ""; //$NON-NLS-1$

View file

@ -35,7 +35,7 @@ public class CLIInfoThreadsInfo extends MIInfo {
parse();
}
public class ThreadInfo{
public class ThreadInfo {
String fName;
String fGdbId;
String fPid;

View file

@ -0,0 +1,254 @@
/*******************************************************************************
* Copyright (c) 2000, 2006 QNX Software 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:
* QNX Software Systems - Initial API and implementation
* Ericsson AB - Modified for DSF Reference Implementation
*******************************************************************************/
package org.eclipse.dd.mi.service.command.output;
import java.math.BigInteger;
import java.util.List;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.dd.dsf.concurrent.Immutable;
/**
* GDB/MI thread list parsing.
*
* Example 1:
*
* -thread-info
* ^done,threads=[
* {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)",
* frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"},
* running="0"},
* {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)",
* frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"},
* running="0"}
* ],current-thread-id="2"
*
* Example 2:
*
* -thread-info 2
* ^done,threads=[
* {id="2",target-id="Thread 0xb7c8ab90 (LWP 7010)",
* frame={level="0",addr="0x08048bba",func="my_func",args=[{name="arg",value="0xbff056f5"}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="26"},
* running="0"}
* ]
*
*
* Example 3 (non-stop):
*
* -thread-info
* ^done,threads=[
* {id="2",target-id="Thread 0xb7c8eb90 (LWP 7807)",running="1"},
* {id="1",target-id="Thread 0xb7c8b8d0 (LWP 7007)",
* frame={level="0",addr="0x08048a77",func="timer",args=[{name="duration",value="0xbff056f5 \"10\""}],
* file="my_test.cc",fullname="/home/francois/GDB/my_test.cc",line="39"},
* running="0"}
* ],current-thread-id="1"
*/
public class MIThreadInfoInfo extends MIInfo {
@Immutable
public class ThreadInfo {
final private String fGdbId;
final private String fTargetId;
final private String fOsId;
final private ThreadFrame fTopFrame;
final private boolean fIsRunning;
public ThreadInfo(String gdbId, String targetId, String osId, ThreadFrame topFrame, boolean isRunning) {
fGdbId = gdbId;
fTargetId = targetId;
fOsId = osId;
fTopFrame = topFrame;
fIsRunning = isRunning;
}
public String getGdbId() { return fGdbId; }
public String getTargetId() { return fTargetId; }
public String getOsId() { return fOsId; }
public ThreadFrame getTopFrame() { return fTopFrame; }
public boolean isRunning() { return fIsRunning; }
}
@Immutable
public class ThreadFrame {
final private int fStackLevel;
final private BigInteger fAddress;
final private String fFunction;
final private ThreadFrameFunctionArgs[] fArgs;
final private String fFileName;
final private String fFullName;
final private int fLineNumber;
public ThreadFrame(int stackLevel, BigInteger address, String function,
ThreadFrameFunctionArgs[] args, String file, String fullName, int line)
{
fStackLevel = stackLevel;
fAddress = address;
fFunction = function;
fArgs = args;
fFileName = file;
fFullName = fullName;
fLineNumber = line;
}
public int getStackLevel() { return fStackLevel; }
public BigInteger getAddress() { return fAddress; }
public String getFucntion() { return fFunction; }
public ThreadFrameFunctionArgs[] getArgs() { return fArgs; }
public String getFileName() { return fFileName; }
public String getFullName() { return fFullName; }
public int getLineNumber() { return fLineNumber; }
}
@Immutable
public class ThreadFrameFunctionArgs {
}
private int fCurrentThread = -1;
private List<ThreadInfo> fThreadInfoList = null;
private int[] fThreadList = null;
public MIThreadInfoInfo(MIOutput out) {
super(out);
parse();
}
public int getCurrentThread() {
return fCurrentThread;
}
public List<ThreadInfo> getThreadInfoList() {
return fThreadInfoList;
}
public int[] getThreadList() {
return fThreadList;
}
// General format:
// threads=[{...}],current-thread-id="n"
private void parse() {
if (isDone()) {
MIOutput out = getMIOutput();
MIResultRecord rr = out.getMIResultRecord();
if (rr != null) {
MIResult[] results = rr.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
if (var.equals("threads")) { //$NON-NLS-1$
MIValue val = results[i].getMIValue();
if (val instanceof MIList) {
parseThreads((MIList) val);
}
}
else if (var.equals("current-thread-id")) { //$NON-NLS-1$
MIValue value = results[i].getMIValue();
if (value instanceof MIConst) {
String str = ((MIConst) value).getCString();
try {
fCurrentThread = Integer.parseInt(str.trim());
} catch (NumberFormatException e) {
fCurrentThread = -1;
}
}
}
}
}
}
if (fThreadInfoList == null) {
fThreadInfoList = new Vector<ThreadInfo>(0);
fThreadList = new int[0];
}
}
// General formats:
// id="n",target-id="Thread 0xb7c8ab90 (LWP 7010)",frame={...},running="0"
// id="n",target-id="Thread 0xb7c8eb90 (LWP 7807)",running="1"
private void parseThreads(MIList list) {
MIValue[] values = list.getMIValues();
fThreadInfoList = new Vector<ThreadInfo>(values.length);
fThreadList = new int[values.length];
for (int i = 0; i < values.length; i++) {
MITuple value = (MITuple) values[i];
MIResult[] results = value.getMIResults();
String gdbId = null;
String targetId = null;
String osId = null;
ThreadFrame topFrame = null;
boolean isRunning = false;
for (int j = 0; j < results.length; j++) {
MIResult result = results[j];
String var = result.getVariable();
if (var.equals("id")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue();
if (val instanceof MIConst) {
gdbId = ((MIConst) val).getCString();
}
}
else if (var.equals("target-id")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue();
if (val instanceof MIConst) {
targetId = ((MIConst) val).getCString();
osId = parseOsId(targetId);
}
}
else if (var.equals("frame")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue();
topFrame = parseFrame(val);
}
else if (var.equals("running")) { //$NON-NLS-1$
MIValue val = results[j].getMIValue();
if (val instanceof MIConst) {
String v = ((MIConst) val).getCString();
isRunning = v.equals("1"); //$NON-NLS-1$
}
}
}
fThreadInfoList.add(new ThreadInfo(gdbId, targetId, osId, topFrame, isRunning));
try {
fThreadList[i] = Integer.parseInt(gdbId);
} catch (NumberFormatException e) {
}
}
}
// General format:
// "Thread 0xb7c8ab90 (LWP 7010)"
private String parseOsId(String str) {
Pattern pattern = Pattern.compile("(Thread\\s*)(0x[0-9a-fA-F]+|-?\\d+)(\\s*\\(LWP\\s*)(\\d*)", 0); //$NON-NLS-1$
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
return matcher.group(4);
}
return null;
}
// General format:
// level="0",addr="0x08048bba",func="func",args=[...],file="file.cc",fullname="/path/file.cc",line="26"
private ThreadFrame parseFrame(MIValue val) {
// TODO Auto-generated method stub
return null;
}
}

View file

@ -26,7 +26,8 @@ import org.junit.runners.Suite;
MIRunControlTest.class,
ExpressionServiceTest.class,
MIMemoryTest.class,
MIBreakpointsTest.class
MIBreakpointsTest.class,
MIDisassemblyTest.class,
/* Add your test class here */
})

View file

@ -24,8 +24,8 @@ import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBThreadData;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
@ -91,8 +91,8 @@ public class GDBProcessesTest extends BaseTestCase {
/*
* Create a request monitor
*/
final DataRequestMonitor<GDBProcessData> rm =
new DataRequestMonitor<GDBProcessData>(fSession.getExecutor(), null) {
final DataRequestMonitor<IGDBProcessData> rm =
new DataRequestMonitor<IGDBProcessData>(fSession.getExecutor(), null) {
@Override
protected void handleCompleted() {
if (isSuccess()) {
@ -123,7 +123,7 @@ public class GDBProcessesTest extends BaseTestCase {
/*
* Get process data
*/
GDBProcessData processData = rm.getData();
IGDBProcessData processData = rm.getData();
if(processData == null)
Assert.fail("No process data is returned for Process DMC");
@ -141,8 +141,8 @@ public class GDBProcessesTest extends BaseTestCase {
*/
@Test
public void getThreadData() throws InterruptedException{
final DataRequestMonitor<GDBThreadData> rm =
new DataRequestMonitor<GDBThreadData>(fSession.getExecutor(), null) {
final DataRequestMonitor<IGDBThreadData> rm =
new DataRequestMonitor<IGDBThreadData>(fSession.getExecutor(), null) {
@Override
protected void handleCompleted() {
if (isSuccess()) {
@ -166,7 +166,7 @@ public class GDBProcessesTest extends BaseTestCase {
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
assertTrue(fWait.getMessage(), fWait.isOK());
GDBThreadData threadData = rm.getData();
IGDBThreadData threadData = rm.getData();
if(threadData == null)
fail("Thread data not returned for thread id = " + fExecDmc.getThreadId());
else{