diff --git a/plugins/org.eclipse.dd.gdb.launch/.classpath b/plugins/org.eclipse.dd.gdb.launch/.classpath
new file mode 100644
index 00000000000..304e86186aa
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.gdb.launch/.project b/plugins/org.eclipse.dd.gdb.launch/.project
new file mode 100644
index 00000000000..116145f8919
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/.project
@@ -0,0 +1,28 @@
+
+
+ org.eclipse.dd.gdb.launch
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/plugins/org.eclipse.dd.gdb.launch/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.dd.gdb.launch/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..8af0c69cefb
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Mon Mar 03 11:58:56 EST 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/plugins/org.eclipse.dd.gdb.launch/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.gdb.launch/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..d63b2e1a771
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Debug Services Framework GDB Launch Plug-in
+Bundle-Vendor: Eclipse.org
+Bundle-SymbolicName: org.eclipse.dd.gdb.launch; singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.dd.dsf,
+ org.eclipse.dd.dsf.debug,
+ org.eclipse.dd.mi,
+ org.eclipse.dd.gdb,
+ org.eclipse.debug.core,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.launch,
+ org.eclipse.cdt.debug.core,
+ org.eclipse.cdt.debug.mi.core
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.eclipse.dd.gdb.launch.launching
diff --git a/plugins/org.eclipse.dd.gdb.launch/about.html b/plugins/org.eclipse.dd.gdb.launch/about.html
new file mode 100644
index 00000000000..cb740ae8bc8
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/about.html
@@ -0,0 +1,24 @@
+
+
+
+
+About
+About This Content
+
+June 5, 2007
+License
+
+The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at http://www.eclipse.org/legal/epl-v10.html .
+For purposes of the EPL, "Program" will mean the Content.
+
+If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at http://www.eclipse.org .
+
+
\ No newline at end of file
diff --git a/plugins/org.eclipse.dd.gdb.launch/build.properties b/plugins/org.eclipse.dd.gdb.launch/build.properties
new file mode 100644
index 00000000000..cf2d90c8779
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/build.properties
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ icons/,\
+ about.html
diff --git a/plugins/org.eclipse.dd.gdb.launch/plugin.xml b/plugins/org.eclipse.dd.gdb.launch/plugin.xml
new file mode 100644
index 00000000000..4b4a09485e8
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/plugin.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/internal/GdbLaunchPlugin.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/internal/GdbLaunchPlugin.java
new file mode 100644
index 00000000000..3e2a6d9e678
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/internal/GdbLaunchPlugin.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Ericsson and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ericsson - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.internal;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Query;
+import org.eclipse.dd.gdb.launch.launching.GdbLaunch;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class GdbLaunchPlugin extends Plugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
+
+ // The shared instance
+ private static GdbLaunchPlugin plugin;
+
+ private static BundleContext fgBundleContext;
+
+ /**
+ * The constructor
+ */
+ public GdbLaunchPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ fgBundleContext = context;
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ shutdownActiveLaunches();
+ plugin = null;
+ super.stop(context);
+ fgBundleContext = null;
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static GdbLaunchPlugin getDefault() {
+ return plugin;
+ }
+
+ public static BundleContext getBundleContext() {
+ return fgBundleContext;
+ }
+
+ /**
+ * Shuts down any active launches. We must shutdown any active sessions
+ * and services associated with this plugin before this plugin is stopped.
+ * Any attempts to use the plugins {@link BundleContext} after the plugin
+ * is shut down will result in exceptions.
+ */
+ private void shutdownActiveLaunches() {
+ for (ILaunch launch : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
+ if (launch instanceof GdbLaunch && ((GdbLaunch)launch).getSession().isActive()) {
+ final GdbLaunch gdbLaunch = (GdbLaunch)launch;
+
+ Query launchShutdownQuery = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ gdbLaunch.shutdownSession(rm);
+ }
+ };
+
+ try {
+ gdbLaunch.getSession().getExecutor().execute(launchShutdownQuery);
+ } catch (RejectedExecutionException e) {
+ // We can get this exception if the session is shutdown concurrently
+ // to this method running.
+ break;
+ }
+
+ // The Query.get() method is a synchronous call which blocks until the
+ // query completes.
+ try {
+ launchShutdownQuery.get();
+ } catch (InterruptedException e) {
+ getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, "InterruptedException while shutting down PDA debugger launch " + gdbLaunch, e.getCause())); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ getLog().log(new Status(IStatus.ERROR, PLUGIN_ID, "Exception while shutting down PDA debugger launch " + gdbLaunch, e.getCause())); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLaunch.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLaunch.java
new file mode 100644
index 00000000000..b98cd3783a2
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLaunch.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.launching;
+
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
+import org.eclipse.dd.dsf.concurrent.DsfExecutor;
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.service.IDsfService;
+import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.Launch;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.model.ITerminate;
+
+/**
+ * The only object in the model that implements the traditional interfaces.
+ */
+@ThreadSafe
+public class GdbLaunch extends Launch
+ implements ITerminate
+{
+ private DefaultDsfExecutor fExecutor;
+ private DsfSession fSession;
+ private DsfServicesTracker fTracker;
+ private boolean fInitialized = false;
+ private boolean fShutDown = false;
+
+
+ public GdbLaunch(ILaunchConfiguration launchConfiguration, String mode, ISourceLocator locator) {
+ super(launchConfiguration, mode, locator);
+
+ // Create the dispatch queue to be used by debugger control and services
+ // that belong to this launch
+ final DefaultDsfExecutor dsfExecutor = new DefaultDsfExecutor(GdbLocalLaunchDelegate.GDB_DEBUG_MODEL_ID);
+ dsfExecutor.prestartCoreThread();
+ fExecutor = dsfExecutor;
+ fSession = DsfSession.startSession(fExecutor, GdbLocalLaunchDelegate.GDB_DEBUG_MODEL_ID);
+ }
+
+ public DsfExecutor getDsfExecutor() { return fExecutor; }
+
+ @ConfinedToDsfExecutor("getExecutor")
+ public void initializeControl()
+ throws CoreException
+ {
+
+ Runnable initRunnable = new DsfRunnable() {
+ public void run() {
+ fTracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), fSession.getId());
+ fSession.addServiceEventListener(GdbLaunch.this, null);
+
+ fInitialized = true;
+ fireChanged();
+ }
+ };
+
+ // Invoke the execution code and block waiting for the result.
+ try {
+ fExecutor.submit(initRunnable).get();
+ } catch (InterruptedException e) {
+ new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
+ }
+ }
+
+ public DsfSession getSession() { return fSession; }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IServiceEventListener
+ @DsfServiceEventHandler public void eventDispatched(GDBControl.ExitedEvent event) {
+ shutdownSession(new RequestMonitor(ImmediateExecutor.getInstance(), null));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ITerminate
+ @Override
+ public boolean canTerminate() {
+ return super.canTerminate() && fInitialized && !fShutDown;
+ }
+
+ @Override
+ public boolean isTerminated() {
+ return super.isTerminated() || fShutDown;
+ }
+
+
+ @Override
+ public void terminate() throws DebugException {
+ if (fShutDown) return;
+ super.terminate();
+ }
+ // ITerminate
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Shuts down the services, the session and the executor associated with
+ * this launch.
+ *
+ * Note: The argument request monitor to this method should NOT use the
+ * executor that belongs to this launch. By the time the shutdown is
+ * complete, this executor will not be dispatching anymore and the
+ * request monitor will never be invoked. Instead callers should use
+ * the {@link ImmediateExecutor}.
+ *
+ * @param rm The request monitor invoked when the shutdown is complete.
+ */
+ @ConfinedToDsfExecutor("getSession().getExecutor()")
+ public void shutdownSession(final RequestMonitor rm) {
+ if (fShutDown) {
+ rm.done();
+ return;
+ }
+ fShutDown = true;
+
+ Sequence shutdownSeq = new ShutdownSequence(
+ getDsfExecutor(), fSession.getId(),
+ new RequestMonitor(fSession.getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ fSession.removeServiceEventListener(GdbLaunch.this);
+ if (!getStatus().isOK()) {
+ GdbLaunchPlugin.getDefault().getLog().log(new MultiStatus(
+ GdbLaunchPlugin.PLUGIN_ID, -1, new IStatus[]{getStatus()}, "Session shutdown failed", null)); //$NON-NLS-1$
+ }
+ // Last order of business, shutdown the dispatch queue.
+ fTracker.dispose();
+ fTracker = null;
+ DsfSession.endSession(fSession);
+ // endSession takes a full dispatch to distribute the
+ // session-ended event, finish step only after the dispatch.
+ fExecutor.shutdown();
+ fExecutor = null;
+ fireTerminate();
+
+ rm.setStatus(getStatus());
+ rm.done();
+ }
+ });
+ fExecutor.execute(shutdownSeq);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object getAdapter(Class adapter) {
+ // Must force adapters to be loaded.
+ Platform.getAdapterManager().loadAdapter(this, adapter.getName());
+ return super.getAdapter(adapter);
+ }
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLocalLaunchDelegate.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLocalLaunchDelegate.java
new file mode 100644
index 00000000000..d5e5c57f478
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbLocalLaunchDelegate.java
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.launching;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
+import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
+import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval;
+import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.command.AbstractCLIProcess;
+import org.eclipse.dd.mi.service.command.MIInferiorProcess;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
+import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
+
+/**
+ * The launch configuration delegate for the CDI debugger session types.
+ */
+@ThreadSafe
+public class GdbLocalLaunchDelegate extends AbstractCLaunchDelegate
+ implements ILaunchConfigurationDelegate2
+{
+ public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor == null ) {
+ monitor = new NullProgressMonitor();
+ }
+ if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
+ launchDebugger( config, launch, monitor );
+ }
+ }
+
+ private void launchDebugger( ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
+ monitor.beginTask("Launching debugger session", 10); //$NON-NLS-1$
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+ try {
+ String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN );
+ if ( debugMode.equals( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ) ) {
+ launchLocalDebugSession( config, launch, monitor );
+ }
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ private void launchLocalDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+ final GdbLaunch launch = (GdbLaunch)l;
+
+ monitor.subTask( "Debugging local C/C++ application" ); //$NON-NLS-1$
+ IPath exePath = verifyProgramPath( config );
+ ICProject project = verifyCProject( config );
+ if ( exePath != null ) {
+ verifyBinary( project, exePath );
+ }
+
+ setDefaultSourceLocator(launch, config);
+
+ monitor.worked( 1 );
+
+
+ // Create and invoke the launch sequence to create the debug control and services
+ final LaunchSequence launchSequence =
+ new LaunchSequence(launch.getSession(), launch, exePath);
+ launch.getSession().getExecutor().execute(launchSequence);
+ try {
+ launchSequence.get();
+ } catch (InterruptedException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
+ } catch (ExecutionException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
+ }
+
+ launch.initializeControl();
+
+ // Add the CLI and "inferior" process objects to the launch.
+ final AtomicReference cliProcessRef = new AtomicReference();
+ final AtomicReference inferiorProcessRef = new AtomicReference();
+ try {
+ launch.getDsfExecutor().submit( new Callable() {
+ public Object call() throws CoreException {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
+ GDBControl gdb = tracker.getService(GDBControl.class);
+ if (gdb != null) {
+ cliProcessRef.set(gdb.getCLIProcess());
+ inferiorProcessRef.set(gdb.getInferiorProcess());
+ }
+ tracker.dispose();
+ return null;
+ }
+ }).get();
+ launch.addProcess(DebugPlugin.newProcess(launch, cliProcessRef.get(), "gdb")); //$NON-NLS-1$
+ launch.addProcess(DebugPlugin.newProcess(launch, inferiorProcessRef.get(), exePath.lastSegment()));
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ throw (CoreException)e.getCause();
+ } catch (RejectedExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+
+ // Create a memory retrieval and register it with session
+ try {
+ launch.getDsfExecutor().submit( new Callable() {
+ public Object call() throws CoreException {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
+ GDBControl gdbControl = tracker.getService(GDBControl.class);
+ if (gdbControl != null) {
+ IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
+ GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
+ launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
+ ((DsfMemoryBlockRetrieval) memRetrieval).initialize();
+ }
+ tracker.dispose();
+ return null;
+ }
+ }).get();
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ throw (CoreException)e.getCause();
+ } catch (RejectedExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#getPluginID()
+ */
+ @Override
+ protected String getPluginID() {
+ return LaunchUIPlugin.getUniqueIdentifier();
+ }
+
+ /**
+ * Performs a runtime exec on the given command line in the context of the
+ * specified working directory, and returns the resulting process. If the
+ * current runtime does not support the specification of a working
+ * directory, the status handler for error code
+ * ERR_WORKING_DIRECTORY_NOT_SUPPORTED
is queried to see if
+ * the exec should be re-executed without specifying a working directory.
+ *
+ * @param cmdLine
+ * the command line
+ * @param workingDirectory
+ * the working directory, or null
+ * @return the resulting process or null
if the exec is
+ * cancelled
+ * @see Runtime
+ */
+ protected Process exec( String[] cmdLine, String[] environ, File workingDirectory, boolean usePty ) throws CoreException {
+ Process p = null;
+ try {
+ if ( workingDirectory == null ) {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ );
+ }
+ else {
+ if ( usePty && PTY.isSupported() ) {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory, new PTY() );
+ }
+ else {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory );
+ }
+ }
+ }
+ catch( IOException e ) {
+ if ( p != null ) {
+ p.destroy();
+ }
+ abort( "Error starting process.", e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR ); //$NON-NLS-1$
+ }
+ catch( NoSuchMethodError e ) {
+ // attempting launches on 1.2.* - no ability to set working
+ // directory
+ IStatus status = new Status( IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_NOT_SUPPORTED, LaunchMessages.getString( "LocalDsfLaunchDelegate.9" ), e ); //$NON-NLS-1$
+ IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler( status );
+ if ( handler != null ) {
+ Object result = handler.handleStatus( status, this );
+ if ( result instanceof Boolean && ((Boolean)result).booleanValue() ) {
+ p = exec( cmdLine, environ, null, usePty );
+ }
+ }
+ }
+ return p;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public boolean preLaunchCheck( ILaunchConfiguration config, String mode, IProgressMonitor monitor ) throws CoreException {
+ // no pre launch check for core file
+ if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
+ if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ) ) )
+ return true;
+ }
+ return super.preLaunchCheck( config, mode, monitor );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ILaunchConfigurationDelegate2
+ @Override
+ public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
+ return true;
+ }
+
+ @Override
+ public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
+ // Need to configure the source locator before creating the launch
+ // because once the launch is created and added to launch manager,
+ // the adapters will be created for the whole session, including
+ // the source lookup adapter.
+ ISourceLocator locator = getSourceLocator(configuration);
+
+ return new GdbLaunch(configuration, mode, locator);
+ }
+
+ private ISourceLocator getSourceLocator(ILaunchConfiguration configuration) throws CoreException {
+ String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
+ if (type == null) {
+ type = configuration.getType().getSourceLocatorId();
+ }
+ if (type != null) {
+ IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
+ String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
+ if (memento == null) {
+ locator.initializeDefaults(configuration);
+ } else {
+ if(locator instanceof IPersistableSourceLocator2)
+ ((IPersistableSourceLocator2)locator).initializeFromMemento(memento, configuration);
+ else
+ locator.initializeFromMemento(memento);
+ }
+ return locator;
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbRemoteLaunchDelegate.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbRemoteLaunchDelegate.java
new file mode 100644
index 00000000000..77f554e2b57
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/GdbRemoteLaunchDelegate.java
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Ericsson and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Ericsson - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.launching;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
+import org.eclipse.cdt.launch.internal.ui.LaunchMessages;
+import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval;
+import org.eclipse.dd.dsf.debug.service.IMemory.IMemoryDMContext;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.command.AbstractCLIProcess;
+import org.eclipse.dd.mi.service.command.MIInferiorProcess;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
+import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
+
+/**
+ * The launch configuration delegate for the CDI debugger session types.
+ */
+@ThreadSafe
+public class GdbRemoteLaunchDelegate extends AbstractCLaunchDelegate
+implements ILaunchConfigurationDelegate2
+{
+ public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.dd.gdb"; //$NON-NLS-1$
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#launch(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.debug.core.ILaunch, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor == null ) {
+ monitor = new NullProgressMonitor();
+ }
+ if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
+ launchDebugger( config, launch, monitor );
+ }
+ }
+
+ private void launchDebugger( ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
+ monitor.beginTask("Launching debugger session", 10); //$NON-NLS-1$
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+ try {
+ // Hack until we fix the tabs
+ try {
+ ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
+ wc.setAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE );
+ wc.doSave();
+ }
+ catch( CoreException e ) {
+ }
+ // END HACK
+ String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE );
+ if ( debugMode.equals( IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE ) ) {
+ launchRemoteDebugSession( config, launch, monitor );
+ }
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ private void launchRemoteDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+ final GdbLaunch launch = (GdbLaunch)l;
+
+ monitor.subTask( "Debugging remote C/C++ application" ); //$NON-NLS-1$
+ IPath exePath = verifyProgramPath( config );
+ ICProject project = verifyCProject( config );
+ if ( exePath != null ) {
+ verifyBinary( project, exePath );
+ }
+
+ setDefaultSourceLocator(launch, config);
+
+ monitor.worked( 1 );
+
+
+ // Create and invoke the launch sequence to create the debug control and services
+ final LaunchSequence launchSequence =
+ new LaunchSequence(launch.getSession(), launch, exePath);
+ launch.getSession().getExecutor().execute(launchSequence);
+ try {
+ launchSequence.get();
+ } catch (InterruptedException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
+ } catch (ExecutionException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in launch sequence", e1.getCause())); //$NON-NLS-1$
+ }
+
+ launch.initializeControl();
+
+ // Add the CLI and "inferior" process objects to the launch.
+ final AtomicReference cliProcessRef = new AtomicReference();
+ final AtomicReference inferiorProcessRef = new AtomicReference();
+ try {
+ launch.getDsfExecutor().submit( new Callable() {
+ public Object call() throws CoreException {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
+ GDBControl gdb = tracker.getService(GDBControl.class);
+ if (gdb != null) {
+ cliProcessRef.set(gdb.getCLIProcess());
+ inferiorProcessRef.set(gdb.getInferiorProcess());
+ }
+ tracker.dispose();
+ return null;
+ }
+ }).get();
+ launch.addProcess(DebugPlugin.newProcess(launch, cliProcessRef.get(), "gdb")); //$NON-NLS-1$
+ launch.addProcess(DebugPlugin.newProcess(launch, inferiorProcessRef.get(), exePath.lastSegment()));
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ throw (CoreException)e.getCause();
+ } catch (RejectedExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+
+ // Create a memory retrieval and register it with session
+ try {
+ launch.getDsfExecutor().submit( new Callable() {
+ public Object call() throws CoreException {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), launch.getSession().getId());
+ GDBControl gdbControl = tracker.getService(GDBControl.class);
+ if (gdbControl != null) {
+ IMemoryBlockRetrieval memRetrieval = new DsfMemoryBlockRetrieval(
+ GDB_DEBUG_MODEL_ID, config, (IMemoryDMContext)gdbControl.getControlDMContext());
+ launch.getSession().registerModelAdapter(IMemoryBlockRetrieval.class, memRetrieval);
+ ((DsfMemoryBlockRetrieval) memRetrieval).initialize();
+ }
+ tracker.dispose();
+ return null;
+ }
+ }).get();
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Interrupted while waiting for get process callable.", e)); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ throw (CoreException)e.getCause();
+ } catch (RejectedExecutionException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#getPluginID()
+ */
+ @Override
+ protected String getPluginID() {
+ return LaunchUIPlugin.getUniqueIdentifier();
+ }
+
+ /**
+ * Performs a runtime exec on the given command line in the context of the
+ * specified working directory, and returns the resulting process. If the
+ * current runtime does not support the specification of a working
+ * directory, the status handler for error code
+ * ERR_WORKING_DIRECTORY_NOT_SUPPORTED
is queried to see if
+ * the exec should be re-executed without specifying a working directory.
+ *
+ * @param cmdLine
+ * the command line
+ * @param workingDirectory
+ * the working directory, or null
+ * @return the resulting process or null
if the exec is
+ * cancelled
+ * @see Runtime
+ */
+ protected Process exec( String[] cmdLine, String[] environ, File workingDirectory, boolean usePty ) throws CoreException {
+ Process p = null;
+ try {
+ if ( workingDirectory == null ) {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ );
+ }
+ else {
+ if ( usePty && PTY.isSupported() ) {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory, new PTY() );
+ }
+ else {
+ p = ProcessFactory.getFactory().exec( cmdLine, environ, workingDirectory );
+ }
+ }
+ }
+ catch( IOException e ) {
+ if ( p != null ) {
+ p.destroy();
+ }
+ abort( "Error starting process.", e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR ); //$NON-NLS-1$
+ }
+ catch( NoSuchMethodError e ) {
+ // attempting launches on 1.2.* - no ability to set working
+ // directory
+ IStatus status = new Status( IStatus.ERROR, LaunchUIPlugin.getUniqueIdentifier(), ICDTLaunchConfigurationConstants.ERR_WORKING_DIRECTORY_NOT_SUPPORTED, LaunchMessages.getString( "LocalDsfLaunchDelegate.9" ), e ); //$NON-NLS-1$
+ IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler( status );
+ if ( handler != null ) {
+ Object result = handler.handleStatus( status, this );
+ if ( result instanceof Boolean && ((Boolean)result).booleanValue() ) {
+ p = exec( cmdLine, environ, null, usePty );
+ }
+ }
+ }
+ return p;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.launch.AbstractCLaunchDelegate#preLaunchCheck(org.eclipse.debug.core.ILaunchConfiguration, java.lang.String, org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public boolean preLaunchCheck( ILaunchConfiguration config, String mode, IProgressMonitor monitor ) throws CoreException {
+ // no pre launch check for core file
+ if ( mode.equals( ILaunchManager.DEBUG_MODE ) ) {
+ if ( ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN ) ) )
+ return true;
+ }
+ return super.preLaunchCheck( config, mode, monitor );
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // ILaunchConfigurationDelegate2
+ @Override
+ public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
+ return false;
+ }
+
+ @Override
+ public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
+ return true;
+ }
+
+ @Override
+ public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
+ // Need to configure the source locator before creating the launch
+ // because once the launch is created and added to launch manager,
+ // the adapters will be created for the whole session, including
+ // the source lookup adapter.
+ ISourceLocator locator = getSourceLocator(configuration);
+
+ return new GdbLaunch(configuration, mode, locator);
+ }
+
+ private ISourceLocator getSourceLocator(ILaunchConfiguration configuration) throws CoreException {
+ String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
+ if (type == null) {
+ type = configuration.getType().getSourceLocatorId();
+ }
+ if (type != null) {
+ IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
+ String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
+ if (memento == null) {
+ locator.initializeDefaults(configuration);
+ } else {
+ if(locator instanceof IPersistableSourceLocator2)
+ ((IPersistableSourceLocator2)locator).initializeFromMemento(memento, configuration);
+ else
+ locator.initializeFromMemento(memento);
+ }
+ return locator;
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/IGDBLaunchConfigurationConstants.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/IGDBLaunchConfigurationConstants.java
new file mode 100644
index 00000000000..fff7667d916
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/IGDBLaunchConfigurationConstants.java
@@ -0,0 +1,7 @@
+package org.eclipse.dd.gdb.launch.launching;
+
+public class IGDBLaunchConfigurationConstants {
+
+ public static final String DEBUGGER_MODE_REMOTE = "remote";
+
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/LaunchSequence.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/LaunchSequence.java
new file mode 100644
index 00000000000..624517fad07
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/LaunchSequence.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.launching;
+
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
+import org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.debug.service.StepQueueManager;
+import org.eclipse.dd.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
+import org.eclipse.dd.gdb.service.GDBRunControl;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.CSourceLookup;
+import org.eclipse.dd.mi.service.ExpressionService;
+import org.eclipse.dd.mi.service.MIBreakpoints;
+import org.eclipse.dd.mi.service.MIBreakpointsManager;
+import org.eclipse.dd.mi.service.MIDisassembly;
+import org.eclipse.dd.mi.service.MIMemory;
+import org.eclipse.dd.mi.service.MIModules;
+import org.eclipse.dd.mi.service.MIRegisters;
+import org.eclipse.dd.mi.service.MIStack;
+import org.eclipse.dd.mi.service.command.commands.MIBreakInsert;
+import org.eclipse.dd.mi.service.command.commands.MIExecRun;
+import org.eclipse.dd.mi.service.command.output.MIBreakInsertInfo;
+import org.eclipse.dd.mi.service.command.output.MIInfo;
+import org.eclipse.debug.core.DebugException;
+
+public class LaunchSequence extends Sequence {
+
+ Step[] fSteps = new Step[] {
+ // Create and initialize the Connection service.
+ new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ //
+ // Create the connection.
+ //
+ fCommandControl = new GDBControl(
+ fSession, getGDBPath(), fExecPath, GDBControl.SessionType.RUN, 30);
+ fCommandControl.initialize(requestMonitor);
+ }
+ },
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new GDBRunControl(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new StepQueueManager(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new MIMemory(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new MIModules(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new MIStack(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new ExpressionService(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fSourceLookup = new CSourceLookup(fSession);
+ fSourceLookup.initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fSourceLookup.setSourceLookupDirector(
+ fCommandControl.getGDBDMContext(),
+ ((CSourceLookupDirector)fLaunch.getSourceLocator()));
+ requestMonitor.done();
+ }},
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ // Create the low-level breakpoint service
+ final MIBreakpoints bpService = new MIBreakpoints(fSession);
+ bpService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+ requestMonitor.done();
+ }
+ });
+ }},
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ // Create high-level breakpoint service and install breakpoints
+ // for the GDB debug context.
+ final MIBreakpointsManager bpmService = new MIBreakpointsManager(fSession, CDebugCorePlugin.PLUGIN_ID);
+ bpmService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+ bpmService.startTrackingBreakpoints(fCommandControl.getGDBDMContext(), requestMonitor);
+ }
+ });
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new MIRegisters(fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ new MIDisassembly(fSession).initialize(requestMonitor);
+ }},
+ /*
+ * If needed, insert breakpoint at main and run to it.
+ */
+ new Step() {
+ private boolean fStopInMain = false;
+ private String fStopSymbol = null;
+
+ /**
+ * @return The return value actually indicates whether the get operation succeeded,
+ * not whether to stop.
+ */
+ private boolean readStopAtMain(RequestMonitor requestMonitor) {
+ try {
+ fStopInMain = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, -1, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean readStopSymbol(RequestMonitor requestMonitor) {
+ try {
+ fStopSymbol = fLaunch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL, ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT );
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ if (!readStopAtMain(requestMonitor)) return;
+ if (!fStopInMain) {
+ // Just start the program.
+ fCommandControl.queueCommand(
+ new MIExecRun((IContainerDMContext)fCommandControl.getControlDMContext(), new String[0]),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+ requestMonitor.done();
+ }
+ }
+ );
+ } else {
+ if (!readStopSymbol(requestMonitor)) return;
+
+ // Insert a breakpoint at the requested stop symbol.
+ fCommandControl.queueCommand(
+ new MIBreakInsert(
+ (IBreakpointsTargetDMContext)fCommandControl.getControlDMContext(),
+ true, false, null, 0, fStopSymbol, 0),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+
+ // After the break-insert is done, execute the -exec-run command.
+ fCommandControl.queueCommand(
+ new MIExecRun((IContainerDMContext)fCommandControl.getControlDMContext(), new String[0]),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleOK() {
+ requestMonitor.done();
+ }
+ }
+ );
+ }
+ });
+ }
+ }
+ },
+ };
+
+ DsfSession fSession;
+ GdbLaunch fLaunch;
+ IPath fExecPath;
+
+ GDBControl fCommandControl;
+ CSourceLookup fSourceLookup;
+
+ public LaunchSequence(DsfSession session, GdbLaunch launch, IPath execPath) {
+ super(session.getExecutor());
+ fSession = session;
+ fLaunch = launch;
+ fExecPath = execPath;
+ }
+
+ @Override
+ public Step[] getSteps() {
+ return fSteps;
+ }
+
+ private IPath getGDBPath() {
+ IPath retVal = new Path("gdb.exe"); //$NON-NLS-1$
+ try {
+ retVal = new Path( fLaunch.getLaunchConfiguration().getAttribute( IMILaunchConfigurationConstants.ATTR_DEBUG_NAME, IMILaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT ) );
+ } catch (CoreException e) {
+ }
+ return retVal;
+ }
+
+}
diff --git a/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/ShutdownSequence.java b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/ShutdownSequence.java
new file mode 100644
index 00000000000..4ddab9e913f
--- /dev/null
+++ b/plugins/org.eclipse.dd.gdb.launch/src/org/eclipse/dd/gdb/launch/launching/ShutdownSequence.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2006 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.dd.gdb.launch.launching;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.DsfExecutor;
+import org.eclipse.dd.dsf.concurrent.RequestMonitor;
+import org.eclipse.dd.dsf.concurrent.Sequence;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.IDsfService;
+import org.eclipse.dd.gdb.launch.internal.GdbLaunchPlugin;
+import org.eclipse.dd.gdb.service.GDBRunControl;
+import org.eclipse.dd.gdb.service.command.GDBControl;
+import org.eclipse.dd.mi.service.CSourceLookup;
+import org.eclipse.dd.mi.service.ExpressionService;
+import org.eclipse.dd.mi.service.MIBreakpoints;
+import org.eclipse.dd.mi.service.MIBreakpointsManager;
+import org.eclipse.dd.mi.service.MIDisassembly;
+import org.eclipse.dd.mi.service.MIMemory;
+import org.eclipse.dd.mi.service.MIModules;
+import org.eclipse.dd.mi.service.MIRegisters;
+import org.eclipse.dd.mi.service.MIStack;
+
+public class ShutdownSequence extends Sequence {
+
+ String fSessionId;
+
+ String fApplicationName;
+
+ String fDebugModelId;
+
+ DsfServicesTracker fTracker;
+
+ public ShutdownSequence(DsfExecutor executor, String sessionId, RequestMonitor requestMonitor) {
+ super(executor, requestMonitor);
+ fSessionId = sessionId;
+ }
+
+ @Override
+ public Step[] getSteps() {
+ return fSteps;
+ }
+
+ private final Step[] fSteps = new Step[] { new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ assert GdbLaunchPlugin.getBundleContext() != null;
+ fTracker = new DsfServicesTracker(GdbLaunchPlugin.getBundleContext(), fSessionId);
+ requestMonitor.done();
+ }
+
+ @Override
+ public void rollBack(RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIDisassembly.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIRegisters.class, requestMonitor);
+ }
+// TODO: As Pawel about the necessity of this step
+// Not clear on the purpose of this step since the next one does it also
+// (stopTrackingBreakpoints() is called as part of the shutdown method)
+// Besides, the run control is already gone so removing breakpoints from
+// the back-end is bound to fail...
+// }, new Step() {
+// @Override
+// public void execute(final RequestMonitor requestMonitor) {
+// MIBreakpointsManager bpm = fTracker.getService(MIBreakpointsManager.class);
+// GDBControl commandControl = fTracker.getService(GDBControl.class);
+// if (bpm != null && commandControl != null) {
+// bpm.stopTrackingBreakpoints(
+// commandControl.getGDBDMContext(),
+// new RequestMonitor(getExecutor(), requestMonitor) {
+// @Override
+// protected void handleCompleted() {
+// // If un-installing breakpoints fails, log the error but continue shutting down.
+// if (!getStatus().isOK()) {
+// DsfGdbLaunchPlugin.getDefault().getLog().log(getStatus());
+// }
+// requestMonitor.done();
+// }
+// });
+// } else {
+// requestMonitor.setStatus(new Status(IStatus.ERROR, DsfGdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
+// "Needed services not found.", null)); //$NON-NLS-1$
+// requestMonitor.done();
+// }
+// }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIBreakpointsManager.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIBreakpoints.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(CSourceLookup.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(ExpressionService.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIStack.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIModules.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIMemory.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(GDBRunControl.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(GDBControl.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
+ } };
+
+ @SuppressWarnings("unchecked")
+ private void shutdownService(Class clazz, final RequestMonitor requestMonitor) {
+ IDsfService service = fTracker.getService(clazz);
+ if (service != null) {
+ service.shutdown(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleCompleted() {
+ if (!getStatus().isOK()) {
+ GdbLaunchPlugin.getDefault().getLog().log(getStatus());
+ }
+ requestMonitor.done();
+ }
+ });
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbLaunchPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
+ "Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$
+ requestMonitor.done();
+ }
+ }
+}