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

View file

@ -37,7 +37,7 @@ public interface IRunControl extends IDMService
/** /**
* Context representing a process, kernel, or some other logical container * 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. * 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.dsf.service.DsfSession;
import org.eclipse.dd.gdb.internal.provisional.breakpoints.CBreakpointGdbThreadsFilterExtension; 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.launching.GdbLaunch;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl; import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData; 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.provisional.service.command.GDBControl;
import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin; import org.eclipse.dd.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.dd.mi.service.IMIExecutionDMContext; import org.eclipse.dd.mi.service.IMIExecutionDMContext;
@ -493,12 +493,12 @@ public class GdbThreadFilterEditor {
return; return;
} }
ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), GDBRunControl.class ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IGDBRunControl.class
.getName(), null); .getName(), null);
tracker.open(); tracker.open();
GDBRunControl runControl = (GDBRunControl) tracker.getService(); IGDBRunControl runControl = (IGDBRunControl) tracker.getService();
if (runControl != null) { if (runControl != null) {
runControl.getThreadData((IMIExecutionDMContext) thread, new DataRequestMonitor<GDBThreadData>( runControl.getThreadData((IMIExecutionDMContext) thread, new DataRequestMonitor<IGDBThreadData>(
ImmediateExecutor.getInstance(), rm) { ImmediateExecutor.getInstance(), rm) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {

View file

@ -45,6 +45,7 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
protected TabFolder fTabFolder; protected TabFolder fTabFolder;
protected Text fGDBCommandText; protected Text fGDBCommandText;
protected Text fGDBInitText; protected Text fGDBInitText;
protected Button fNonStopCheckBox;
private IMILaunchConfigurationComponent fSolibBlock; private IMILaunchConfigurationComponent fSolibBlock;
private boolean fIsInitializing = false; private boolean fIsInitializing = false;
@ -64,6 +65,9 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT); IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT); IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
if (fSolibBlock != null) if (fSolibBlock != null)
fSolibBlock.setDefaults(configuration); fSolibBlock.setDefaults(configuration);
} }
@ -86,6 +90,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
setInitializing(true); setInitializing(true);
String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT; String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT;
String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT; String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT;
boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT;
try { try {
gdbCommand = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME, gdbCommand = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT); IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
@ -99,10 +105,18 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
catch(CoreException e) { catch(CoreException e) {
} }
try {
nonStopMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
}
catch(CoreException e) {
}
if (fSolibBlock != null) if (fSolibBlock != null)
fSolibBlock.initializeFrom(configuration); fSolibBlock.initializeFrom(configuration);
fGDBCommandText.setText(gdbCommand); fGDBCommandText.setText(gdbCommand);
fGDBInitText.setText(gdbInit); fGDBInitText.setText(gdbInit);
fNonStopCheckBox.setSelection(nonStopMode);
setInitializing(false); setInitializing(false);
} }
@ -112,6 +126,8 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
fGDBCommandText.getText().trim()); fGDBCommandText.getText().trim());
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT, configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
fGDBInitText.getText().trim()); fGDBInitText.getText().trim());
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
fNonStopCheckBox.getSelection());
if (fSolibBlock != null) if (fSolibBlock != null)
fSolibBlock.performApply(configuration); fSolibBlock.performApply(configuration);
@ -242,8 +258,23 @@ public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
fGDBInitText.setText(res); 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$ label = ControlFactory.createLabel(subComp, LaunchUIMessages.getString("GDBDebuggerPage.9"), //$NON-NLS-1$
200, SWT.DEFAULT, SWT.WRAP); 200, SWT.DEFAULT, SWT.WRAP);
gd = new GridData(GridData.FILL_HORIZONTAL); gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 3; gd.horizontalSpan = 3;
gd.widthHint = 200; 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.10=Shared Libraries
GDBDebuggerPage.11=Protocol: GDBDebuggerPage.11=Protocol:
GDBDebuggerPage.12=Default GDBDebuggerPage.12=Default
GDBDebuggerPage.13=Non-stop mode (Note: Requires non-stop GDB)
StandardGDBDebuggerPage.0=Debugger executable must be specified. StandardGDBDebuggerPage.0=Debugger executable must be specified.
StandardGDBDebuggerPage.1=GDB Debugger Options StandardGDBDebuggerPage.1=GDB Debugger Options
StandardGDBDebuggerPage.2=Main 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.VMDelta;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext; 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.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBProcessData; 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.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.command.MIInferiorProcess; import org.eclipse.dd.mi.service.command.MIInferiorProcess;
@ -72,7 +72,7 @@ public class ContainerVMNode extends AbstractContainerVMNode
@Override @Override
protected void updateLabelInSessionThread(final ILabelUpdate update) { protected void updateLabelInSessionThread(final ILabelUpdate update) {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class); final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) { if ( runControl == null ) {
handleFailedUpdate(update); handleFailedUpdate(update);
return; return;
@ -90,7 +90,7 @@ public class ContainerVMNode extends AbstractContainerVMNode
runControl.getProcessData( runControl.getProcessData(
dmc, dmc,
new ViewerDataRequestMonitor<GDBProcessData>(getExecutor(), update) { new ViewerDataRequestMonitor<IGDBProcessData>(getExecutor(), update) {
@Override @Override
public void handleCompleted() { public void handleCompleted() {
if (!isSuccess()) { if (!isSuccess()) {
@ -151,11 +151,11 @@ public class ContainerVMNode extends AbstractContainerVMNode
try { try {
getSession().getExecutor().execute(new DsfRunnable() { getSession().getExecutor().execute(new DsfRunnable() {
public void run() { public void run() {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class); final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) { if ( runControl != null ) {
runControl.getProcessData( runControl.getProcessData(
procDmc, procDmc,
new ViewerDataRequestMonitor<GDBProcessData>(runControl.getExecutor(), request) { new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
if ( getStatus().isOK() ) { if ( getStatus().isOK() ) {
@ -203,11 +203,11 @@ public class ContainerVMNode extends AbstractContainerVMNode
try { try {
getSession().getExecutor().execute(new DsfRunnable() { getSession().getExecutor().execute(new DsfRunnable() {
public void run() { public void run() {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class); final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl != null ) { if ( runControl != null ) {
runControl.getProcessData( runControl.getProcessData(
procDmc, procDmc,
new ViewerDataRequestMonitor<GDBProcessData>(runControl.getExecutor(), request) { new ViewerDataRequestMonitor<IGDBProcessData>(runControl.getExecutor(), request) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
if ( getStatus().isOK() ) { 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.concurrent.ViewerDataRequestMonitor;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.dd.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.datamodel.IDMVMContext; 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.IGDBRunControl;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData; import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBThreadData;
import org.eclipse.dd.mi.service.IMIExecutionDMContext; 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.IElementCompareRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
@ -49,7 +49,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
@Override @Override
protected void updateLabelInSessionThread(ILabelUpdate[] updates) { protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
for (final ILabelUpdate update : updates) { for (final ILabelUpdate update : updates) {
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class); final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) { if ( runControl == null ) {
handleFailedUpdate(update); handleFailedUpdate(update);
continue; continue;
@ -78,7 +78,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
// We're in a new dispatch cycle, and we have to check whether the // We're in a new dispatch cycle, and we have to check whether the
// service reference is still valid. // service reference is still valid.
final GDBRunControl runControl = getServicesTracker().getService(GDBRunControl.class); final IGDBRunControl runControl = getServicesTracker().getService(IGDBRunControl.class);
if ( runControl == null ) { if ( runControl == null ) {
handleFailedUpdate(update); handleFailedUpdate(update);
return; return;
@ -89,7 +89,7 @@ public class ThreadVMNode extends AbstractThreadVMNode
// Retrieve the rest of the thread information // Retrieve the rest of the thread information
runControl.getThreadData( runControl.getThreadData(
dmc, dmc,
new ViewerDataRequestMonitor<GDBThreadData>(getSession().getExecutor(), update) { new ViewerDataRequestMonitor<IGDBThreadData>(getSession().getExecutor(), update) {
@Override @Override
public void handleCompleted() { public void handleCompleted() {
if (!isSuccess()) { 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$ 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. * 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$ 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. * 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.GdbPlugin;
import org.eclipse.dd.gdb.internal.provisional.IGDBLaunchConfigurationConstants; 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.GdbDebugServicesFactory;
import org.eclipse.dd.gdb.internal.provisional.service.GdbDebugServicesFactoryNS;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType;
import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunch;
@ -56,7 +57,9 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
{ {
public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$ public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException { private boolean isNonStopSession = false;
public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
if ( monitor == null ) { if ( monitor == null ) {
monitor = new NullProgressMonitor(); monitor = new NullProgressMonitor();
} }
@ -167,6 +170,16 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
return SessionType.LOCAL; 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) { private boolean getIsAttach(ILaunchConfiguration config) {
try { try {
String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ); 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 adapters will be created for the whole session, including
// the source lookup adapter. // the source lookup adapter.
isNonStopSession = isNonStopSession(configuration);
GdbLaunch launch = new GdbLaunch(configuration, mode, null); GdbLaunch launch = new GdbLaunch(configuration, mode, null);
launch.initialize(); launch.initialize();
launch.setSourceLocator(getSourceLocator(configuration, launch.getSession())); launch.setSourceLocator(getSourceLocator(configuration, launch.getSession()));
@ -314,6 +329,12 @@ public class GdbLaunchDelegate extends LaunchConfigurationDelegate
} }
private IDsfDebugServicesFactory newServiceFactory(String version) { 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$ if (version.startsWith("6.6") || //$NON-NLS-1$
version.startsWith("6.7") || //$NON-NLS-1$ version.startsWith("6.7") || //$NON-NLS-1$
version.startsWith("6.8")) { //$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.GDBControl;
import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControlDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext; 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.MIRunControl;
import org.eclipse.dd.mi.service.command.commands.CLIInfoThreads; 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.MIEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent; import org.eclipse.dd.mi.service.command.events.MIThreadExitEvent;
import org.eclipse.dd.mi.service.command.output.CLIInfoThreadsInfo; 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 * Implement a custom execution data for threads in order to provide additional
* information. This object can be made separate from IExecutionDMData after * information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used. * 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 fId;
private final String fName; private final String fName;
@ -63,7 +65,7 @@ public class GDBRunControl extends MIRunControl {
* information. This object can be made separate from IExecutionDMData after * information. This object can be made separate from IExecutionDMData after
* the deprecated method: IDMService.getModelData() is no longer used. * the deprecated method: IDMService.getModelData() is no longer used.
*/ */
public static class GDBProcessData { public static class GDBProcessData implements IGDBProcessData {
private final String fName; private final String fName;
GDBProcessData(String name) { GDBProcessData(String name) {
@ -74,7 +76,7 @@ public class GDBRunControl extends MIRunControl {
return fName; return fName;
} }
} }
private GDBControl fGdb; private GDBControl fGdb;
// Record list of execution contexts // Record list of execution contexts
@ -98,8 +100,9 @@ public class GDBRunControl extends MIRunControl {
private void doInitialize(final RequestMonitor requestMonitor) { private void doInitialize(final RequestMonitor requestMonitor) {
fGdb = getServicesTracker().getService(GDBControl.class); 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(); requestMonitor.done();
} }
@ -149,12 +152,12 @@ public class GDBRunControl extends MIRunControl {
super.getExecutionContexts(c, rm1); 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.setData( new GDBProcessData(fGdb.getExecutablePath().lastSegment()) );
rm.done(); 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); IContainerDMContext containerDmc = DMContexts.getAncestorOfType(execDmc, IContainerDMContext.class);
assert containerDmc != null; // Every exec context should have a container as an ancestor. assert containerDmc != null; // Every exec context should have a container as an ancestor.
getCache().execute(new CLIInfoThreads(containerDmc), 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()}. * More strongly typed version of {@link #getControlDMContext()}.
*/ */
public GDBControlDMContext getGDBDMContext() { public GDBControlDMContext getGDBDMContext() {
return (GDBControlDMContext)getControlDMContext(); return (GDBControlDMContext) getControlDMContext();
} }
public SessionType getSessionType() { public SessionType getSessionType() {

View file

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

View file

@ -893,7 +893,6 @@ public class ExpressionService extends AbstractDsfService implements IExpression
} }
} }
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) { public void eventDispatched(IRunControl.IResumedDMEvent e) {
fExpressionCache.setContextAvailable(e.getDMContext(), false); 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.BreakpointRemovedEvent;
import org.eclipse.dd.mi.service.MIBreakpoints.BreakpointUpdatedEvent; import org.eclipse.dd.mi.service.MIBreakpoints.BreakpointUpdatedEvent;
import org.eclipse.dd.mi.service.MIBreakpoints.MIBreakpointDMContext; 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.breakpoint.actions.BreakpointActionAdapter;
import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent; import org.eclipse.dd.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.dd.mi.service.command.events.MIGDBExitEvent; 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>(); Set<String> results = new HashSet<String>();
if ((threads != null) && (supportsThreads(breakpoint))) { if ((threads != null) && (supportsThreads(breakpoint))) {
for (IExecutionDMContext thread : threads) { for (IExecutionDMContext thread : threads) {
if (thread instanceof MIExecutionDMC) { if (thread instanceof IMIExecutionDMContext) {
MIExecutionDMC dmc = (MIExecutionDMC) thread; IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
results.add(((Integer) dmc.getThreadId()).toString()); 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; private MIMemoryCache fMemoryCache;
/** /**
@ -113,9 +111,6 @@ public class MIMemory extends AbstractDsfService implements IMemory {
// Register this service // Register this service
register(new String[] { MIMemory.class.getName(), IMemory.class.getName() }, new Hashtable<String, String>()); 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 // Create the memory requests cache
fMemoryCache = new MIMemoryCache(); fMemoryCache = new MIMemoryCache();
@ -279,7 +274,7 @@ public class MIMemory extends AbstractDsfService implements IMemory {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) { public void eventDispatched(IRunControl.IContainerResumedDMEvent e) {
fMemoryCache.setTargetAvailable(e.getDMContext(), false); fMemoryCache.setTargetAvailable(e.getDMContext(), false);
if (e.getReason() != StateChangeReason.STEP) { if (e.getReason() != StateChangeReason.STEP) {
fMemoryCache.reset(); fMemoryCache.reset();
@ -287,7 +282,7 @@ public class MIMemory extends AbstractDsfService implements IMemory {
} }
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) { public void eventDispatched(IRunControl.IContainerSuspendedDMEvent e) {
fMemoryCache.setTargetAvailable(e.getDMContext(), true); fMemoryCache.setTargetAvailable(e.getDMContext(), true);
fMemoryCache.reset(); 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.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent; 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.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache; import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.service.AbstractDsfService; import org.eclipse.dd.dsf.service.AbstractDsfService;
@ -71,197 +70,212 @@ import org.osgi.framework.BundleContext;
* events and track service state, to be perfectly in sync with the service * events and track service state, to be perfectly in sync with the service
* state. * state.
*/ */
public class MIRunControl extends AbstractDsfService implements IRunControl public class MIRunControl extends AbstractDsfService implements IMIRunControl
{ {
protected class MIExecutionDMC extends AbstractDMContext class MIExecutionDMC extends AbstractDMContext implements IMIExecutionDMContext
implements IMIExecutionDMContext {
{ /**
/** * Integer ID that is used to identify the thread in the GDB/MI protocol.
* Integer ID that is used to identify the thread in the GDB/MI protocol. */
*/ private final int fThreadId;
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 MIExecutionDMC(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) && ((MIExecutionDMC)obj).fThreadId == fThreadId;
}
@Override
public int hashCode() { return super.baseHashCode() ^ fThreadId; }
}
@Immutable
private 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 * Constructor for the context. It should not be called directly by clients.
* generated by the MI Run Control service are directly caused by some MI event. * Instead clients should call {@link MIRunControl#createMIExecutionContext(IContainerDMContext, int)}
* Other services may need access to the extended MI data carried in the event. * to create instances of this context based on the thread ID.
* * <p/>
* @param <V> DMC that this event refers to * Classes extending {@link MIRunControl} may also extend this class to include
* @param <T> MIInfo object that is the direct cause of this event * additional information in the context.
* @see MIRunControl *
*/ * @param sessionId Session that this context belongs to.
@Immutable * @param containerDmc The container that this context belongs to.
protected static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V> * @param threadId GDB/MI thread identifier.
implements IDMEvent<V>, IMIDMEvent */
{ protected MIExecutionDMC(String sessionId, IContainerDMContext containerDmc, int threadId) {
final private T fMIInfo; super(sessionId, containerDmc != null ? new IDMContext[] { containerDmc } : new IDMContext[0]);
public RunControlEvent(V dmc, T miInfo) { fThreadId = threadId;
super(dmc); }
fMIInfo = miInfo;
}
public T getMIEvent() { return fMIInfo; }
}
/**
* Indicates that the given thread has been suspended.
*/
@Immutable
protected 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 /**
protected static class ContainerSuspendedEvent extends SuspendedEvent * Returns the GDB/MI thread identifier of this context.
implements IContainerSuspendedDMEvent * @return
{ */
final IExecutionDMContext[] triggeringDmcs; public int getThreadId(){
ContainerSuspendedEvent(IContainerDMContext containerDmc, MIStoppedEvent miInfo, IExecutionDMContext triggeringDmc) { return fThreadId;
super(containerDmc, miInfo); }
this.triggeringDmcs = triggeringDmc != null
? new IExecutionDMContext[] { triggeringDmc } : new IExecutionDMContext[0];
}
public IExecutionDMContext[] getTriggeringContexts() {
return triggeringDmcs;
}
}
@Immutable @Override
protected static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent> public String toString() { return baseToString() + ".thread[" + fThreadId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
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 @Override
protected static class ContainerResumedEvent extends ResumedEvent public boolean equals(Object obj) {
implements IContainerResumedDMEvent return super.baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId == fThreadId;
{ }
final IExecutionDMContext[] triggeringDmcs;
ContainerResumedEvent(IContainerDMContext containerDmc, MIRunningEvent miInfo, IExecutionDMContext triggeringDmc) { @Override
super(containerDmc, miInfo); public int hashCode() { return super.baseHashCode() ^ fThreadId; }
this.triggeringDmcs = triggeringDmc != null }
? new IExecutionDMContext[] { triggeringDmc } : new IExecutionDMContext[0];
} @Immutable
static class ExecutionData implements IExecutionDMData {
public IExecutionDMContext[] getTriggeringContexts() { private final StateChangeReason fReason;
return triggeringDmcs; ExecutionData(StateChangeReason reason) {
} fReason = reason;
} }
public StateChangeReason getStateChangeReason() { return fReason; }
@Immutable }
protected static class StartedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadCreatedEvent>
implements IStartedDMEvent /**
{ * Base class for events generated by the MI Run Control service. Most events
StartedDMEvent(IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) { * generated by the MI Run Control service are directly caused by some MI event.
super(executionDmc, miInfo); * 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
@Immutable * @see MIRunControl
protected static class ExitedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadExitEvent> */
implements IExitedDMEvent @Immutable
{ static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
ExitedDMEvent(IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) { implements IDMEvent<V>, IMIDMEvent
super(executionDmc, miInfo); {
} final private T fMIInfo;
} public RunControlEvent(V dmc, T miInfo) {
super(dmc);
private AbstractMIControl fConnection; 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);
}
}
private AbstractMIControl fConnection;
private CommandCache fMICommandCache; private CommandCache fMICommandCache;
// state flags // State flags
private boolean fSuspended = true; private boolean fSuspended = true;
private boolean fResumePending = false; private boolean fResumePending = false;
private boolean fStepping = false; private boolean fStepping = false;
@ -291,9 +305,6 @@ public class MIRunControl extends AbstractDsfService implements IRunControl
fMICommandCache = new CommandCache(getSession(), fConnection); fMICommandCache = new CommandCache(getSession(), fConnection);
fMICommandCache.setContextAvailable(fConnection.getControlDMContext(), true); fMICommandCache.setContextAvailable(fConnection.getControlDMContext(), true);
getSession().addServiceEventListener(this, null); getSession().addServiceEventListener(this, null);
//register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName()}, new Hashtable<String,String>());
rm.done(); 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.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable; import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.datamodel.DMContexts; 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.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.command.ICommand; import org.eclipse.dd.dsf.debug.service.command.ICommand;
import org.eclipse.dd.dsf.debug.service.command.ICommandControl; import org.eclipse.dd.dsf.debug.service.command.ICommandControl;
@ -74,7 +76,7 @@ public abstract class AbstractMIControl extends AbstractDsfService
private RxThread fRxThread; private RxThread fRxThread;
private int fCurrentStackLevel = -1; private int fCurrentStackLevel = -1;
private int fCurrentThreadId = -1; private int fCurrentThreadId = -1;
private final BlockingQueue<CommandHandle> fTxCommands = new LinkedBlockingQueue<CommandHandle>(); private final BlockingQueue<CommandHandle> fTxCommands = new LinkedBlockingQueue<CommandHandle>();
@ -85,7 +87,6 @@ public abstract class AbstractMIControl extends AbstractDsfService
* that the TX thread should shut down. * that the TX thread should shut down.
*/ */
private final CommandHandle fTerminatorHandle = new CommandHandle(null, null); private final CommandHandle fTerminatorHandle = new CommandHandle(null, null);
/* /*
* Various listener control variables used to keep track of listeners who want to monitor * Various listener control variables used to keep track of listeners who want to monitor
@ -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 // 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. // against an erased type so it should never throw any exceptions.
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>)rm; DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>) rm;
final CommandHandle handle = new CommandHandle(miCommand, miDone); final CommandHandle handle = new CommandHandle(miCommand, miDone);
@ -240,38 +241,43 @@ public abstract class AbstractMIControl extends AbstractDsfService
} }
private void processNextQueuedCommand() { private void processNextQueuedCommand() {
if ( fCommandQueue.size() > 0 ) { if (fCommandQueue.size() > 0) {
CommandHandle handle = fCommandQueue.remove(0); final CommandHandle handle = fCommandQueue.remove(0);
if ( handle != null ) { if (handle != null) {
processCommandSent(handle); processCommandSent(handle);
// Before the command is sent, Check the Thread Id and send it to // Identify target thread/frame (we might have to update them at the target)
// the queue only if the id has been changed. final IDMContext targetContext = handle.fCommand.getContext();
if( handle.getThreadId()!= null && final int targetThread = (handle.getThreadId() != null) ? handle.getThreadId().intValue() : -1;
handle.getThreadId().intValue() != fCurrentThreadId && handle.getThreadId().intValue() != 0) final int targetFrame = (handle.getStackFrameId() != null) ? handle.getStackFrameId().intValue() : -1;
{
// Re-set the level
fCurrentThreadId = handle.getThreadId().intValue();
CommandHandle cmdHandle = new CommandHandle(
new MIThreadSelect(handle.fCommand.getContext(), fCurrentThreadId), null);
cmdHandle.generateTokenId();
fTxCommands.add(cmdHandle);
}
// Before the command is sent, Check the Stack level and send it to // The thread-select and frame-select make sense only if the thread is stopped.
// the queue only if the level has been changed. // Some non-stop commands don't require the thread to be stopped so we send the
if( handle.getStackFrameId()!= null && // command anyway.
handle.getStackFrameId().intValue() != fCurrentStackLevel) IRunControl runControl = getServicesTracker().getService(IRunControl.class);
{ IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(targetContext, IMIExecutionDMContext.class);
// Re-set the level if (runControl != null && execDmc != null && runControl.isSuspended(execDmc)) {
fCurrentStackLevel = handle.getStackFrameId().intValue(); // Before the command is sent, Check the Thread Id and send it to
CommandHandle cmdHandle = new CommandHandle( // the queue only if the id has been changed.
new MIStackSelectFrame(handle.fCommand.getContext(), fCurrentStackLevel), null); if (targetThread != -1 && targetThread != fCurrentThreadId) {
cmdHandle.generateTokenId(); fCurrentThreadId = targetThread;
fTxCommands.add(cmdHandle); 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 (targetFrame != -1 && targetFrame != fCurrentStackLevel) {
fCurrentStackLevel = targetFrame;
CommandHandle cmdHandle = new CommandHandle(new MIStackSelectFrame(execDmc, targetFrame), null);
cmdHandle.generateTokenId();
fTxCommands.add(cmdHandle);
}
} }
handle.generateTokenId(); handle.generateTokenId();
fTxCommands.add(handle); fTxCommands.add(handle);
} }
} }
} }

View file

@ -57,7 +57,6 @@ public class CLIEventProcessor
// Last Thread ID created // Last Thread ID created
private static int fLastThreadId; private static int fLastThreadId;
public CLIEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc, MIInferiorProcess inferior) { public CLIEventProcessor(AbstractMIControl connection, IContainerDMContext containerDmc, MIInferiorProcess inferior) {
fCommandControl = connection; fCommandControl = connection;
fInferior = inferior; fInferior = inferior;
@ -109,32 +108,16 @@ public class CLIEventProcessor
fEventList.add(oobr); fEventList.add(oobr);
if (oobr instanceof MIConsoleStreamOutput) { if (oobr instanceof MIConsoleStreamOutput) {
// Process Events of type DsfMIConsoleStreamOutput here // Process Events of type DsfMIConsoleStreamOutput here
MIConsoleStreamOutput exec = (MIConsoleStreamOutput) oobr; MIConsoleStreamOutput exec = (MIConsoleStreamOutput) oobr;
// Look for events with Pattern ^[New Thread 1077300144 (LWP 7973) // Look for events with Pattern ^[New Thread 1077300144 (LWP 7973)
Pattern pattern = Pattern.compile("(^\\[New Thread.*LWP\\s*)(\\d*)", Pattern.MULTILINE); //$NON-NLS-1$ Pattern pattern = Pattern.compile("(^\\[New Thread.*LWP\\s*)(\\d*)", Pattern.MULTILINE); //$NON-NLS-1$
Matcher matcher = pattern.matcher(exec.getCString()); Matcher matcher = pattern.matcher(exec.getCString());
if (matcher.find()) { if (matcher.find()) {
//fMapThreadIds.put(matcher.group(2), Integer.valueOf(++fLastThreadId)); MIEvent<?> e = new MIThreadCreatedEvent(fContainerDmc, ++fLastThreadId);
//DsfMIEvent e = new DsfMIThreadCreatedEvent(Integer.valueOf(matcher.group(2))); fCommandControl.getSession().dispatchEvent(e, fCommandControl.getProperties());
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.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.service.DsfServicesTracker; import org.eclipse.dd.dsf.service.DsfServicesTracker;
import org.eclipse.dd.mi.internal.MIPlugin; 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.MIExecContinue;
import org.eclipse.dd.mi.service.command.commands.MIExecFinish; import org.eclipse.dd.mi.service.command.commands.MIExecFinish;
import org.eclipse.dd.mi.service.command.commands.MIExecNext; 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.MISignalEvent;
import org.eclipse.dd.mi.service.command.events.MISteppingRangeEvent; 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.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.MIWatchpointScopeEvent;
import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent; import org.eclipse.dd.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.dd.mi.service.command.output.MIConst; 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.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResult; 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.MIResultRecord;
import org.eclipse.dd.mi.service.command.output.MIStatusAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIValue; import org.eclipse.dd.mi.service.command.output.MIValue;
/** /**
@ -102,57 +104,95 @@ public class MIRunControlEventProcessor
} }
public void eventReceived(Object output) { public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) { for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
if (oobr instanceof MIExecAsyncOutput) { List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr; if (oobr instanceof MIExecAsyncOutput) {
// Change of state. MIExecAsyncOutput exec = (MIExecAsyncOutput) oobr;
String state = exec.getAsyncClass(); // Change of state.
if ("stopped".equals(state)) { //$NON-NLS-1$ String state = exec.getAsyncClass();
// Re-set the thread and stack level to -1 when stopped event is recvd. if ("stopped".equals(state)) { //$NON-NLS-1$
// This is to synchronize the state between GDB back-end and AbstractMIControl. // Re-set the thread and stack level to -1 when stopped event is recvd.
fCommandControl.resetCurrentThreadLevel(); // This is to synchronize the state between GDB back-end and AbstractMIControl.
fCommandControl.resetCurrentStackLevel(); fCommandControl.resetCurrentThreadLevel();
fCommandControl.resetCurrentStackLevel();
List<MIEvent<?>> events = new LinkedList<MIEvent<?>>();
MIResult[] results = exec.getMIResults(); MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) { for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable(); String var = results[i].getVariable();
MIValue val = results[i].getMIValue(); MIValue val = results[i].getMIValue();
if (var.equals("reason")) { //$NON-NLS-1$ if (var.equals("reason")) { //$NON-NLS-1$
if (val instanceof MIConst) { if (val instanceof MIConst) {
String reason = ((MIConst) val).getString(); String reason = ((MIConst) val).getString();
MIEvent<?> e = createEvent(reason, exec); MIEvent<?> e = createEvent(reason, exec);
if (e != null) { if (e != null) {
events.add(e); events.add(e);
continue; continue;
} }
} }
} }
} }
// We were stopped for some unknown reason, for example
// We were stopped for some unknown reason, for example // GDB for temporary breakpoints will not send the
// GDB for temporary breakpoints will not send the // "reason" ??? still fire a stopped event.
// "reason" ??? still fire a stopped event. if (events.isEmpty()) {
if (events.isEmpty()) { MIEvent<?> e = MIStoppedEvent.parse(
MIEvent<?> e = MIStoppedEvent.parse( fServicesTracker.getService(IMIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults());
fServicesTracker.getService(MIRunControl.class), fContainerDmc, exec.getToken(), exec.getMIResults()); events.add(e);
events.add(e); }
}
for (MIEvent<?> event : events) { for (MIEvent<?> event : events) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
} }
} }
} else if ("running".equals(state)) { //$NON-NLS-1$
else if (oobr instanceof MIStatusAsyncOutput) { int token = exec.getToken();
// Nothing done .. but what about +download?? MIResult[] results = exec.getMIResults();
} else if (oobr instanceof MINotifyAsyncOutput) { for (int i = 0; i < results.length; i++) {
// Nothing 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());
}
}
}
}
} }
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) { protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
MIRunControl runControl = fServicesTracker.getService(MIRunControl.class); IMIRunControl runControl = fServicesTracker.getService(IMIRunControl.class);
MIEvent<?> event = null; MIEvent<?> event = null;
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$ if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
event = MIBreakpointHitEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults()); event = MIBreakpointHitEvent.parse(runControl, fContainerDmc, exec.getToken(), exec.getMIResults());
@ -213,7 +253,7 @@ public class MIRunControlEventProcessor
else if (cmd instanceof MIExecFinish) { type = MIRunningEvent.FINISH; } else if (cmd instanceof MIExecFinish) { type = MIRunningEvent.FINISH; }
else if (cmd instanceof MIExecReturn) { type = MIRunningEvent.RETURN; } else if (cmd instanceof MIExecReturn) { type = MIRunningEvent.RETURN; }
else if (cmd instanceof MIExecContinue) { type = MIRunningEvent.CONTINUE; } else if (cmd instanceof MIExecContinue) { type = MIRunningEvent.CONTINUE; }
else { type = MIRunningEvent.CONTINUE; } else { type = MIRunningEvent.CONTINUE; }
fCommandControl.getSession().dispatchEvent( fCommandControl.getSession().dispatchEvent(
new MIRunningEvent(fContainerDmc, id, type), fCommandControl.getProperties()); new MIRunningEvent(fContainerDmc, id, type), fCommandControl.getProperties());

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 * Asynchronous command. Resumes the execution of the inferior program
* until a breakpoint is encountered, or until the inferior exits. * 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 class MIExecContinue extends MICommand<MIInfo>
{ {
public MIExecContinue(IExecutionDMContext dmc) { public MIExecContinue(IExecutionDMContext dmc) {
this(dmc, false);
}
public MIExecContinue(IExecutionDMContext dmc, boolean allThreads) {
super(dmc, "-exec-continue"); //$NON-NLS-1$ 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; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; import org.eclipse.dd.mi.service.command.output.MIInfo;
/** /**
* *
* -exec-interrupt * -exec-interrupt [ --thread <tid> | --all ]
* *
* Asynchronous command. Interrupts the background execution of the * Asynchronous command. Interrupts the background execution of the
* target. Note how the token associated with the stop message is the one * 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 class MIExecInterrupt extends MICommand<MIInfo>
{ {
public MIExecInterrupt(IExecutionDMContext dmc) { public MIExecInterrupt(IExecutionDMContext dmc) {
this(dmc, false);
}
public MIExecInterrupt(IExecutionDMContext dmc, boolean allThreads) {
super(dmc, "-exec-interrupt"); //$NON-NLS-1$ 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; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; import org.eclipse.dd.mi.service.command.output.MIInfo;
/** /**
* *
* -exec-next * -exec-next [--thread <tid>] [count]
* *
* Asynchronous command. Resumes execution of the inferior program, * Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached. * stopping when the beginning of the next source line is reached.
@ -26,11 +27,24 @@ import org.eclipse.dd.mi.service.command.output.MIInfo;
*/ */
public class MIExecNext extends MICommand<MIInfo> public class MIExecNext extends MICommand<MIInfo>
{ {
public MIExecNext(IExecutionDMContext dmc) { public MIExecNext(IExecutionDMContext dmc) {
super(dmc, "-exec-next"); //$NON-NLS-1$ this(dmc, 1);
} }
public MIExecNext(IExecutionDMContext dmc, int count) { public MIExecNext(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next", new String[] { Integer.toString(count) }); //$NON-NLS-1$ 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; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; 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 class MIExecNextInstruction extends MICommand<MIInfo>
{ {
public MIExecNextInstruction(IExecutionDMContext dmc) { public MIExecNextInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-next-instruction"); //$NON-NLS-1$ this(dmc, 1);
} }
public MIExecNextInstruction(IExecutionDMContext dmc, int count) { public MIExecNextInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-next-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$ 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> * <p>
* Makes current function return immediately. Doesn't execute the * 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) { public MIExecReturn(IFrameDMContext dmc, String arg) {
super(dmc, "-exec-return", new String[] { arg }); //$NON-NLS-1$ super(dmc, "-exec-return", new String[] { arg }); //$NON-NLS-1$
} }
} }

View file

@ -14,11 +14,12 @@
package org.eclipse.dd.mi.service.command.commands; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; import org.eclipse.dd.mi.service.command.output.MIInfo;
/** /**
* *
* -exec-step * -exec-step [--thread <tid>] [count]
* *
* Asynchronous command. Resumes execution of the inferior program, * Asynchronous command. Resumes execution of the inferior program,
* stopping when the beginning of the next source line is reached, if the * 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 class MIExecStep extends MICommand<MIInfo>
{ {
public MIExecStep(IExecutionDMContext dmc) { public MIExecStep(IExecutionDMContext dmc) {
super(dmc, "-exec-step"); //$NON-NLS-1$ this(dmc, 1);
} }
public MIExecStep(IExecutionDMContext dmc, int count) { public MIExecStep(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step", new String[] { Integer.toString(count) }); //$NON-NLS-1$ 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; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; 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 * Asynchronous command. Resumes the inferior which executes one
* machine instruction. The output, once GDB has stopped, will vary * 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 class MIExecStepInstruction extends MICommand<MIInfo>
{ {
public MIExecStepInstruction(IExecutionDMContext dmc) { public MIExecStepInstruction(IExecutionDMContext dmc) {
super(dmc, "-exec-step-instruction"); //$NON-NLS-1$ this(dmc, 1);
} }
public MIExecStepInstruction(IExecutionDMContext dmc, int count) { public MIExecStepInstruction(IExecutionDMContext dmc, int count) {
super(dmc, "-exec-step-instruction", new String[] { Integer.toString(count) }); //$NON-NLS-1$ 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; package org.eclipse.dd.mi.service.command.commands;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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; 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 * Asynchronous command. Executes the inferior until the LOCATION
* specified in the argument is reached. If there is no argument, the * 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) { 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,13 +25,30 @@ public class MIStackInfoDepth extends MICommand<MIStackInfoDepthInfo>
{ {
public MIStackInfoDepth(IMIExecutionDMContext ctx) { public MIStackInfoDepth(IMIExecutionDMContext ctx) {
this(ctx, false);
}
public MIStackInfoDepth(IMIExecutionDMContext ctx, boolean setThread) {
super(ctx, "-stack-info-depth"); //$NON-NLS-1$ 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) { 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 @Override
public MIStackInfoDepthInfo getResult(MIOutput out) { public MIStackInfoDepthInfo getResult(MIOutput out) {
return new MIStackInfoDepthInfo(out); return new MIStackInfoDepthInfo(out);

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 ] * [ LOW-FRAME HIGH-FRAME ]
* *
* Display a list of the arguments for the frames between LOW-FRAME and * 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 class MIStackListArguments extends MICommand<MIStackListArgumentsInfo>
{ {
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues) { 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$ super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
if (showValues) { if (setThread) {
setParameters(new String[]{"1"}); //$NON-NLS-1$ setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), showValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else { } 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) { public MIStackListArguments(IFrameDMContext frameDmc, boolean showValues) {
super(frameDmc, "-stack-list-arguments"); //$NON-NLS-1$ super(frameDmc, "-stack-list-arguments", new String[] { showValues ? "1" : "0" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (showValues) {
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else {
setParameters(new String[]{"0"}); //$NON-NLS-1$
}
} }
public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues, int low, int high) { public MIStackListArguments(IMIExecutionDMContext execDmc, boolean showValues, int low, int high) {
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$ super(execDmc, "-stack-list-arguments"); //$NON-NLS-1$
String[] params = new String[3]; if (setThread) {
if (showValues) { setParameters(new String[] { "--thread", Integer.toString(execDmc.getThreadId()), //$NON-NLS-1$
params[0] = "1"; //$NON-NLS-1$ showValues ? "1" : "0", Integer.toString(low), Integer.toString(high) } ); //$NON-NLS-1$ //$NON-NLS-2$
} else { } else {
params[0] = "0"; //$NON-NLS-1$ 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 @Override

View file

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

View file

@ -13,7 +13,9 @@
package org.eclipse.dd.mi.service.command.commands; 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.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.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo; import org.eclipse.dd.mi.service.command.output.MIStackListLocalsInfo;
@ -30,12 +32,17 @@ public class MIStackListLocals extends MICommand<MIStackListLocalsInfo>
{ {
public MIStackListLocals(IFrameDMContext frameCtx, boolean printValues) { public MIStackListLocals(IFrameDMContext frameCtx, boolean printValues) {
super(frameCtx, "-stack-list-locals"); //$NON-NLS-1$ this(frameCtx, false, printValues);
if (printValues) { }
setParameters(new String[]{"1"}); //$NON-NLS-1$
} else { public MIStackListLocals(IFrameDMContext frameCtx, boolean setThread, boolean printValues) {
setParameters(new String[]{"0"}); //$NON-NLS-1$ super(frameCtx, "-stack-list-locals"); //$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[] { printValues ? "1" : "0" } ); //$NON-NLS-1$ //$NON-NLS-2$
}
} }
@Override @Override

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.dsf.datamodel.IDMContext;
import org.eclipse.dd.mi.service.command.output.MIInfo; import org.eclipse.dd.mi.service.command.output.MIInfo;
/** /**
* *
* -stack-select-frame FRAMENUM * -stack-select-frame FRAMENUM
@ -30,4 +28,8 @@ public class MIStackSelectFrame extends MICommand<MIInfo> {
public MIStackSelectFrame(IDMContext ctx, int frameNum) { public MIStackSelectFrame(IDMContext ctx, int frameNum) {
super(ctx, "-stack-select-frame", new String[]{Integer.toString(frameNum)}, new String[0]); //$NON-NLS-1$ 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$ 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$ 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -40,7 +40,7 @@ public class MIBreakpointHitEvent extends MIStoppedEvent {
} }
public static MIBreakpointHitEvent parse( public static MIBreakpointHitEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results) IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{ {
int bkptno = -1; 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -54,7 +54,7 @@ public class MIFunctionFinishedEvent extends MIStoppedEvent {
} }
public static MIFunctionFinishedEvent parse( 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 gdbResult = ""; //$NON-NLS-1$
String returnValue = ""; //$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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -30,7 +30,7 @@ public class MILocationReachedEvent extends MIStoppedEvent {
} }
public static MILocationReachedEvent parse( 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); MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MILocationReachedEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame()); 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -30,7 +30,7 @@ public class MISharedLibEvent extends MIStoppedEvent {
} }
public static MIStoppedEvent parse( 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); MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MISharedLibEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame()); 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -49,7 +49,7 @@ public class MISignalEvent extends MIStoppedEvent {
} }
public static MISignalEvent parse( 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 sigName = ""; //$NON-NLS-1$
String sigMeaning = ""; //$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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -31,7 +31,7 @@ public class MISteppingRangeEvent extends MIStoppedEvent {
} }
public static MISteppingRangeEvent parse( 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); MIStoppedEvent stoppedEvent = MIStoppedEvent.parse(runControl, containerDmc, token, results);
return new MISteppingRangeEvent(stoppedEvent.getDMContext(), token, results, stoppedEvent.getFrame()); 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -41,7 +41,7 @@ public class MIStoppedEvent extends MIEvent<IExecutionDMContext> {
} }
public static MIStoppedEvent parse( public static MIStoppedEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results) IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{ {
int threadId = -1; int threadId = -1;
MIFrame frame = null; 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; 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() { public int getId() {
return tid; 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; 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() { public int getId() {
return tid; 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -42,7 +42,7 @@ public class MIWatchpointScopeEvent extends MIStoppedEvent {
} }
public static MIWatchpointScopeEvent parse( public static MIWatchpointScopeEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results) IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{ {
int number = 0; int number = 0;
for (int i = 0; i < results.length; i++) { 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.concurrent.Immutable;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; 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.MIConst;
import org.eclipse.dd.mi.service.command.output.MIFrame; import org.eclipse.dd.mi.service.command.output.MIFrame;
import org.eclipse.dd.mi.service.command.output.MIResult; import org.eclipse.dd.mi.service.command.output.MIResult;
@ -62,7 +62,7 @@ public class MIWatchpointTriggerEvent extends MIStoppedEvent {
} }
public static MIWatchpointTriggerEvent parse( public static MIWatchpointTriggerEvent parse(
MIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results) IMIRunControl runControl, IContainerDMContext containerDmc, int token, MIResult[] results)
{ {
int number = 0; int number = 0;
String exp = ""; //$NON-NLS-1$ String exp = ""; //$NON-NLS-1$

View file

@ -35,7 +35,7 @@ public class CLIInfoThreadsInfo extends MIInfo {
parse(); parse();
} }
public class ThreadInfo{ public class ThreadInfo {
String fName; String fName;
String fGdbId; String fGdbId;
String fPid; 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, MIRunControlTest.class,
ExpressionServiceTest.class, ExpressionServiceTest.class,
MIMemoryTest.class, MIMemoryTest.class,
MIBreakpointsTest.class MIBreakpointsTest.class,
MIDisassemblyTest.class,
/* Add your test class here */ /* 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.DsfServicesTracker;
import org.eclipse.dd.dsf.service.DsfSession; 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;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBProcessData; import org.eclipse.dd.gdb.internal.provisional.service.IGDBRunControl.IGDBProcessData;
import org.eclipse.dd.gdb.internal.provisional.service.GDBRunControl.GDBThreadData; 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.provisional.service.command.GDBControl;
import org.eclipse.dd.mi.service.IMIExecutionDMContext; import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor; import org.eclipse.dd.tests.gdb.framework.AsyncCompletionWaitor;
@ -91,8 +91,8 @@ public class GDBProcessesTest extends BaseTestCase {
/* /*
* Create a request monitor * Create a request monitor
*/ */
final DataRequestMonitor<GDBProcessData> rm = final DataRequestMonitor<IGDBProcessData> rm =
new DataRequestMonitor<GDBProcessData>(fSession.getExecutor(), null) { new DataRequestMonitor<IGDBProcessData>(fSession.getExecutor(), null) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
if (isSuccess()) { if (isSuccess()) {
@ -123,7 +123,7 @@ public class GDBProcessesTest extends BaseTestCase {
/* /*
* Get process data * Get process data
*/ */
GDBProcessData processData = rm.getData(); IGDBProcessData processData = rm.getData();
if(processData == null) if(processData == null)
Assert.fail("No process data is returned for Process DMC"); Assert.fail("No process data is returned for Process DMC");
@ -141,8 +141,8 @@ public class GDBProcessesTest extends BaseTestCase {
*/ */
@Test @Test
public void getThreadData() throws InterruptedException{ public void getThreadData() throws InterruptedException{
final DataRequestMonitor<GDBThreadData> rm = final DataRequestMonitor<IGDBThreadData> rm =
new DataRequestMonitor<GDBThreadData>(fSession.getExecutor(), null) { new DataRequestMonitor<IGDBThreadData>(fSession.getExecutor(), null) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
if (isSuccess()) { if (isSuccess()) {
@ -166,7 +166,7 @@ public class GDBProcessesTest extends BaseTestCase {
fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); fWait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
assertTrue(fWait.getMessage(), fWait.isOK()); assertTrue(fWait.getMessage(), fWait.isOK());
GDBThreadData threadData = rm.getData(); IGDBThreadData threadData = rm.getData();
if(threadData == null) if(threadData == null)
fail("Thread data not returned for thread id = " + fExecDmc.getThreadId()); fail("Thread data not returned for thread id = " + fExecDmc.getThreadId());
else{ else{