mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Bug 335528: [multi-process] Move startOrRestart to the Processes service
This commit is contained in:
parent
58a312b4ed
commit
8bec791d32
6 changed files with 875 additions and 324 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2011 Ericsson and others.
|
* Copyright (c) 2008, 2010 Ericsson and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -15,35 +15,30 @@ package org.eclipse.cdt.dsf.gdb.launching;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
|
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
|
import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
|
||||||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
|
||||||
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
|
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
|
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
@ -63,6 +58,9 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
private SessionType fSessionType;
|
private SessionType fSessionType;
|
||||||
private boolean fAttach;
|
private boolean fAttach;
|
||||||
|
|
||||||
|
// The launchConfiguration attributes
|
||||||
|
private Map<String, Object> fAttributes;
|
||||||
|
|
||||||
private IGDBControl fCommandControl;
|
private IGDBControl fCommandControl;
|
||||||
private IGDBBackend fGDBBackend;
|
private IGDBBackend fGDBBackend;
|
||||||
private IMIProcesses fProcService;
|
private IMIProcesses fProcService;
|
||||||
|
@ -82,22 +80,24 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
if (GROUP_TOP_LEVEL.equals(group)) {
|
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||||
return new String[] {
|
return new String[] {
|
||||||
"stepInitializeFinalLaunchSequence", //$NON-NLS-1$
|
"stepInitializeFinalLaunchSequence", //$NON-NLS-1$
|
||||||
|
// Global GDB settings
|
||||||
"stepSetEnvironmentDirectory", //$NON-NLS-1$
|
"stepSetEnvironmentDirectory", //$NON-NLS-1$
|
||||||
"stepSetBreakpointPending", //$NON-NLS-1$
|
"stepSetBreakpointPending", //$NON-NLS-1$
|
||||||
"stepEnablePrettyPrinting", //$NON-NLS-1$
|
"stepEnablePrettyPrinting", //$NON-NLS-1$
|
||||||
"stepSourceGDBInitFile", //$NON-NLS-1$
|
"stepSourceGDBInitFile", //$NON-NLS-1$
|
||||||
"stepSetEnvironmentVariables", //$NON-NLS-1$
|
|
||||||
"stepSetExecutable", //$NON-NLS-1$
|
|
||||||
"stepSetArguments", //$NON-NLS-1$
|
|
||||||
"stepSetNonStop", //$NON-NLS-1$
|
"stepSetNonStop", //$NON-NLS-1$
|
||||||
"stepSetAutoLoadSharedLibrarySymbols", //$NON-NLS-1$
|
"stepSetAutoLoadSharedLibrarySymbols", //$NON-NLS-1$
|
||||||
"stepSetSharedLibraryPaths", //$NON-NLS-1$
|
"stepSetSharedLibraryPaths", //$NON-NLS-1$
|
||||||
"stepSetSourceLookupPath", //$NON-NLS-1$
|
"stepSetSourceLookupPath", //$NON-NLS-1$
|
||||||
|
// For post-mortem launch only
|
||||||
"stepSpecifyCoreFile", //$NON-NLS-1$
|
"stepSpecifyCoreFile", //$NON-NLS-1$
|
||||||
|
// For remote-attach launch only
|
||||||
"stepRemoteConnection", //$NON-NLS-1$
|
"stepRemoteConnection", //$NON-NLS-1$
|
||||||
|
// For all launches except attach ones
|
||||||
|
"stepNewProcess", //$NON-NLS-1$
|
||||||
|
// For local attach launch only
|
||||||
"stepAttachToProcess", //$NON-NLS-1$
|
"stepAttachToProcess", //$NON-NLS-1$
|
||||||
"stepStartTrackingBreakpoints", //$NON-NLS-1$
|
// Global
|
||||||
"stepStartExecution", //$NON-NLS-1$
|
|
||||||
"stepDataModelInitializationComplete", //$NON-NLS-1$
|
"stepDataModelInitializationComplete", //$NON-NLS-1$
|
||||||
"stepCleanup", //$NON-NLS-1$
|
"stepCleanup", //$NON-NLS-1$
|
||||||
};
|
};
|
||||||
|
@ -110,6 +110,7 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
* This step is mandatory for the rest fo the sequence to complete.
|
* This step is mandatory for the rest fo the sequence to complete.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Execute
|
@Execute
|
||||||
public void stepInitializeFinalLaunchSequence(RequestMonitor requestMonitor) {
|
public void stepInitializeFinalLaunchSequence(RequestMonitor requestMonitor) {
|
||||||
fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
|
fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
|
||||||
|
@ -136,6 +137,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
fAttributes = fLaunch.getLaunchConfiguration().getAttributes();
|
||||||
|
} catch (CoreException e) {
|
||||||
|
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain launch configuration attributes", null)); //$NON-NLS-1$
|
||||||
|
requestMonitor.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,91 +256,16 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify environment variables if needed
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
@Execute
|
|
||||||
public void stepSetEnvironmentVariables(final RequestMonitor requestMonitor) {
|
|
||||||
boolean clear = false;
|
|
||||||
Properties properties = new Properties();
|
|
||||||
try {
|
|
||||||
clear = fGDBBackend.getClearEnvironment();
|
|
||||||
properties = fGDBBackend.getEnvironmentVariables();
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get environment information", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clear == true || properties.size() > 0) {
|
|
||||||
fCommandControl.setEnvironment(properties, clear, requestMonitor);
|
|
||||||
} else {
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify the executable file to be debugged and read the symbol table.
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
@Execute
|
|
||||||
public void stepSetExecutable(final RequestMonitor requestMonitor) {
|
|
||||||
boolean noFileCommand = IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT;
|
|
||||||
try {
|
|
||||||
noFileCommand = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
|
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot read use solib symbols for app options", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final IPath execPath = fGDBBackend.getProgramPath();
|
|
||||||
if (!noFileCommand && execPath != null && !execPath.isEmpty()) {
|
|
||||||
fCommandControl.queueCommand(
|
|
||||||
fCommandFactory.createMIFileExecAndSymbols(fCommandControl.getContext(),
|
|
||||||
execPath.toPortableString()),
|
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
|
||||||
} else {
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify the arguments to the executable file.
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
@Execute
|
|
||||||
public void stepSetArguments(final RequestMonitor requestMonitor) {
|
|
||||||
try {
|
|
||||||
String args = fGDBBackend.getProgramArguments();
|
|
||||||
|
|
||||||
if (args != null) {
|
|
||||||
fCommandControl.queueCommand(
|
|
||||||
fCommandFactory.createMIGDBSetArgs(fCommandControl.getContext(), args),
|
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
|
||||||
} else {
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable non-stop mode if requested.
|
* Enable non-stop mode if requested.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@Execute
|
@Execute
|
||||||
public void stepSetNonStop(final RequestMonitor requestMonitor) {
|
public void stepSetNonStop(final RequestMonitor requestMonitor) {
|
||||||
boolean isNonStop = false;
|
boolean isNonStop = CDebugUtils.getAttribute(
|
||||||
try {
|
fAttributes,
|
||||||
isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
||||||
} catch (CoreException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// GDBs that don't support non-stop don't allow you to set it to false.
|
// GDBs that don't support non-stop don't allow you to set it to false.
|
||||||
// We really should set it to false when GDB supports it though.
|
// We really should set it to false when GDB supports it though.
|
||||||
|
@ -365,16 +299,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
*/
|
*/
|
||||||
@Execute
|
@Execute
|
||||||
public void stepSetAutoLoadSharedLibrarySymbols(RequestMonitor requestMonitor) {
|
public void stepSetAutoLoadSharedLibrarySymbols(RequestMonitor requestMonitor) {
|
||||||
try {
|
boolean autolib = CDebugUtils.getAttribute(
|
||||||
boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
|
||||||
|
|
||||||
fCommandControl.queueCommand(
|
fCommandControl.queueCommand(
|
||||||
fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
|
fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set shared library option", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -476,10 +408,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
@Execute
|
@Execute
|
||||||
public void stepSpecifyCoreFile(final RequestMonitor requestMonitor) {
|
public void stepSpecifyCoreFile(final RequestMonitor requestMonitor) {
|
||||||
if (fSessionType == SessionType.CORE) {
|
if (fSessionType == SessionType.CORE) {
|
||||||
try {
|
String coreFile = CDebugUtils.getAttribute(
|
||||||
String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
|
fAttributes,
|
||||||
final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
|
||||||
|
final String coreType = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
||||||
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
||||||
|
|
||||||
if (coreFile.length() == 0) {
|
if (coreFile.length() == 0) {
|
||||||
new PromptForCoreJob(
|
new PromptForCoreJob(
|
||||||
"Prompt for post mortem file", //$NON-NLS-1$
|
"Prompt for post mortem file", //$NON-NLS-1$
|
||||||
|
@ -530,124 +466,93 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get post mortem file path", e));
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final static String INVALID = "invalid"; //$NON-NLS-1$
|
||||||
private boolean fTcpConnection;
|
|
||||||
private String fRemoteTcpHost;
|
|
||||||
private String fRemoteTcpPort;
|
|
||||||
private String fSerialDevice;
|
|
||||||
|
|
||||||
private boolean checkConnectionType(RequestMonitor requestMonitor) {
|
|
||||||
try {
|
|
||||||
fTcpConnection = fLaunch.getLaunchConfiguration().getAttribute(
|
|
||||||
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
|
||||||
false);
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve connection mode", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getSerialDevice(RequestMonitor requestMonitor) {
|
|
||||||
try {
|
|
||||||
fSerialDevice = fLaunch.getLaunchConfiguration().getAttribute(
|
|
||||||
IGDBLaunchConfigurationConstants.ATTR_DEV, "invalid"); //$NON-NLS-1$
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve serial device", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getTcpHost(RequestMonitor requestMonitor) {
|
|
||||||
try {
|
|
||||||
fRemoteTcpHost = fLaunch.getLaunchConfiguration().getAttribute(
|
|
||||||
IGDBLaunchConfigurationConstants.ATTR_HOST, "invalid"); //$NON-NLS-1$
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP host", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getTcpPort(RequestMonitor requestMonitor) {
|
|
||||||
try {
|
|
||||||
fRemoteTcpPort = fLaunch.getLaunchConfiguration().getAttribute(
|
|
||||||
IGDBLaunchConfigurationConstants.ATTR_PORT, "invalid"); //$NON-NLS-1$
|
|
||||||
} catch (CoreException e) {
|
|
||||||
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve remote TCP port", e)); //$NON-NLS-1$
|
|
||||||
requestMonitor.done();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we are dealing with a remote debugging session, connect to the target.
|
* If we are dealing with a remote-attach debugging session, connect to the target.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@Execute
|
@Execute
|
||||||
public void stepRemoteConnection(final RequestMonitor requestMonitor) {
|
public void stepRemoteConnection(final RequestMonitor rm) {
|
||||||
if (fSessionType == SessionType.REMOTE) {
|
if (fSessionType == SessionType.REMOTE && fAttach) {
|
||||||
if (!checkConnectionType(requestMonitor)) return;
|
boolean isTcpConnection = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
||||||
|
false);
|
||||||
|
|
||||||
if (fTcpConnection) {
|
if (isTcpConnection) {
|
||||||
if (!getTcpHost(requestMonitor)) return;
|
String remoteTcpHost = CDebugUtils.getAttribute(
|
||||||
if (!getTcpPort(requestMonitor)) return;
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_HOST, INVALID);
|
||||||
|
String remoteTcpPort = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_PORT, INVALID);
|
||||||
|
|
||||||
fCommandControl.queueCommand(
|
fCommandControl.queueCommand(
|
||||||
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||||
fRemoteTcpHost, fRemoteTcpPort, fAttach),
|
remoteTcpHost, remoteTcpPort, true),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
} else {
|
} else {
|
||||||
if (!getSerialDevice(requestMonitor)) return;
|
String serialDevice = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEV, INVALID);
|
||||||
|
|
||||||
fCommandControl.queueCommand(
|
fCommandControl.queueCommand(
|
||||||
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||||
fSerialDevice, fAttach),
|
serialDevice, true),
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
requestMonitor.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we are dealing with an attach debugging session, perform the attach.
|
* Start a new process if we are not dealing with an attach session
|
||||||
|
* i.e., a local session, a remote session or a post-mortem (core) session.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepNewProcess(final RequestMonitor rm) {
|
||||||
|
if (!fAttach) {
|
||||||
|
|
||||||
|
boolean noBinarySpecified = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
|
||||||
|
|
||||||
|
String binary = null;
|
||||||
|
final IPath execPath = fGDBBackend.getProgramPath();
|
||||||
|
if (!noBinarySpecified && execPath != null && !execPath.isEmpty()) {
|
||||||
|
binary = execPath.toPortableString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even if binary is null, we must call this to do all the other steps
|
||||||
|
// necessary to create a process. It is possible that the binary is not needed
|
||||||
|
fProcService.debugNewProcess(fCommandControl.getContext(), binary, fAttributes,
|
||||||
|
new DataRequestMonitor<IDMContext>(getExecutor(), rm));
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we are dealing with an local attach session, perform the attach.
|
||||||
|
* For a remote attach session, we don't attach during the launch; instead
|
||||||
|
* we wait for the user to manually do the attach.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
@Execute
|
@Execute
|
||||||
public void stepAttachToProcess(final RequestMonitor requestMonitor) {
|
public void stepAttachToProcess(final RequestMonitor requestMonitor) {
|
||||||
// A local attach can figure out the binary from the attach
|
|
||||||
// command. This allows the user not to specify the binary
|
|
||||||
// in the launch. But for breakpoints to work, we must do the
|
|
||||||
// attach before we set the breakpoints, i.e., here.
|
|
||||||
// On the other hand, for a remote attach, we need to specify
|
|
||||||
// the binary anyway, or use the solib command. In both cases,
|
|
||||||
// breakpoints can be set before we attach. Therefore, we don't
|
|
||||||
// force an attach here, but wait for the user to decide to connect
|
|
||||||
// using the connect action.
|
|
||||||
if (fAttach && fSessionType != SessionType.REMOTE) {
|
if (fAttach && fSessionType != SessionType.REMOTE) {
|
||||||
// If we are attaching, get the process id.
|
// Is the process id already stored in the launch?
|
||||||
int pid = -1;
|
int pid = CDebugUtils.getAttribute(
|
||||||
try {
|
fAttributes,
|
||||||
// have we already been given the pid (maybe from a JUnit test launch or something)
|
ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
|
||||||
pid = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
|
|
||||||
} catch (CoreException e) {
|
|
||||||
// do nothing and fall to below
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid != -1) {
|
if (pid != -1) {
|
||||||
fProcService.attachDebuggerToProcess(
|
fProcService.attachDebuggerToProcess(
|
||||||
|
@ -666,48 +571,6 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Start tracking the breakpoints. Note that for remote debugging
|
|
||||||
* we should first connect to the target.
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
@Execute
|
|
||||||
public void stepStartTrackingBreakpoints(final RequestMonitor requestMonitor) {
|
|
||||||
if (fSessionType != SessionType.CORE) {
|
|
||||||
MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class);
|
|
||||||
IMIContainerDMContext containerDmc = fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), null);
|
|
||||||
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
|
||||||
|
|
||||||
bpmService.startTrackingBreakpoints(bpTargetDmc, requestMonitor);
|
|
||||||
} else {
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start executing the program.
|
|
||||||
* @since 4.0
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Execute
|
|
||||||
public void stepStartExecution(final RequestMonitor requestMonitor) {
|
|
||||||
if (fSessionType != SessionType.CORE) {
|
|
||||||
Map<String, Object> attributes = null;
|
|
||||||
try {
|
|
||||||
attributes = fLaunch.getLaunchConfiguration().getAttributes();
|
|
||||||
} catch (CoreException e) {}
|
|
||||||
|
|
||||||
IGDBProcesses procService = fTracker.getService(IGDBProcesses.class);
|
|
||||||
IContainerDMContext containerDmc = procService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
|
|
||||||
|
|
||||||
// For now, call restart since it does the same as start
|
|
||||||
// but this is just temporary until procService.debugNewProcess is ready
|
|
||||||
procService.restart(containerDmc, attributes, requestMonitor);
|
|
||||||
} else {
|
|
||||||
requestMonitor.done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicate that the Data Model has been filled. This will trigger the Debug view to expand.
|
* Indicate that the Data Model has been filled. This will trigger the Debug view to expand.
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
|
|
@ -0,0 +1,302 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Ericsson and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ericsson - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ReflectionSequence;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class DebugNewProcessSequence extends ReflectionSequence {
|
||||||
|
|
||||||
|
private final static String INVALID = "invalid"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private IGDBControl fCommandControl;
|
||||||
|
private CommandFactory fCommandFactory;
|
||||||
|
private IGDBBackend fBackend;
|
||||||
|
private IGDBProcesses fProcService;
|
||||||
|
private DsfServicesTracker fTracker;
|
||||||
|
|
||||||
|
private IDMContext fContext;
|
||||||
|
private String fBinaryName;
|
||||||
|
private Map<String, Object> fAttributes;
|
||||||
|
private IMIContainerDMContext fContainerCtx;
|
||||||
|
|
||||||
|
// Store the dataRM so that we can fill it with the container context that we will be creating
|
||||||
|
private DataRequestMonitor<IDMContext> fDataRequestMonitor;
|
||||||
|
|
||||||
|
|
||||||
|
protected IMIContainerDMContext getContainerContext() {
|
||||||
|
return fContainerCtx;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setContainerContext(IMIContainerDMContext ctx) {
|
||||||
|
fContainerCtx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DebugNewProcessSequence(DsfExecutor executor, IDMContext dmc, String file, Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||||
|
super(executor, rm);
|
||||||
|
fContext = dmc;
|
||||||
|
fBinaryName = file;
|
||||||
|
fAttributes = attributes;
|
||||||
|
fDataRequestMonitor = rm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getExecutionOrder(String group) {
|
||||||
|
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||||
|
return new String[] {
|
||||||
|
"stepInitializeBaseSequence", //$NON-NLS-1$
|
||||||
|
"stepSetEnvironmentVariables", //$NON-NLS-1$
|
||||||
|
"stepSetExecutable", //$NON-NLS-1$
|
||||||
|
"stepSetArguments", //$NON-NLS-1$
|
||||||
|
"stepRemoteConnection", //$NON-NLS-1$
|
||||||
|
"stepStartTrackingBreakpoints", //$NON-NLS-1$
|
||||||
|
"stepStartExecution", //$NON-NLS-1$
|
||||||
|
"stepCleanupBaseSequence", //$NON-NLS-1$
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the members of the {@link StartOrRestartProcessSequence_7_0} class.
|
||||||
|
* This step is mandatory for the rest of the sequence to complete.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepInitializeBaseSequence(RequestMonitor rm) {
|
||||||
|
fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fContext.getSessionId());
|
||||||
|
fBackend = fTracker.getService(IGDBBackend.class);
|
||||||
|
fCommandControl = fTracker.getService(IGDBControl.class);
|
||||||
|
fCommandFactory = fTracker.getService(IMICommandControl.class).getCommandFactory();
|
||||||
|
fProcService = fTracker.getService(IGDBProcesses.class);
|
||||||
|
|
||||||
|
if (fBackend == null || fCommandControl == null || fCommandFactory == null || fProcService == null) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we are starting to debug a new process, the container is the default process used by GDB.
|
||||||
|
// We don't have a pid yet, so we can simply create the container with the UNIQUE_GROUP_ID
|
||||||
|
setContainerContext(fProcService.createContainerContextFromGroupId(fCommandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID));
|
||||||
|
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback method for {@link #stepInitializeBaseSequence()}
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@RollBack("stepInitializeBaseSequence")
|
||||||
|
public void rollBackInitializeBaseSequence(RequestMonitor rm) {
|
||||||
|
if (fTracker != null) fTracker.dispose();
|
||||||
|
fTracker = null;
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify environment variables if needed
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepSetEnvironmentVariables(RequestMonitor rm) {
|
||||||
|
boolean clear = false;
|
||||||
|
Properties properties = new Properties();
|
||||||
|
try {
|
||||||
|
// here we need to pass the proper container context
|
||||||
|
clear = fBackend.getClearEnvironment();
|
||||||
|
properties = fBackend.getEnvironmentVariables();
|
||||||
|
} catch (CoreException e) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Cannot get environment information", e)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clear == true || properties.size() > 0) {
|
||||||
|
// here we need to pass the proper container context
|
||||||
|
fCommandControl.setEnvironment(properties, clear, rm);
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the executable file to be debugged and read the symbol table.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepSetExecutable(RequestMonitor rm) {
|
||||||
|
boolean noFileCommand = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
|
||||||
|
|
||||||
|
if (!noFileCommand && fBinaryName != null && fBinaryName.length() > 0) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIFileExecAndSymbols(getContainerContext(), fBinaryName),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the arguments to the program that will be run.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepSetArguments(RequestMonitor rm) {
|
||||||
|
try {
|
||||||
|
String args = fBackend.getProgramArguments();
|
||||||
|
|
||||||
|
if (args != null) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
// here we need to pass the proper container context
|
||||||
|
fCommandFactory.createMIGDBSetArgs(fCommandControl.getContext(), args),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Cannot get inferior arguments", e)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we are dealing with a remote debugging session, connect to the target.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepRemoteConnection(RequestMonitor rm) {
|
||||||
|
// If we are dealing with a remote session, it is now time to connect
|
||||||
|
// to the remote side. Note that this is the 'target remote' case
|
||||||
|
// and not the 'target extended-remote' case (remote attach session)
|
||||||
|
// We know this because a remote attach session does not start a new
|
||||||
|
// process, so we wouldn't be in this sequence
|
||||||
|
// This step is actually global for GDB. However, we have to do it after
|
||||||
|
// we have specified the executable, so we have to do it here.
|
||||||
|
// It is safe to do it here because a 'target remote' does not support
|
||||||
|
// multi-process so this step will not be executed more than once.
|
||||||
|
|
||||||
|
assert fBackend.getIsAttachSession() == false;
|
||||||
|
|
||||||
|
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||||
|
boolean isTcpConnection = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if (isTcpConnection) {
|
||||||
|
String remoteTcpHost = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_HOST, INVALID);
|
||||||
|
String remoteTcpPort = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_PORT, INVALID);
|
||||||
|
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||||
|
remoteTcpHost, remoteTcpPort, false),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
} else {
|
||||||
|
String serialDevice = CDebugUtils.getAttribute(
|
||||||
|
fAttributes,
|
||||||
|
IGDBLaunchConfigurationConstants.ATTR_DEV, INVALID);
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||||
|
serialDevice, false),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start tracking the breakpoints. Note that for remote debugging
|
||||||
|
* we should first connect to the target.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepStartTrackingBreakpoints(RequestMonitor rm) {
|
||||||
|
if (fBackend.getSessionType() != SessionType.CORE) {
|
||||||
|
MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class);
|
||||||
|
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(getContainerContext(), IBreakpointsTargetDMContext.class);
|
||||||
|
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
||||||
|
} else {
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start executing the program.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepStartExecution(final RequestMonitor rm) {
|
||||||
|
if (fBackend.getSessionType() != SessionType.CORE) {
|
||||||
|
ImmediateExecutor.getInstance().execute(
|
||||||
|
new StartOrRestartProcessSequence_7_0(
|
||||||
|
getExecutor(), getContainerContext(), fAttributes, false,
|
||||||
|
new DataRequestMonitor<IContainerDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
assert getData() instanceof IMIContainerDMContext;
|
||||||
|
|
||||||
|
// Set the container that we created
|
||||||
|
setContainerContext(DMContexts.getAncestorOfType(getData(), IMIContainerDMContext.class));
|
||||||
|
fDataRequestMonitor.setData(getContainerContext());
|
||||||
|
|
||||||
|
// Don't call fDataRequestMonitor.done(), the sequence will
|
||||||
|
// automatically do that when we call rm.done();
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
fDataRequestMonitor.setData(getContainerContext());
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup now that the sequence has been run.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepCleanupBaseSequence(RequestMonitor rm) {
|
||||||
|
fTracker.dispose();
|
||||||
|
fTracker = null;
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Ericsson and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Ericsson - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo;
|
||||||
|
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With GDB 7.2, to create a new process, we need to use the -add-inferior command first.
|
||||||
|
* This allows to create multiple processes, unlike previous versions of GDB.
|
||||||
|
* Note that GDB 7.1 does support multi-process but didn't have the MI commands (e.g., -add-inferior)
|
||||||
|
* so we only support multi-process starting with 7.2
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class DebugNewProcessSequence_7_2 extends DebugNewProcessSequence {
|
||||||
|
|
||||||
|
private IGDBControl fGdbControl;
|
||||||
|
private IGDBProcesses fProcService;
|
||||||
|
private String fSessionId;
|
||||||
|
private boolean fInitialProcess;
|
||||||
|
|
||||||
|
public DebugNewProcessSequence_7_2(DsfExecutor executor, boolean initialProcess, IDMContext dmc, String file,
|
||||||
|
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||||
|
super(executor, dmc, file, attributes, rm);
|
||||||
|
fSessionId = dmc.getSessionId();
|
||||||
|
fInitialProcess = initialProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getExecutionOrder(String group) {
|
||||||
|
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||||
|
// Initialize the list with the base class' steps
|
||||||
|
// We need to create a list that we can modify, which is why we create our own ArrayList.
|
||||||
|
List<String> orderList = new ArrayList<String>(Arrays.asList(super.getExecutionOrder(GROUP_TOP_LEVEL)));
|
||||||
|
|
||||||
|
// Now insert our steps right after the initialization of the base class.
|
||||||
|
orderList.add(orderList.indexOf("stepInitializeBaseSequence") + 1, "stepInitializeSequence_7_2"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
orderList.add(orderList.indexOf("stepInitializeSequence_7_2") + 1, "stepAddInferior"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
return orderList.toArray(new String[orderList.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the members of the {@link DebugNewProcessSequence_7_2} class.
|
||||||
|
* This step is mandatory for the rest of the sequence to complete.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepInitializeSequence_7_2(RequestMonitor rm) {
|
||||||
|
DsfServicesTracker tracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fSessionId);
|
||||||
|
fGdbControl = tracker.getService(IGDBControl.class);
|
||||||
|
fProcService = tracker.getService(IGDBProcesses.class);
|
||||||
|
tracker.dispose();
|
||||||
|
|
||||||
|
if (fGdbControl == null || fProcService == null) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot obtain service", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new inferior.
|
||||||
|
*/
|
||||||
|
@Execute
|
||||||
|
public void stepAddInferior(final RequestMonitor rm) {
|
||||||
|
if (fInitialProcess) {
|
||||||
|
// The first process is automatically created by GDB. We actually want to use that first created process
|
||||||
|
// instead of ignoring it and creating a new one for a couple of reasons:
|
||||||
|
// 1- post-mortem and non-attach remote sessions don't support creating a new process
|
||||||
|
// 2- commands that were part of the .gdbinit file will affect the initial process, which is what the user expects,
|
||||||
|
// but would not affect a new process we created instead.
|
||||||
|
setContainerContext(fProcService.createContainerContextFromGroupId(fGdbControl.getContext(), "i1")); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fGdbControl.queueCommand(
|
||||||
|
fGdbControl.getCommandFactory().createMIAddInferior(fGdbControl.getContext()),
|
||||||
|
new DataRequestMonitor<MIAddInferiorInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
final String groupId = getData().getGroupId();
|
||||||
|
if (groupId == null || groupId.trim().length() == 0) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Invalid gdb group id.", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setContainerContext(fProcService.createContainerContextFromGroupId(fGdbControl.getContext(), groupId));
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,7 @@ import org.eclipse.cdt.core.IProcessList;
|
||||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
|
@ -37,6 +38,7 @@ import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
|
||||||
|
@ -46,6 +48,7 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
@ -200,9 +203,18 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
|
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
|
||||||
super.attachDebuggerToProcess(
|
// For remote attach, we must set the binary first
|
||||||
|
// For a local attach, GDB can figure out the binary automatically,
|
||||||
|
// so we don't specify it.
|
||||||
|
|
||||||
|
IMIContainerDMContext containerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||||
|
|
||||||
|
DataRequestMonitor<MIInfo> attachRm = new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||||
|
@Override
|
||||||
|
protected void handleSuccess() {
|
||||||
|
GDBProcesses.super.attachDebuggerToProcess(
|
||||||
procCtx,
|
procCtx,
|
||||||
new DataRequestMonitor<IDMContext>(getExecutor(), rm) {
|
new DataRequestMonitor<IDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
fGdb.setConnected(true);
|
fGdb.setConnected(true);
|
||||||
|
@ -212,11 +224,31 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
||||||
inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
||||||
}
|
}
|
||||||
|
|
||||||
rm.setData(getData());
|
IDMContext containerDmc = getData();
|
||||||
rm.done();
|
rm.setData(containerDmc);
|
||||||
|
|
||||||
|
// Start tracking breakpoints.
|
||||||
|
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
|
||||||
|
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
||||||
|
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||||
|
final IPath execPath = fBackend.getProgramPath();
|
||||||
|
if (execPath != null && !execPath.isEmpty()) {
|
||||||
|
fGdb.queueCommand(
|
||||||
|
fCommandFactory.createMIFileExecAndSymbols(containerDmc, execPath.toPortableString()),
|
||||||
|
attachRm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, let's do the attach by completing the requestMonitor
|
||||||
|
attachRm.done();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||||
|
@ -243,6 +275,13 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debugNewProcess(IDMContext dmc, String file,
|
||||||
|
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||||
|
ImmediateExecutor.getInstance().execute(
|
||||||
|
new DebugNewProcessSequence(getExecutor(), dmc, file, attributes, rm));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
|
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
|
||||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
import org.eclipse.cdt.dsf.concurrent.Immutable;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
|
||||||
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
|
@ -47,6 +48,7 @@ import org.eclipse.cdt.dsf.debug.service.command.BufferedCommandControl;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||||
|
@ -54,6 +56,7 @@ import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||||
|
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
|
||||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupCreatedEvent;
|
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupCreatedEvent;
|
||||||
|
@ -73,8 +76,10 @@ import org.eclipse.cdt.dsf.service.AbstractDsfService;
|
||||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -430,6 +435,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
|
|
||||||
private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$
|
private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
private boolean fInitialProcess = true;
|
||||||
|
|
||||||
public GDBProcesses_7_0(DsfSession session) {
|
public GDBProcesses_7_0(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
}
|
}
|
||||||
|
@ -639,8 +646,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
} else if (name.length() == 0) {
|
} else if (name.length() == 0) {
|
||||||
// Probably will not happen, but just in case...use the
|
// Probably will not happen, but just in case...use the
|
||||||
// binary file name (absolute path)
|
// binary file name (absolute path)
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
name = fBackend.getProgramPath().toOSString();
|
||||||
name = backend.getProgramPath().toOSString();
|
|
||||||
fDebuggedProcessesAndNames.put(id, name);
|
fDebuggedProcessesAndNames.put(id, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,11 +708,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
|
|
||||||
/** @since 4.0 */
|
/** @since 4.0 */
|
||||||
protected boolean doIsDebuggerAttachSupported() {
|
protected boolean doIsDebuggerAttachSupported() {
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
return fBackend.getIsAttachSession() && !fCommandControl.isConnected();
|
||||||
if (backend != null) {
|
|
||||||
return backend.getIsAttachSession();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||||
|
@ -714,39 +716,102 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
|
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> dataRm) {
|
||||||
if (procCtx instanceof IMIProcessDMContext) {
|
if (procCtx instanceof IMIProcessDMContext) {
|
||||||
if (!doIsDebuggerAttachSupported()) {
|
if (!doIsDebuggerAttachSupported()) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
dataRm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
// Use a sequence for better control of each step
|
||||||
fCommandControl.queueCommand(
|
ImmediateExecutor.getInstance().execute(new Sequence(getExecutor(), dataRm) {
|
||||||
fCommandFactory.createMITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
private IMIContainerDMContext fContainerDmc;
|
||||||
|
|
||||||
|
private Step[] steps = new Step[] {
|
||||||
|
// For remote attach, we must set the binary first
|
||||||
|
// For a local attach, GDB can figure out the binary automatically,
|
||||||
|
// so we don't specify it.
|
||||||
|
new Step() {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
public void execute(RequestMonitor rm) {
|
||||||
// By now, GDB has reported the groupId that was attached to this process
|
// There is no groupId until we attach, so we can use the default groupId
|
||||||
rm.setData(createContainerContext(procCtx, getGroupFromPid(((IMIProcessDMContext)procCtx).getProcId())));
|
fContainerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||||
|
|
||||||
|
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||||
|
final IPath execPath = fBackend.getProgramPath();
|
||||||
|
if (execPath != null && !execPath.isEmpty()) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIFileExecAndSymbols(fContainerDmc, execPath.toPortableString()),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
// Attach to the process
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMITargetAttach(fContainerDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
||||||
|
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
// By now, GDB has reported the groupId that was created for this process
|
||||||
|
fContainerDmc = createContainerContext(procCtx, getGroupFromPid(((IMIProcessDMContext)procCtx).getProcId()));
|
||||||
|
// Store the fully formed container context so it can be returned to the caller.
|
||||||
|
dataRm.setData(fContainerDmc);
|
||||||
|
|
||||||
} else {
|
// Start tracking breakpoints.
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
|
||||||
|
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(fContainerDmc, IBreakpointsTargetDMContext.class);
|
||||||
|
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Turn on reverse debugging if it was enabled as a launch option
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
IReverseRunControl reverseService = getServicesTracker().getService(IReverseRunControl.class);
|
||||||
|
if (reverseService != null) {
|
||||||
|
ILaunch launch = (ILaunch)procCtx.getAdapter(ILaunch.class);
|
||||||
|
if (launch != null) {
|
||||||
|
try {
|
||||||
|
boolean reverseEnabled =
|
||||||
|
launch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||||
|
if (reverseEnabled) {
|
||||||
|
reverseService.enableReverseMode(fCommandControl.getContext(), true, rm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
// Ignore, just don't set reverse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override public Step[] getSteps() { return steps; }
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||||
|
dataRm.done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 4.0 */
|
/** @since 4.0 */
|
||||||
protected boolean doCanDetachDebuggerFromProcess() {
|
protected boolean doCanDetachDebuggerFromProcess() {
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
return fBackend.getIsAttachSession() && fCommandControl.isConnected();
|
||||||
if (backend != null) {
|
|
||||||
return backend.getIsAttachSession() && fCommandControl.isConnected();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||||
|
@ -781,15 +846,29 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
}
|
}
|
||||||
|
|
||||||
public void isDebugNewProcessSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
public void isDebugNewProcessSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||||
rm.setData(false);
|
rm.setData(doIsDebugNewProcessSupported());
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 4.0 */
|
||||||
|
protected boolean doIsDebugNewProcessSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void debugNewProcess(IDMContext dmc, String file,
|
public void debugNewProcess(IDMContext dmc, String file,
|
||||||
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
if (!fInitialProcess) {
|
||||||
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
|
// If we have already dealt with the initial process, check if we are allowed to create another one
|
||||||
|
if (!doIsDebugNewProcessSupported()) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Cannot start a new process", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fInitialProcess = false;
|
||||||
|
ImmediateExecutor.getInstance().execute(
|
||||||
|
new DebugNewProcessSequence(getExecutor(), dmc, file, attributes, rm));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> rm) {
|
public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> rm) {
|
||||||
|
@ -904,8 +983,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
// list natively (as we do with gdb 6.8). If
|
// list natively (as we do with gdb 6.8). If
|
||||||
// we're debugging remotely, the user is out
|
// we're debugging remotely, the user is out
|
||||||
// of luck
|
// of luck
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
if (fBackend.getSessionType() == SessionType.LOCAL) {
|
||||||
if (backend.getSessionType() == SessionType.LOCAL) {
|
|
||||||
IProcessList list = null;
|
IProcessList list = null;
|
||||||
try {
|
try {
|
||||||
list = CCorePlugin.getDefault().getProcessList();
|
list = CCorePlugin.getDefault().getProcessList();
|
||||||
|
@ -1185,8 +1263,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
||||||
// Looks like this gdb doesn't truly support
|
// Looks like this gdb doesn't truly support
|
||||||
// "-list-thread-groups --available". Get the
|
// "-list-thread-groups --available". Get the
|
||||||
// process list natively if we're debugging locally
|
// process list natively if we're debugging locally
|
||||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
if (fBackend.getSessionType() == SessionType.LOCAL) {
|
||||||
if (backend.getSessionType() == SessionType.LOCAL) {
|
|
||||||
IProcessList list = null;
|
IProcessList list = null;
|
||||||
try {
|
try {
|
||||||
list = CCorePlugin.getDefault().getProcessList();
|
list = CCorePlugin.getDefault().getProcessList();
|
||||||
|
|
|
@ -10,12 +10,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.dsf.gdb.service;
|
package org.eclipse.cdt.dsf.gdb.service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
import org.eclipse.cdt.dsf.concurrent.Sequence;
|
||||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
|
||||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||||
|
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||||
|
@ -26,8 +31,11 @@ import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo;
|
||||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
import org.eclipse.core.runtime.IStatus;
|
import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.debug.core.ILaunch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adding support for multi-process with GDB 7.2
|
* Adding support for multi-process with GDB 7.2
|
||||||
|
@ -38,6 +46,14 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
|
|
||||||
private CommandFactory fCommandFactory;
|
private CommandFactory fCommandFactory;
|
||||||
private IGDBControl fCommandControl;
|
private IGDBControl fCommandControl;
|
||||||
|
private IGDBBackend fBackend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track if we are dealing with the very first
|
||||||
|
* process of GDB. In such a case, we should not create a new
|
||||||
|
* inferior, since GDB has already created one by default.
|
||||||
|
*/
|
||||||
|
private boolean fInitialProcess = true;
|
||||||
|
|
||||||
public GDBProcesses_7_2(DsfSession session) {
|
public GDBProcesses_7_2(DsfSession session) {
|
||||||
super(session);
|
super(session);
|
||||||
|
@ -64,6 +80,8 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
private void doInitialize(RequestMonitor requestMonitor) {
|
private void doInitialize(RequestMonitor requestMonitor) {
|
||||||
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
||||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||||
|
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||||
|
|
||||||
requestMonitor.done();
|
requestMonitor.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +91,41 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
|
protected boolean doIsDebuggerAttachSupported() {
|
||||||
|
// Multi-process is not applicable to post-mortem sessions (core)
|
||||||
|
// or to non-attach remote sessions.
|
||||||
|
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fBackend.getSessionType() == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> dataRm) {
|
||||||
if (procCtx instanceof IMIProcessDMContext) {
|
if (procCtx instanceof IMIProcessDMContext) {
|
||||||
if (!doIsDebuggerAttachSupported()) {
|
if (!doIsDebuggerAttachSupported()) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||||
|
dataRm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a sequence for better control of each step
|
||||||
|
ImmediateExecutor.getInstance().execute(new Sequence(getExecutor(), dataRm) {
|
||||||
|
private IMIContainerDMContext fContainerDmc;
|
||||||
|
|
||||||
|
private Step[] steps = new Step[] {
|
||||||
|
// If this is not the very first inferior, we first need create the new inferior
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(final RequestMonitor rm) {
|
||||||
|
if (fInitialProcess) {
|
||||||
|
fInitialProcess = false;
|
||||||
|
fContainerDmc = createContainerContext(procCtx, "i1"); //$NON-NLS-1$
|
||||||
rm.done();
|
rm.done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,35 +133,97 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
||||||
fCommandControl.queueCommand(
|
fCommandControl.queueCommand(
|
||||||
fCommandFactory.createMIAddInferior(controlDmc),
|
fCommandFactory.createMIAddInferior(controlDmc),
|
||||||
new DataRequestMonitor<MIAddInferiorInfo>(getExecutor(), rm) {
|
new DataRequestMonitor<MIAddInferiorInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
final String groupId = getData().getGroupId();
|
final String groupId = getData().getGroupId();
|
||||||
if (groupId == null || groupId.trim().length() == 0) {
|
if (groupId == null || groupId.trim().length() == 0) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid gdb group id.", null)); //$NON-NLS-1$
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid gdb group id.", null)); //$NON-NLS-1$
|
||||||
|
} else {
|
||||||
|
fContainerDmc = createContainerContext(procCtx, groupId);
|
||||||
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// For remote attach, we must set the binary first
|
||||||
|
// For a local attach, GDB can figure out the binary automatically,
|
||||||
|
// so we don't specify it.
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
if (fBackend.getSessionType() == SessionType.REMOTE) {
|
||||||
|
final IPath execPath = fBackend.getProgramPath();
|
||||||
|
if (execPath != null && !execPath.isEmpty()) {
|
||||||
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMIFileExecAndSymbols(fContainerDmc, execPath.toPortableString()),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final IMIContainerDMContext containerDmc = createContainerContext(procCtx, groupId);
|
rm.done();
|
||||||
fCommandControl.queueCommand(
|
}
|
||||||
fCommandFactory.createMITargetAttach(containerDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
},
|
||||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
// Now, actually do the attach
|
||||||
|
new Step() {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
public void execute(RequestMonitor rm) {
|
||||||
rm.setData(containerDmc);
|
fCommandControl.queueCommand(
|
||||||
|
fCommandFactory.createMITargetAttach(fContainerDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
||||||
|
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||||
|
}
|
||||||
|
},
|
||||||
// Start tracking this process' breakpoints.
|
// Start tracking this process' breakpoints.
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
|
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
|
||||||
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(fContainerDmc, IBreakpointsTargetDMContext.class);
|
||||||
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
// Turn on reverse debugging if it was enabled as a launch option
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
IReverseRunControl reverseService = getServicesTracker().getService(IReverseRunControl.class);
|
||||||
|
if (reverseService != null) {
|
||||||
|
ILaunch launch = (ILaunch)procCtx.getAdapter(ILaunch.class);
|
||||||
|
if (launch != null) {
|
||||||
|
try {
|
||||||
|
boolean reverseEnabled =
|
||||||
|
launch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
|
||||||
|
IGDBLaunchConfigurationConstants.DEBUGGER_REVERSE_DEFAULT);
|
||||||
|
if (reverseEnabled) {
|
||||||
|
reverseService.enableReverseMode(fCommandControl.getContext(), true, rm);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
} catch (CoreException e) {
|
||||||
|
// Ignore, just don't set reverse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Store the fully formed container context so it can be returned to the caller.
|
||||||
|
new Step() {
|
||||||
|
@Override
|
||||||
|
public void execute(RequestMonitor rm) {
|
||||||
|
dataRm.setData(fContainerDmc);
|
||||||
|
|
||||||
|
rm.done();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override public Step[] getSteps() { return steps; }
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||||
rm.done();
|
dataRm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,5 +267,41 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean doIsDebugNewProcessSupported() {
|
||||||
|
// Multi-process is not applicable to post-mortem sessions (core)
|
||||||
|
// or to non-attach remote sessions.
|
||||||
|
SessionType type = fBackend.getSessionType();
|
||||||
|
|
||||||
|
if (type == SessionType.CORE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void debugNewProcess(IDMContext dmc, String file,
|
||||||
|
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||||
|
boolean isInitial = fInitialProcess;
|
||||||
|
if (fInitialProcess) {
|
||||||
|
fInitialProcess = false;
|
||||||
|
} else {
|
||||||
|
// If we are trying to create another process than the initial one, see if we are allowed
|
||||||
|
if (!doIsDebugNewProcessSupported()) {
|
||||||
|
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Not allowed to create a new process", null)); //$NON-NLS-1$
|
||||||
|
rm.done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmediateExecutor.getInstance().execute(
|
||||||
|
new DebugNewProcessSequence_7_2(getExecutor(), isInitial, dmc, file, attributes, rm));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue