mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-21 21:52:10 +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
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* 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.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
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.RequestMonitor;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||
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.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
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.ITraceTargetDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
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.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;
|
||||
|
@ -63,6 +58,9 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
private SessionType fSessionType;
|
||||
private boolean fAttach;
|
||||
|
||||
// The launchConfiguration attributes
|
||||
private Map<String, Object> fAttributes;
|
||||
|
||||
private IGDBControl fCommandControl;
|
||||
private IGDBBackend fGDBBackend;
|
||||
private IMIProcesses fProcService;
|
||||
|
@ -82,22 +80,24 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
if (GROUP_TOP_LEVEL.equals(group)) {
|
||||
return new String[] {
|
||||
"stepInitializeFinalLaunchSequence", //$NON-NLS-1$
|
||||
// Global GDB settings
|
||||
"stepSetEnvironmentDirectory", //$NON-NLS-1$
|
||||
"stepSetBreakpointPending", //$NON-NLS-1$
|
||||
"stepEnablePrettyPrinting", //$NON-NLS-1$
|
||||
"stepSourceGDBInitFile", //$NON-NLS-1$
|
||||
"stepSetEnvironmentVariables", //$NON-NLS-1$
|
||||
"stepSetExecutable", //$NON-NLS-1$
|
||||
"stepSetArguments", //$NON-NLS-1$
|
||||
"stepSetNonStop", //$NON-NLS-1$
|
||||
"stepSetAutoLoadSharedLibrarySymbols", //$NON-NLS-1$
|
||||
"stepSetSharedLibraryPaths", //$NON-NLS-1$
|
||||
"stepSetSourceLookupPath", //$NON-NLS-1$
|
||||
// For post-mortem launch only
|
||||
"stepSpecifyCoreFile", //$NON-NLS-1$
|
||||
// For remote-attach launch only
|
||||
"stepRemoteConnection", //$NON-NLS-1$
|
||||
// For all launches except attach ones
|
||||
"stepNewProcess", //$NON-NLS-1$
|
||||
// For local attach launch only
|
||||
"stepAttachToProcess", //$NON-NLS-1$
|
||||
"stepStartTrackingBreakpoints", //$NON-NLS-1$
|
||||
"stepStartExecution", //$NON-NLS-1$
|
||||
// Global
|
||||
"stepDataModelInitializationComplete", //$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.
|
||||
* @since 4.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Execute
|
||||
public void stepInitializeFinalLaunchSequence(RequestMonitor requestMonitor) {
|
||||
fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
|
||||
|
@ -136,6 +137,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
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();
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
* @since 4.0
|
||||
*/
|
||||
@Execute
|
||||
public void stepSetNonStop(final RequestMonitor requestMonitor) {
|
||||
boolean isNonStop = false;
|
||||
try {
|
||||
isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
boolean isNonStop = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
|
||||
|
||||
// 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.
|
||||
|
@ -365,16 +299,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
*/
|
||||
@Execute
|
||||
public void stepSetAutoLoadSharedLibrarySymbols(RequestMonitor requestMonitor) {
|
||||
try {
|
||||
boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
|
||||
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();
|
||||
}
|
||||
boolean autolib = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -476,10 +408,14 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
@Execute
|
||||
public void stepSpecifyCoreFile(final RequestMonitor requestMonitor) {
|
||||
if (fSessionType == SessionType.CORE) {
|
||||
try {
|
||||
String coreFile = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_COREFILE_PATH, ""); //$NON-NLS-1$
|
||||
final String coreType = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_POST_MORTEM_TYPE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_POST_MORTEM_TYPE_DEFAULT);
|
||||
String coreFile = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
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);
|
||||
|
||||
if (coreFile.length() == 0) {
|
||||
new PromptForCoreJob(
|
||||
"Prompt for post mortem file", //$NON-NLS-1$
|
||||
|
@ -530,124 +466,93 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
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 {
|
||||
requestMonitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private final static String INVALID = "invalid"; //$NON-NLS-1$
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@Execute
|
||||
public void stepRemoteConnection(final RequestMonitor requestMonitor) {
|
||||
if (fSessionType == SessionType.REMOTE) {
|
||||
if (!checkConnectionType(requestMonitor)) return;
|
||||
public void stepRemoteConnection(final RequestMonitor rm) {
|
||||
if (fSessionType == SessionType.REMOTE && fAttach) {
|
||||
boolean isTcpConnection = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
||||
false);
|
||||
|
||||
if (fTcpConnection) {
|
||||
if (!getTcpHost(requestMonitor)) return;
|
||||
if (!getTcpPort(requestMonitor)) return;
|
||||
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(),
|
||||
fRemoteTcpHost, fRemoteTcpPort, fAttach),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
remoteTcpHost, remoteTcpPort, true),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||
} else {
|
||||
if (!getSerialDevice(requestMonitor)) return;
|
||||
String serialDevice = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEV, INVALID);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||
fSerialDevice, fAttach),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor));
|
||||
serialDevice, true),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||
}
|
||||
} 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
|
||||
*/
|
||||
@Execute
|
||||
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 we are attaching, get the process id.
|
||||
int pid = -1;
|
||||
try {
|
||||
// have we already been given the pid (maybe from a JUnit test launch or something)
|
||||
pid = fLaunch.getLaunchConfiguration().getAttribute(ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
|
||||
} catch (CoreException e) {
|
||||
// do nothing and fall to below
|
||||
}
|
||||
// Is the process id already stored in the launch?
|
||||
int pid = CDebugUtils.getAttribute(
|
||||
fAttributes,
|
||||
ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID, -1);
|
||||
|
||||
if (pid != -1) {
|
||||
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.
|
||||
* @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.ICDTLaunchConfigurationConstants;
|
||||
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.datamodel.DMContexts;
|
||||
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.IMIProcessDMContext;
|
||||
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.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.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -200,22 +203,51 @@ public class GDBProcesses extends MIProcesses implements IGDBProcesses {
|
|||
|
||||
@Override
|
||||
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
|
||||
super.attachDebuggerToProcess(
|
||||
procCtx,
|
||||
new DataRequestMonitor<IDMContext>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdb.setConnected(true);
|
||||
// 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.
|
||||
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (inferiorProcess != null) {
|
||||
inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
||||
}
|
||||
IMIContainerDMContext containerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||
|
||||
rm.setData(getData());
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
DataRequestMonitor<MIInfo> attachRm = new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
GDBProcesses.super.attachDebuggerToProcess(
|
||||
procCtx,
|
||||
new DataRequestMonitor<IDMContext>(ImmediateExecutor.getInstance(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
fGdb.setConnected(true);
|
||||
|
||||
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
|
||||
if (inferiorProcess != null) {
|
||||
inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
|
||||
}
|
||||
|
||||
IDMContext containerDmc = getData();
|
||||
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
|
||||
|
@ -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
|
||||
public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor<IDMContext[]> rm) {
|
||||
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.Immutable;
|
||||
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.AbstractDMEvent;
|
||||
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.ICommandControlService.ICommandControlDMContext;
|
||||
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.service.command.IGDBControl;
|
||||
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.IMIProcessDMContext;
|
||||
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.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.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
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 boolean fInitialProcess = true;
|
||||
|
||||
public GDBProcesses_7_0(DsfSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
@ -639,8 +646,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
} else if (name.length() == 0) {
|
||||
// Probably will not happen, but just in case...use the
|
||||
// binary file name (absolute path)
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
name = backend.getProgramPath().toOSString();
|
||||
name = fBackend.getProgramPath().toOSString();
|
||||
fDebuggedProcessesAndNames.put(id, name);
|
||||
}
|
||||
}
|
||||
|
@ -702,11 +708,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
|
||||
/** @since 4.0 */
|
||||
protected boolean doIsDebuggerAttachSupported() {
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
if (backend != null) {
|
||||
return backend.getIsAttachSession();
|
||||
}
|
||||
return false;
|
||||
return fBackend.getIsAttachSession() && !fCommandControl.isConnected();
|
||||
}
|
||||
|
||||
public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
|
||||
|
@ -714,39 +716,102 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
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 (!doIsDebuggerAttachSupported()) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||
dataRm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
// By now, GDB has reported the groupId that was attached to this process
|
||||
rm.setData(createContainerContext(procCtx, getGroupFromPid(((IMIProcessDMContext)procCtx).getProcId())));
|
||||
rm.done();
|
||||
}
|
||||
});
|
||||
// Use a sequence for better control of each step
|
||||
ImmediateExecutor.getInstance().execute(new Sequence(getExecutor(), dataRm) {
|
||||
|
||||
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
|
||||
public void execute(RequestMonitor rm) {
|
||||
// There is no groupId until we attach, so we can use the default groupId
|
||||
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();
|
||||
}
|
||||
},
|
||||
// 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);
|
||||
|
||||
// Start tracking breakpoints.
|
||||
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();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@Override public Step[] getSteps() { return steps; }
|
||||
});
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
dataRm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
protected boolean doCanDetachDebuggerFromProcess() {
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
if (backend != null) {
|
||||
return backend.getIsAttachSession() && fCommandControl.isConnected();
|
||||
}
|
||||
return false;
|
||||
return fBackend.getIsAttachSession() && fCommandControl.isConnected();
|
||||
}
|
||||
|
||||
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) {
|
||||
rm.setData(false);
|
||||
rm.setData(doIsDebugNewProcessSupported());
|
||||
rm.done();
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
protected boolean doIsDebugNewProcessSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void debugNewProcess(IDMContext dmc, String file,
|
||||
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
|
||||
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
if (!fInitialProcess) {
|
||||
// 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();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fInitialProcess = false;
|
||||
ImmediateExecutor.getInstance().execute(
|
||||
new DebugNewProcessSequence(getExecutor(), dmc, file, attributes, 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
|
||||
// we're debugging remotely, the user is out
|
||||
// of luck
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
if (backend.getSessionType() == SessionType.LOCAL) {
|
||||
if (fBackend.getSessionType() == SessionType.LOCAL) {
|
||||
IProcessList list = null;
|
||||
try {
|
||||
list = CCorePlugin.getDefault().getProcessList();
|
||||
|
@ -1185,8 +1263,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
|
|||
// Looks like this gdb doesn't truly support
|
||||
// "-list-thread-groups --available". Get the
|
||||
// process list natively if we're debugging locally
|
||||
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
|
||||
if (backend.getSessionType() == SessionType.LOCAL) {
|
||||
if (fBackend.getSessionType() == SessionType.LOCAL) {
|
||||
IProcessList list = null;
|
||||
try {
|
||||
list = CCorePlugin.getDefault().getProcessList();
|
||||
|
|
|
@ -10,12 +10,17 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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.Sequence;
|
||||
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.command.ICommandControlService.ICommandControlDMContext;
|
||||
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;
|
||||
|
@ -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.MIInfo;
|
||||
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.Status;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
|
||||
/**
|
||||
* 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 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) {
|
||||
super(session);
|
||||
|
@ -64,6 +80,8 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
|||
private void doInitialize(RequestMonitor requestMonitor) {
|
||||
fCommandControl = getServicesTracker().getService(IGDBControl.class);
|
||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||
fBackend = getServicesTracker().getService(IGDBBackend.class);
|
||||
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
|
@ -72,47 +90,140 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
|||
super.shutdown(requestMonitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
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> rm) {
|
||||
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> dataRm) {
|
||||
if (procCtx instanceof IMIProcessDMContext) {
|
||||
if (!doIsDebuggerAttachSupported()) {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
|
||||
dataRm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIAddInferior(controlDmc),
|
||||
new DataRequestMonitor<MIAddInferiorInfo>(getExecutor(), 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, INTERNAL_ERROR, "Invalid gdb group id.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
// Use a sequence for better control of each step
|
||||
ImmediateExecutor.getInstance().execute(new Sequence(getExecutor(), dataRm) {
|
||||
private IMIContainerDMContext fContainerDmc;
|
||||
|
||||
final IMIContainerDMContext containerDmc = createContainerContext(procCtx, groupId);
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetAttach(containerDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
||||
new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
rm.setData(containerDmc);
|
||||
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();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start tracking this process' breakpoints.
|
||||
MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);
|
||||
IBreakpointsTargetDMContext bpTargetDmc = DMContexts.getAncestorOfType(containerDmc, IBreakpointsTargetDMContext.class);
|
||||
bpmService.startTrackingBreakpoints(bpTargetDmc, rm);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMIAddInferior(controlDmc),
|
||||
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, INTERNAL_ERROR, "Invalid gdb group id.", null)); //$NON-NLS-1$
|
||||
} else {
|
||||
fContainerDmc = createContainerContext(procCtx, groupId);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
rm.done();
|
||||
}
|
||||
},
|
||||
// Now, actually do the attach
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetAttach(fContainerDmc, ((IMIProcessDMContext)procCtx).getProcId()),
|
||||
new DataRequestMonitor<MIInfo>(ImmediateExecutor.getInstance(), rm));
|
||||
}
|
||||
},
|
||||
// Start tracking this process' breakpoints.
|
||||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
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();
|
||||
}
|
||||
},
|
||||
// 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 {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
rm.done();
|
||||
dataRm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
|
||||
dataRm.done();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,5 +267,41 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 {
|
|||
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