diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.classpath b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.classpath
new file mode 100644
index 00000000000..304e86186aa
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.project b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.project
new file mode 100644
index 00000000000..3e2c012e7ff
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.project
@@ -0,0 +1,34 @@
+
+
+ org.eclipse.cdt.dsf.gdb.ui
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.pde.api.tools.apiAnalysisBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.pde.api.tools.apiAnalysisNature
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/.api_filters b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/.api_filters
new file mode 100644
index 00000000000..f17a60ee7f9
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/.api_filters
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/org.eclipse.jdt.core.prefs b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..e2b74ae779a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,70 @@
+#Tue Jun 24 11:04:56 PDT 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..6165783264e
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,27 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb.ui;singleton:=true
+Bundle-Version: 2.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.cdt.dsf,
+ org.eclipse.cdt.dsf.ui,
+ org.eclipse.debug.ui,
+ org.eclipse.cdt.debug.core,
+ org.eclipse.cdt.dsf.gdb,
+ org.eclipse.cdt.debug.ui,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.core.variables
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.eclipse.cdt.dsf.gdb.internal.ui.actions;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.breakpoints;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.launching;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;x-internal:=true,
+ org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch;x-internal:=true
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/about.html b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/about.html
new file mode 100644
index 00000000000..cb740ae8bc8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/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/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/build.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/build.properties
new file mode 100644
index 00000000000..4b33d1a92e1
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/build.properties
@@ -0,0 +1,18 @@
+###############################################################################
+# Copyright (c) 2006, 2008 Wind River Systems and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Wind River Systems - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ about.html,\
+ icons/,\
+ plugin.properties
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/c_app.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/c_app.gif
new file mode 100644
index 00000000000..805a1d0ab8b
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/c_app.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/connect.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/connect.gif
new file mode 100755
index 00000000000..866ad338250
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/connect.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/exec_obj.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/exec_obj.gif
new file mode 100644
index 00000000000..7b3a92e0906
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/exec_obj.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/arguments_tab.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/arguments_tab.gif
new file mode 100644
index 00000000000..44660b5f0b5
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/arguments_tab.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugger_tab.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugger_tab.gif
new file mode 100644
index 00000000000..d90a29fead8
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/debugger_tab.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/main_tab.gif b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/main_tab.gif
new file mode 100644
index 00000000000..b226e41c527
Binary files /dev/null and b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/view16/main_tab.gif differ
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
new file mode 100644
index 00000000000..affa7716080
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# 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
+###############################################################################
+pluginName=GDB DSF Debugger Integration UI
+providerName=Eclipse.org
+
+action.connect.label = Connect...
+action.connect.tooltip = Connect to a process
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
new file mode 100644
index 00000000000..2b4ad5f4e77
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java
new file mode 100644
index 00000000000..6dd3e7cb61c
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.eclipse.cdt.debug.core.model.IRestart;
+import org.eclipse.cdt.debug.core.model.ISteppingModeTarget;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfResumeCommand;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepIntoCommand;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepOverCommand;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfStepReturnCommand;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfSteppingModeTarget;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfSuspendCommand;
+import org.eclipse.cdt.dsf.debug.ui.contexts.DsfSuspendTrigger;
+import org.eclipse.cdt.dsf.debug.ui.sourcelookup.DsfSourceDisplayAdapter;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.DefaultRefreshAllTarget;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.IRefreshAllTarget;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.DefaultDsfModelSelectionPolicyFactory;
+import org.eclipse.cdt.dsf.gdb.actions.IConnect;
+import org.eclipse.cdt.dsf.gdb.internal.ui.actions.DsfTerminateCommand;
+import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbConnectCommand;
+import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbDisconnectCommand;
+import org.eclipse.cdt.dsf.gdb.internal.ui.actions.GdbRestartCommand;
+import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.GdbViewModelAdapter;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.IAdapterFactory;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.debug.core.commands.IDisconnectHandler;
+import org.eclipse.debug.core.commands.IResumeHandler;
+import org.eclipse.debug.core.commands.IStepIntoHandler;
+import org.eclipse.debug.core.commands.IStepOverHandler;
+import org.eclipse.debug.core.commands.IStepReturnHandler;
+import org.eclipse.debug.core.commands.ISuspendHandler;
+import org.eclipse.debug.core.commands.ITerminateHandler;
+import org.eclipse.debug.core.model.IDebugModelProvider;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory;
+import org.eclipse.debug.ui.contexts.ISuspendTrigger;
+import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
+
+/**
+ * This implementation of platform adapter factory only retrieves the adapters
+ * for the launch object. But it also manages the creation and destruction
+ * of the session-based adapters which are returned by the
+ * IDMContext.getAdapter() methods.
+ */
+@ThreadSafe
+@SuppressWarnings({"restriction"})
+public class GdbAdapterFactory
+ implements IAdapterFactory, ILaunchesListener2
+{
+ @Immutable
+ class SessionAdapterSet {
+ final GdbLaunch fLaunch;
+ final GdbViewModelAdapter fViewModelAdapter;
+ final DsfSourceDisplayAdapter fSourceDisplayAdapter;
+ final DsfStepIntoCommand fStepIntoCommand;
+ final DsfStepOverCommand fStepOverCommand;
+ final DsfStepReturnCommand fStepReturnCommand;
+ final DsfSuspendCommand fSuspendCommand;
+ final DsfResumeCommand fResumeCommand;
+ final GdbRestartCommand fRestartCommand;
+ final DsfTerminateCommand fTerminateCommand;
+ final GdbConnectCommand fConnectCommand;
+ final GdbDisconnectCommand fDisconnectCommand;
+ final IDebugModelProvider fDebugModelProvider;
+ final DsfSuspendTrigger fSuspendTrigger;
+ final DsfSteppingModeTarget fSteppingModeTarget;
+ final IModelSelectionPolicyFactory fModelSelectionPolicyFactory;
+ final SteppingController fSteppingController;
+ final DefaultRefreshAllTarget fRefreshAllTarget;
+
+ SessionAdapterSet(GdbLaunch launch) {
+ fLaunch = launch;
+ DsfSession session = launch.getSession();
+
+ // register stepping controller
+ fSteppingController = new SteppingController(session);
+ session.registerModelAdapter(SteppingController.class, fSteppingController);
+
+ fViewModelAdapter = new GdbViewModelAdapter(session, fSteppingController);
+
+ if (launch.getSourceLocator() instanceof ISourceLookupDirector) {
+ fSourceDisplayAdapter = new DsfSourceDisplayAdapter(session, (ISourceLookupDirector)launch.getSourceLocator(), fSteppingController);
+ } else {
+ fSourceDisplayAdapter = null;
+ }
+ session.registerModelAdapter(ISourceDisplay.class, fSourceDisplayAdapter);
+
+ fSteppingModeTarget= new DsfSteppingModeTarget();
+ fStepIntoCommand = new DsfStepIntoCommand(session, fSteppingModeTarget);
+ fStepOverCommand = new DsfStepOverCommand(session, fSteppingModeTarget);
+ fStepReturnCommand = new DsfStepReturnCommand(session);
+ fSuspendCommand = new DsfSuspendCommand(session);
+ fResumeCommand = new DsfResumeCommand(session);
+ fRestartCommand = new GdbRestartCommand(session, fLaunch);
+ fTerminateCommand = new DsfTerminateCommand(session);
+ fConnectCommand = new GdbConnectCommand(session);
+ fDisconnectCommand = new GdbDisconnectCommand(session);
+ fSuspendTrigger = new DsfSuspendTrigger(session, fLaunch);
+ fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory();
+ fRefreshAllTarget = new DefaultRefreshAllTarget();
+
+ session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget);
+ session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand);
+ session.registerModelAdapter(IStepOverHandler.class, fStepOverCommand);
+ session.registerModelAdapter(IStepReturnHandler.class, fStepReturnCommand);
+ session.registerModelAdapter(ISuspendHandler.class, fSuspendCommand);
+ session.registerModelAdapter(IResumeHandler.class, fResumeCommand);
+ session.registerModelAdapter(IRestart.class, fRestartCommand);
+ session.registerModelAdapter(ITerminateHandler.class, fTerminateCommand);
+ session.registerModelAdapter(IConnect.class, fConnectCommand);
+ session.registerModelAdapter(IDisconnectHandler.class, fDisconnectCommand);
+ session.registerModelAdapter(IModelSelectionPolicyFactory.class, fModelSelectionPolicyFactory);
+ session.registerModelAdapter(IRefreshAllTarget.class, fRefreshAllTarget);
+
+ fDebugModelProvider = new IDebugModelProvider() {
+ // @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers()
+ public String[] getModelIdentifiers() {
+ return new String[] { GdbLaunchDelegate.GDB_DEBUG_MODEL_ID };
+ }
+ };
+ session.registerModelAdapter(IDebugModelProvider.class, fDebugModelProvider);
+
+ /*
+ * Registering the launch as an adapter, ensures that this launch,
+ * and debug model ID will be associated with all DMContexts from this
+ * session.
+ */
+ session.registerModelAdapter(ILaunch.class, fLaunch);
+ }
+
+ void dispose() {
+ DsfSession session = fLaunch.getSession();
+
+ fViewModelAdapter.dispose();
+
+ session.unregisterModelAdapter(ISourceDisplay.class);
+ if (fSourceDisplayAdapter != null) fSourceDisplayAdapter.dispose();
+
+ session.unregisterModelAdapter(SteppingController.class);
+ fSteppingController.dispose();
+
+ session.unregisterModelAdapter(ISteppingModeTarget.class);
+ session.unregisterModelAdapter(IStepIntoHandler.class);
+ session.unregisterModelAdapter(IStepOverHandler.class);
+ session.unregisterModelAdapter(IStepReturnHandler.class);
+ session.unregisterModelAdapter(ISuspendHandler.class);
+ session.unregisterModelAdapter(IResumeHandler.class);
+ session.unregisterModelAdapter(IRestart.class);
+ session.unregisterModelAdapter(ITerminateHandler.class);
+ session.unregisterModelAdapter(IConnect.class);
+ session.unregisterModelAdapter(IDisconnectHandler.class);
+ session.unregisterModelAdapter(IModelSelectionPolicyFactory.class);
+ session.unregisterModelAdapter(IRefreshAllTarget.class);
+
+ fStepIntoCommand.dispose();
+ fStepOverCommand.dispose();
+ fStepReturnCommand.dispose();
+ fSuspendCommand.dispose();
+ fResumeCommand.dispose();
+ fRestartCommand.dispose();
+ fTerminateCommand.dispose();
+ fConnectCommand.dispose();
+ fDisconnectCommand.dispose();
+ fSuspendTrigger.dispose();
+ }
+ }
+
+ /**
+ * Active adapter sets. They are accessed using the launch instance
+ * which owns the debug services session.
+ */
+ private static Map fgLaunchAdapterSets =
+ Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Map of launches for which adapter sets have already been disposed.
+ * This map (used as a set) is maintained in order to avoid re-creating an
+ * adapter set after the launch was removed from the launch manager, but
+ * while the launch is still being held by other classes which may
+ * request its adapters. A weak map is used to avoid leaking
+ * memory once the launches are no longer referenced.
+ *
+ * Access to this map is synchronized using the fgLaunchAdapterSets
+ * instance.
+ *
+ */
+ private static Map fgDisposedLaunchAdapterSets =
+ new WeakHashMap();
+
+ static void disposeAdapterSet(ILaunch launch) {
+ synchronized(fgLaunchAdapterSets) {
+ if ( fgLaunchAdapterSets.containsKey(launch) ) {
+ fgLaunchAdapterSets.remove(launch).dispose();
+ fgDisposedLaunchAdapterSets.put(launch, null);
+ }
+ }
+ }
+
+ public GdbAdapterFactory() {
+ DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
+ }
+
+ /**
+ * This method only actually returns adapters for the launch object.
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Object adaptableObject, Class adapterType) {
+ if (!(adaptableObject instanceof GdbLaunch)) return null;
+
+ GdbLaunch launch = (GdbLaunch)adaptableObject;
+
+ // Check for valid session.
+ // Note: even if the session is no longer active, the adapter set
+ // should still be returned. This is because the view model may still
+ // need to show elements representing a terminated process/thread/etc.
+ DsfSession session = launch.getSession();
+ if (session == null) return null;
+
+ // Find the correct set of adapters based on the launch session-ID. If not found
+ // it means that we have a new launch and new session, and we have to create a
+ // new set of adapters.
+
+ SessionAdapterSet adapterSet;
+ synchronized(fgLaunchAdapterSets) {
+ // The adapter set for the given launch was already disposed.
+ // Return a null adapter.
+ if (fgDisposedLaunchAdapterSets.containsKey(launch)) {
+ return null;
+ }
+ adapterSet = fgLaunchAdapterSets.get(launch);
+ if (adapterSet == null) {
+ adapterSet = new SessionAdapterSet(launch);
+ fgLaunchAdapterSets.put(launch, adapterSet);
+ }
+ }
+
+ // Returns the adapter type for the launch object.
+ if (adapterType.equals(IElementContentProvider.class)) return adapterSet.fViewModelAdapter;
+ else if (adapterType.equals(IModelProxyFactory.class)) return adapterSet.fViewModelAdapter;
+ else if (adapterType.equals(IColumnPresentationFactory.class)) return adapterSet.fViewModelAdapter;
+ else if (adapterType.equals(ISuspendTrigger.class)) return adapterSet.fSuspendTrigger;
+ else return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Class[] getAdapterList() {
+ return new Class[] {
+ IElementContentProvider.class, IModelProxyFactory.class, ISuspendTrigger.class,
+ IColumnPresentationFactory.class
+ };
+ }
+
+ public void launchesRemoved(ILaunch[] launches) {
+ // Dispose the set of adapters for a launch only after the launch is
+ // removed.
+ for (ILaunch launch : launches) {
+ if (launch instanceof GdbLaunch) {
+ disposeAdapterSet(launch);
+ }
+ }
+ }
+
+ public void launchesTerminated(ILaunch[] launches) {
+ }
+
+ public void launchesAdded(ILaunch[] launches) {
+ }
+
+ public void launchesChanged(ILaunch[] launches) {
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java
new file mode 100644
index 00000000000..383de2ec65d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbUIPlugin.java
@@ -0,0 +1,204 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - modified to remove dependency on cdt.launch
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui;
+
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class GdbUIPlugin extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.cdt.dsf.gdb.ui"; //$NON-NLS-1$
+
+ // The shared instance
+ private static GdbUIPlugin plugin;
+
+ private static BundleContext fgBundleContext;
+
+ /**
+ * The constructor
+ */
+ public GdbUIPlugin() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#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.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ disposeAdapterSets();
+ plugin = null;
+ super.stop(context);
+ fgBundleContext = null;
+ }
+
+ /**
+ * Dispose adapter sets for all launches.
+ */
+ private void disposeAdapterSets() {
+ for (ILaunch launch : DebugPlugin.getDefault().getLaunchManager().getLaunches()) {
+ if (launch instanceof GdbLaunch) {
+ GdbAdapterFactory.disposeAdapterSet(launch);
+ }
+ }
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static GdbUIPlugin getDefault() {
+ return plugin;
+ }
+
+ public static BundleContext getBundleContext() {
+ return fgBundleContext;
+ }
+
+ /**
+ * copied from org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin
+ */
+ private static Shell debugDialogShell;
+
+ public static Shell getShell() {
+ if (getActiveWorkbenchShell() != null) {
+ return getActiveWorkbenchShell();
+ }
+ if (debugDialogShell != null) {
+ if (!debugDialogShell.isDisposed())
+ return debugDialogShell;
+ debugDialogShell = null;
+ }
+ IWorkbenchWindow[] windows = getDefault().getWorkbench().getWorkbenchWindows();
+ return windows[0].getShell();
+ }
+
+ public static void setDialogShell(Shell shell) {
+ debugDialogShell = shell;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getDefault() == null) {
+ // If the default instance is not yet initialized,
+ // return a static identifier. This identifier must
+ // match the plugin id defined in plugin.xml
+ return PLUGIN_ID;
+ }
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ /**
+ * Logs the specified status with this plug-in's log.
+ *
+ * @param status
+ * status to log
+ */
+ public static void log(IStatus status) {
+ getDefault().getLog().log(status);
+ }
+ /**
+ * Logs an internal error with the specified message.
+ *
+ * @param message
+ * the error message to log
+ */
+ public static void logErrorMessage(String message) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, message, null));
+ }
+
+ /**
+ * Logs an internal error with the specified throwable
+ *
+ * @param e
+ * the exception to be logged
+ */
+ public static void log(Throwable e) {
+ log(new Status(IStatus.ERROR, getUniqueIdentifier(), IStatus.ERROR, e.getMessage(), e));
+ }
+
+ /**
+ * Returns the active workbench window
+ *
+ * @return the active workbench window
+ */
+ public static IWorkbenchWindow getActiveWorkbenchWindow() {
+ return getDefault().getWorkbench().getActiveWorkbenchWindow();
+ }
+
+ public static IWorkbenchPage getActivePage() {
+ IWorkbenchWindow w = getActiveWorkbenchWindow();
+ if (w != null) {
+ return w.getActivePage();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the active workbench shell or null
if none
+ *
+ * @return the active workbench shell or null
if none
+ */
+ public static Shell getActiveWorkbenchShell() {
+ IWorkbenchWindow window = getActiveWorkbenchWindow();
+ if (window != null) {
+ return window.getShell();
+ }
+ return null;
+ }
+
+ public static void errorDialog(String message, IStatus status) {
+ log(status);
+ Shell shell = getActiveWorkbenchShell();
+ if (shell != null) {
+ ErrorDialog.openError(shell, LaunchMessages.getString("LaunchUIPlugin.Error"), message, status); //$NON-NLS-1$
+ }
+ }
+
+ public static void errorDialog(String message, Throwable t) {
+ log(t);
+ Shell shell = getActiveWorkbenchShell();
+ if (shell != null) {
+ IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), 1, t.getMessage(), null);
+ ErrorDialog.openError(shell, LaunchMessages.getString("LaunchUIPlugin.Error"), message, status); //$NON-NLS-1$
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ConnectActionDelegate.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ConnectActionDelegate.java
new file mode 100644
index 00000000000..9be142bd967
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ConnectActionDelegate.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.actions;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.AbstractVMProviderActionDelegate;
+import org.eclipse.cdt.dsf.gdb.actions.IConnect;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IViewPart;
+
+/*
+ * Action to trigger a prompt for a process to attach to
+ */
+public class ConnectActionDelegate extends AbstractVMProviderActionDelegate {
+
+ /*
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ if (action.isEnabled()) {
+ // disable the action so it cannot be run again until an event or
+ // selection change updates the enablement
+ action.setEnabled(false);
+
+ final IConnect connectCommand = getConnectCommand();
+ if (connectCommand != null) {
+ connectCommand.connect(null);
+ }
+ }
+ }
+
+ @Override
+ public void init(IViewPart view) {
+ super.init(view);
+ updateEnablement();
+ }
+
+ @Override
+ public void debugContextChanged(DebugContextEvent event) {
+ super.debugContextChanged(event);
+ updateEnablement();
+ }
+
+ @Override
+ public void selectionChanged(IAction action, ISelection selection) {
+ super.selectionChanged(action, selection);
+ updateEnablement();
+ }
+
+ private void updateEnablement() {
+ boolean enabled = false;
+ final IConnect connectCommand = getConnectCommand();
+ if (connectCommand != null) {
+ enabled = connectCommand.canConnect();
+ }
+ getAction().setEnabled(enabled);
+ }
+
+ private IConnect getConnectCommand() {
+ IConnect command = null;
+ Object element = getViewerInput();
+ if (element instanceof IDMVMContext) {
+ IDMVMContext dmc = (IDMVMContext)element;
+ command = (IConnect)dmc.getAdapter(IConnect.class);
+ } else if (element instanceof GdbLaunch) {
+ GdbLaunch launch = (GdbLaunch)element;
+ command = (IConnect)launch.getSession().getModelAdapter(IConnect.class);
+ }
+
+ return command;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java
new file mode 100644
index 00000000000..bf600ec3346
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/DsfTerminateCommand.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfCommandRunnable;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.ITerminateHandler;
+
+public class DsfTerminateCommand implements ITerminateHandler {
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public DsfTerminateCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ // Run control may not be avilable after a connection is terminated and shut down.
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1 ||
+ !(request.getElements()[0] instanceof IDMVMContext) )
+ {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ // Javac doesn't like the cast to "(AbstractDMVMLayoutNode>.DMVMContext)" need to use the
+ // construct below and suppress warnings.
+ IDMVMContext vmc = (IDMVMContext)request.getElements()[0];
+ final IExecutionDMContext dmc = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
+ if (dmc == null) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.execute(
+ new DsfRunnable() {
+ public void run() {
+ // Get the processes service and the exec context.
+ IGDBBackend gdbBackend = fTracker.getService(IGDBBackend.class);
+ if (gdbBackend == null || dmc == null) {
+ // Context or service already invalid.
+ request.setEnabled(false);
+ request.done();
+ } else {
+ // Check the terminate.
+ request.setEnabled(gdbBackend.getState() == IMIBackend.State.STARTED);
+ request.done();
+ }
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
+ if (gdbControl != null) {
+ gdbControl.terminate(new RequestMonitor(fExecutor, null));
+ }
+ }
+ });
+ return false;
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java
new file mode 100644
index 00000000000..bdaabae7616
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.actions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.core.IProcessInfo;
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
+import org.eclipse.cdt.dsf.gdb.actions.IConnect;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IStatusHandler;
+
+public class GdbConnectCommand implements IConnect {
+
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public GdbConnectCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public boolean canConnect() {
+ Query canConnectQuery = new Query() {
+ @Override
+ public void execute(DataRequestMonitor rm) {
+ IProcesses procService = fTracker.getService(IProcesses.class);
+ ICommandControlService commandControl = fTracker.getService(ICommandControlService.class);
+
+ if (procService != null && commandControl != null) {
+ procService.isDebuggerAttachSupported(commandControl.getContext(), rm);
+ } else {
+ rm.setData(false);
+ rm.done();
+ }
+ }
+ };
+ try {
+ fExecutor.execute(canConnectQuery);
+ return canConnectQuery.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ } catch (RejectedExecutionException e) {
+ // Can be thrown if the session is shutdown
+ }
+
+ return false;
+ }
+
+ // Need a job because prompter.handleStatus will block
+ class PromptForPidJob extends Job {
+
+ // The list of processes used in the case of an ATTACH session
+ IProcessInfo[] fProcessList = null;
+ DataRequestMonitor fRequestMonitor;
+
+ public PromptForPidJob(String name, IProcessInfo[] procs, DataRequestMonitor rm) {
+ super(name);
+ fProcessList = procs;
+ fRequestMonitor = rm;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IStatus promptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200/*STATUS_HANDLER_PROMPT*/, "", null); //$NON-NLS-1$//$NON-NLS-2$
+ final IStatus processPromptStatus = new Status(IStatus.INFO, "org.eclipse.cdt.dsf.gdb.ui", 100, "", null); //$NON-NLS-1$//$NON-NLS-2$
+
+ final IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus);
+
+ final Status NO_PID_STATUS = new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, -1,
+ LaunchMessages.getString("LocalAttachLaunchDelegate.No_Process_ID_selected"), //$NON-NLS-1$
+ null);
+
+ if (prompter == null) {
+ fRequestMonitor.setStatus(NO_PID_STATUS);
+ fRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+
+ try {
+ Object result = prompter.handleStatus(processPromptStatus, fProcessList);
+ if (result instanceof Integer) {
+ fRequestMonitor.setData((Integer)result);
+ } else {
+ fRequestMonitor.setStatus(NO_PID_STATUS);
+ }
+ } catch (CoreException e) {
+ fRequestMonitor.setStatus(NO_PID_STATUS);
+ }
+ fRequestMonitor.done();
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ public void connect(RequestMonitor requestMonitor)
+ {
+ // Create a fake rm to avoid null pointer exceptions
+ final RequestMonitor rm;
+ if (requestMonitor == null) {
+ rm = new RequestMonitor(fExecutor, null);
+ } else {
+ rm = requestMonitor;
+ }
+
+ // Don't wait for the operation to finish because this
+ // method can be called from the UI thread, and it will
+ // block it, which is bad, because we need to use the UI
+ // thread to prompt the user for the process to choose.
+ // This is why we simply use a DsfRunnable.
+ fExecutor.execute(new DsfRunnable() {
+ public void run() {
+ final IProcesses procService = fTracker.getService(IProcesses.class);
+ ICommandControlService commandControl = fTracker.getService(ICommandControlService.class);
+
+ if (procService != null && commandControl != null) {
+ final ICommandControlDMContext controlCtx = commandControl.getContext();
+ procService.getRunningProcesses(
+ controlCtx,
+ new DataRequestMonitor(fExecutor, rm) {
+ @Override
+ protected void handleSuccess() {
+
+ final List procInfoList = new ArrayList();
+
+ // For each process, obtain its name
+ // Once all the names are obtained, prompt the user for the pid to use
+ final CountingRequestMonitor countingRm =
+ new CountingRequestMonitor(fExecutor, rm) {
+ @Override
+ protected void handleSuccess() {
+ new PromptForPidJob(
+ "Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$
+ new DataRequestMonitor(fExecutor, rm) {
+ @Override
+ protected void handleSuccess() {
+ // New cycle, look for service again
+ final IMIProcesses procService = fTracker.getService(IMIProcesses.class);
+ if (procService != null) {
+ IProcessDMContext procDmc = procService.createProcessContext(controlCtx,
+ Integer.toString(getData()));
+ procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor(fExecutor, rm));
+ }
+ }
+ }).schedule();
+ }
+ };
+
+ // New cycle, look for service again
+ final IProcesses procService = fTracker.getService(IProcesses.class);
+
+ if (procService != null) {
+ countingRm.setDoneCount(getData().length);
+
+ for (IProcessDMContext processCtx : getData()) {
+ procService.getExecutionData(
+ processCtx,
+ new DataRequestMonitor (fExecutor, countingRm) {
+ @Override
+ protected void handleSuccess() {
+ int pid = 0;
+ try {
+ pid = Integer.parseInt(getData().getId());
+ } catch (NumberFormatException e) {
+ }
+ procInfoList.add(new ProcessInfo(pid, getData().getName()));
+ countingRm.done();
+ }
+ });
+ }
+ } else {
+ countingRm.setDoneCount(1);
+ countingRm.done();
+ }
+ }
+ });
+ } else {
+ rm.done();
+ }
+ }
+ });
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbDisconnectCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbDisconnectCommand.java
new file mode 100644
index 00000000000..4cdb70cfa55
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbDisconnectCommand.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.ui.actions.DsfCommandRunnable;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IDisconnectHandler;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+
+public class GdbDisconnectCommand implements IDisconnectHandler {
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public GdbDisconnectCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
+
+ getProcessService().canDetachDebuggerFromProcess(
+ containerDmc,
+ new DataRequestMonitor(fExecutor, null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(getContext(), IContainerDMContext.class);
+ getProcessService().detachDebuggerFromProcess(containerDmc, new RequestMonitor(fExecutor, null));
+ }
+ });
+ return false;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRestartCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRestartCommand.java
new file mode 100644
index 00000000000..317ee34afb4
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbRestartCommand.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.cdt.debug.core.model.IRestart;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IProcess;
+
+public class GdbRestartCommand implements IRestart {
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+ private final GdbLaunch fLaunch;
+
+ public GdbRestartCommand(DsfSession session, GdbLaunch launch) {
+ fExecutor = session.getExecutor();
+ fLaunch = launch;
+ fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ // Run control may not be available after a connection is terminated and shut down.
+ public boolean canRestart() {
+ Query canRestart = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
+ if (gdbControl != null) {
+ rm.setData(gdbControl.canRestart());
+ } else {
+ rm.setData(false);
+ }
+
+ rm.done();
+ }
+ };
+
+ fExecutor.execute(canRestart);
+ try {
+ return canRestart.get();
+ } catch (InterruptedException e1) {
+ } catch (ExecutionException e1) {
+ }
+ return false;
+ }
+
+
+ public void restart() throws DebugException
+ {
+ final AtomicReference execPathRef = new AtomicReference();
+ Query restartQuery = new Query() {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ final IGDBControl gdbControl = fTracker.getService(IGDBControl.class);
+ final IGDBBackend backend = fTracker.getService(IGDBBackend.class);
+ if (gdbControl != null && backend != null) {
+ execPathRef.set(backend.getProgramPath());
+ gdbControl.initInferiorInputOutput(new RequestMonitor(fExecutor, rm) {
+ @Override
+ protected void handleSuccess() {
+ gdbControl.createInferiorProcess();
+ gdbControl.restart(fLaunch, rm);
+ }
+ });
+ } else {
+ rm.done();
+ }
+ }
+ };
+
+ fExecutor.execute(restartQuery);
+ try {
+ restartQuery.get();
+ } catch (InterruptedException e1) {
+ } catch (ExecutionException e1) {
+ }
+
+ // Now that we restarted the inferior, we must add it to our launch
+ // we must do this here because we cannot do it in the executor, or else
+ // it deadlocks
+ // We must first remove the old inferior from our launch (since it uses
+ // the same name and we use that name to find the old one)
+ //
+ // Remove
+ String inferiorLabel = execPathRef.get().lastSegment();
+
+ IProcess[] launchProcesses = fLaunch.getProcesses();
+ for (IProcess p : launchProcesses) {
+ if (p.getLabel().equals(inferiorLabel)) {
+ fLaunch.removeProcess(p);
+ break;
+ }
+ }
+ // Add
+ try {
+ fLaunch.addInferiorProcess(inferiorLabel);
+ } catch (CoreException e) {
+ throw new DebugException(e.getStatus());
+ }
+ }
+}
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ProcessInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ProcessInfo.java
new file mode 100644
index 00000000000..71033928bc5
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/ProcessInfo.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.actions;
+
+import org.eclipse.cdt.core.IProcessInfo;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+
+@Immutable
+class ProcessInfo implements IProcessInfo, Comparable {
+ private final int pid;
+ private final String name;
+
+ public ProcessInfo(String pidString, String name) {
+ int tmpPid = 0;
+ try {
+ tmpPid = Integer.parseInt(pidString);
+ } catch (NumberFormatException e) {
+ }
+ this.pid = tmpPid;
+ this.name = name;
+ }
+
+ public ProcessInfo(int pid, String name) {
+ this.pid = pid;
+ this.name = name;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.IProcessInfo#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see org.eclipse.cdt.core.IProcessInfo#getPid()
+ */
+ public int getPid() {
+ return pid;
+ }
+
+ public int compareTo(ProcessInfo other) {
+ int nameCompare = getName().compareTo(other.getName());
+ if (nameCompare != 0) return nameCompare;
+ else return (getPid() < other.getPid()) ? -1 : 1;
+ }
+}
\ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/CBreakpointGdbThreadFilterPage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/CBreakpointGdbThreadFilterPage.java
new file mode 100644
index 00000000000..7d585bce77e
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/CBreakpointGdbThreadFilterPage.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.breakpoints;
+
+import org.eclipse.cdt.debug.core.model.ICBreakpoint;
+import org.eclipse.cdt.dsf.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.dialogs.PropertyPage;
+
+public class CBreakpointGdbThreadFilterPage extends PropertyPage {
+
+ private GdbThreadFilterEditor fThreadFilterEditor;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ protected Control createContents( Composite parent ) {
+ noDefaultAndApplyButton();
+ Composite mainComposite = new Composite( parent, SWT.NONE );
+ mainComposite.setFont( parent.getFont() );
+ mainComposite.setLayout( new GridLayout() );
+ mainComposite.setLayoutData( new GridData( GridData.FILL_BOTH ) );
+ createThreadFilterEditor( mainComposite );
+ setValid( true );
+ return mainComposite;
+ }
+
+ public ICBreakpoint getBreakpoint() {
+ return (ICBreakpoint)getElement().getAdapter(ICBreakpoint.class);
+ }
+
+ public CBreakpointGdbThreadsFilterExtension getFilterExtension() {
+ ICBreakpoint bp = getBreakpoint();
+ if (bp != null) {
+ try {
+ CBreakpointGdbThreadsFilterExtension filter =
+ (CBreakpointGdbThreadsFilterExtension) bp.getExtension(
+ GdbLaunchDelegate.GDB_DEBUG_MODEL_ID, CBreakpointGdbThreadsFilterExtension.class);
+ filter.initialize(bp);
+ return filter;
+ } catch (CoreException e) {}
+ }
+ return null;
+ }
+
+ protected void createThreadFilterEditor( Composite parent ) {
+ fThreadFilterEditor = new GdbThreadFilterEditor( parent, this );
+ }
+
+ protected GdbThreadFilterEditor getThreadFilterEditor() {
+ return fThreadFilterEditor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.IPreferencePage#performOk()
+ */
+ @Override
+ public boolean performOk() {
+ doStore();
+ return super.performOk();
+ }
+
+ /**
+ * Stores the values configured in this page.
+ */
+ protected void doStore() {
+ fThreadFilterEditor.doStore();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/GdbThreadFilterEditor.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/GdbThreadFilterEditor.java
new file mode 100644
index 00000000000..83f4fc68195
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/breakpoints/GdbThreadFilterEditor.java
@@ -0,0 +1,553 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2005 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.cdt.dsf.gdb.internal.ui.breakpoints;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.viewers.AbstractTreeViewer;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class GdbThreadFilterEditor {
+
+ /**
+ * Comment for ThreadFilterEditor.
+ */
+ public class CheckHandler implements ICheckStateListener {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged(org.eclipse.jface.viewers.CheckStateChangedEvent)
+ */
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ Object element = event.getElement();
+ if (element instanceof IContainerDMContext) {
+ checkTarget((IContainerDMContext) element, event.getChecked());
+ } else if (element instanceof IExecutionDMContext) {
+ checkThread((IExecutionDMContext) element, event.getChecked());
+ }
+ }
+
+ /**
+ * Check or uncheck a debug target in the tree viewer. When a debug
+ * target is checked, attempt to check all of the target's threads by
+ * default. When a debug target is unchecked, uncheck all its threads.
+ */
+ protected void checkTarget(IContainerDMContext target, boolean checked) {
+ getThreadViewer().setChecked(target, checked);
+ getThreadViewer().setGrayed(target, false);
+ getThreadViewer().expandToLevel(target, AbstractTreeViewer.ALL_LEVELS);
+ IExecutionDMContext[] threads = syncGetThreads(target);
+ for (int i = 0; i < threads.length; i++) {
+ getThreadViewer().setChecked(threads[i], checked);
+ getThreadViewer().setGrayed(threads[i], false);
+ }
+ }
+
+ /**
+ * Check or uncheck a thread. Update the thread's debug target.
+ */
+ protected void checkThread(IExecutionDMContext thread, boolean checked) {
+ getThreadViewer().setChecked(thread, checked);
+ IContainerDMContext target = DMContexts.getAncestorOfType(thread, IContainerDMContext.class);
+ IExecutionDMContext[] threads = syncGetThreads(target);
+ int checkedNumber = 0;
+ for (int i = 0; i < threads.length; i++) {
+ if (getThreadViewer().getChecked(threads[i])) {
+ ++checkedNumber;
+ }
+ }
+ if (checkedNumber == 0) {
+ getThreadViewer().setChecked(target, false);
+ getThreadViewer().setGrayed(target, false);
+ } else if (checkedNumber == threads.length) {
+ getThreadViewer().setChecked(target, true);
+ getThreadViewer().setGrayed(target, false);
+ } else {
+ getThreadViewer().setGrayChecked(target, true);
+ }
+ }
+ }
+
+ /**
+ * Comment for ThreadFilterEditor.
+ */
+ public class ThreadFilterContentProvider implements ITreeContentProvider {
+
+ /**
+ * Constructor for ThreadFilterContentProvider.
+ */
+ public ThreadFilterContentProvider() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
+ */
+ public Object[] getChildren(Object parent) {
+ if (parent instanceof IContainerDMContext) {
+ return syncGetThreads((IContainerDMContext) parent);
+ }
+
+ if (parent instanceof ILaunchManager) {
+ List children = new ArrayList();
+ ILaunch[] launches = ((ILaunchManager) parent).getLaunches();
+ IContainerDMContext target;
+ for (int i = 0; i < launches.length; i++) {
+ if (launches[i] instanceof GdbLaunch) {
+ target = syncGetContainer((GdbLaunch) launches[i]);
+ if (target != null) {
+ children.add(target);
+ }
+ }
+ }
+ return children.toArray();
+ }
+ return new Object[0];
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
+ */
+ public Object getParent(Object element) {
+ if (element instanceof IContainerDMContext) {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+ if (element instanceof IExecutionDMContext) {
+ return DMContexts.getAncestorOfType((IExecutionDMContext) element, IContainerDMContext.class);
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
+ */
+ public boolean hasChildren(Object element) {
+ return getChildren(element).length > 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer,
+ * java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ }
+
+ public class ThreadFilterLabelProvider extends LabelProvider {
+
+ @Override
+ public Image getImage(Object element) {
+ if (element instanceof IContainerDMContext) {
+ return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET);
+ } else {
+ return DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING);
+ }
+ }
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof IContainerDMContext) {
+ return syncGetContainerLabel((IContainerDMContext)element);
+ } else {
+ return syncGetThreadLabel((IExecutionDMContext)element);
+ }
+ }
+ }
+
+
+ private CBreakpointGdbThreadFilterPage fPage;
+
+ private CheckboxTreeViewer fThreadViewer;
+
+ private ThreadFilterContentProvider fContentProvider;
+
+ private CheckHandler fCheckHandler;
+
+ /**
+ * Constructor for ThreadFilterEditor.
+ */
+ public GdbThreadFilterEditor(Composite parent, CBreakpointGdbThreadFilterPage page) {
+ fPage = page;
+ fContentProvider = new ThreadFilterContentProvider();
+ fCheckHandler = new CheckHandler();
+ createThreadViewer(parent);
+ }
+
+ protected CBreakpointGdbThreadFilterPage getPage() {
+ return fPage;
+ }
+
+ private void createThreadViewer(Composite parent) {
+ Label label = new Label(parent, SWT.NONE);
+ label.setText("&Restrict to Selected Targets and Threads:"); //$NON-NLS-1$
+ label.setFont(parent.getFont());
+ label.setLayoutData(new GridData());
+ GridData data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = 100;
+ fThreadViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
+ fThreadViewer.addCheckStateListener(fCheckHandler);
+ fThreadViewer.getTree().setLayoutData(data);
+ fThreadViewer.getTree().setFont(parent.getFont());
+ fThreadViewer.setContentProvider(fContentProvider);
+ fThreadViewer.setLabelProvider(new ThreadFilterLabelProvider());
+ fThreadViewer.setInput(DebugPlugin.getDefault().getLaunchManager());
+ setInitialCheckedState();
+ }
+
+ /**
+ * Returns the debug targets that appear in the tree
+ */
+ protected IContainerDMContext[] getDebugTargets() {
+ Object input = fThreadViewer.getInput();
+ if (!(input instanceof ILaunchManager)) {
+ return new IContainerDMContext[0];
+ }
+ List targets = new ArrayList();
+ ILaunch[] launches = ((ILaunchManager) input).getLaunches();
+ IContainerDMContext target;
+ for (int i = 0; i < launches.length; i++) {
+ if (launches[i] instanceof GdbLaunch) {
+ target = syncGetContainer((GdbLaunch) launches[i]);
+ if (target != null) {
+ targets.add(target);
+ }
+ }
+ }
+ return targets.toArray(new IContainerDMContext[targets.size()]);
+ }
+
+ protected CheckboxTreeViewer getThreadViewer() {
+ return fThreadViewer;
+ }
+
+ /**
+ * Sets the initial checked state of the tree viewer. The initial state
+ * should reflect the current state of the breakpoint. If the breakpoint has
+ * a thread filter in a given thread, that thread should be checked.
+ */
+ protected void setInitialCheckedState() {
+ CBreakpointGdbThreadsFilterExtension filterExtension = fPage.getFilterExtension();
+ try {
+ IContainerDMContext[] targets = filterExtension.getTargetFilters();
+
+ // TODO: Hack to properly initialize the target/thread list
+ // Should be done in filterExtension.initialize() but we don't know
+ // how to get the target list from an ICBreakpoint...
+ if (targets.length == 0) {
+ targets = getDebugTargets();
+ for (IContainerDMContext target : targets) {
+ filterExtension.setTargetFilter(target);
+ }
+ }
+ // TODO: End of hack
+
+ for (int i = 0; i < targets.length; i++) {
+ IExecutionDMContext[] filteredThreads = filterExtension.getThreadFilters(targets[i]);
+ if (filteredThreads != null) {
+ for (int j = 0; j < filteredThreads.length; ++j)
+ fCheckHandler.checkThread(filteredThreads[j], true);
+ } else {
+ fCheckHandler.checkTarget(targets[i], true);
+ }
+ }
+ } catch (CoreException e) {
+ CDebugUIPlugin.log(e);
+ }
+ }
+
+ protected void doStore() {
+ CBreakpointGdbThreadsFilterExtension filterExtension = fPage.getFilterExtension();
+ IContainerDMContext[] targets = getDebugTargets();
+ for (int i = 0; i < targets.length; ++i) {
+ try {
+ if (getThreadViewer().getChecked(targets[i])) {
+ if (getThreadViewer().getGrayed(targets[i])) {
+ IExecutionDMContext[] threads = getTargetThreadFilters(targets[i]);
+ filterExtension.setThreadFilters(threads);
+ } else {
+ filterExtension.setTargetFilter(targets[i]);
+ }
+ } else {
+ filterExtension.removeTargetFilter(targets[i]);
+ }
+ DebugPlugin.getDefault().getBreakpointManager().fireBreakpointChanged(fPage.getBreakpoint());
+ } catch (CoreException e) {
+ CDebugUIPlugin.log(e);
+ }
+ }
+ }
+
+ private IExecutionDMContext[] getTargetThreadFilters(IContainerDMContext target) {
+ Object[] threads = ((ITreeContentProvider) getThreadViewer().getContentProvider()).getChildren(target);
+ ArrayList list = new ArrayList(threads.length);
+ for (int i = 0; i < threads.length; ++i) {
+ if (getThreadViewer().getChecked(threads[i]))
+ list.add(threads[i]);
+ }
+ return list.toArray(new IExecutionDMContext[list.size()]);
+ }
+
+ private IContainerDMContext syncGetContainer(final GdbLaunch launch) {
+ final DsfSession session = launch.getSession();
+
+ class ContainerQuery extends Query {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ if (!session.isActive()) {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "Launch's session not active.")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ ServiceTracker tracker1 = new ServiceTracker(GdbUIPlugin.getBundleContext(), ICommandControlService.class
+ .getName(), null);
+ tracker1.open();
+
+ ICommandControlService commandControl = (ICommandControlService) tracker1.getService();
+ ServiceTracker tracker2 = new ServiceTracker(GdbUIPlugin.getBundleContext(), IMIProcesses.class
+ .getName(), null);
+ tracker2.open();
+ IMIProcesses procService = (IMIProcesses) tracker2.getService();
+
+ if (commandControl != null && procService != null) {
+ IProcessDMContext procDmc = procService.createProcessContext(commandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
+ IContainerDMContext containerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
+
+ rm.setData(containerDmc);
+ } else {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "GDB Control or Process service not accessible.")); //$NON-NLS-1$
+ }
+ rm.done();
+ tracker1.close();
+ tracker2.close();
+ }
+ }
+
+ ContainerQuery query = new ContainerQuery();
+ try {
+ session.getExecutor().execute(query);
+ return query.get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ return null;
+ }
+
+ private IExecutionDMContext[] syncGetThreads(final IContainerDMContext container) {
+ final DsfSession session = DsfSession.getSession(container.getSessionId());
+ if (session == null) {
+ return new IExecutionDMContext[0];
+ }
+
+ class ThreadsQuery extends Query {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ if (!session.isActive()) {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IRunControl.class
+ .getName(), null);
+ tracker.open();
+ IRunControl runControl = (IRunControl) tracker.getService();
+ if (runControl != null) {
+ runControl.getExecutionContexts(container, rm);
+ } else {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "GDB Control not accessible.")); //$NON-NLS-1$
+ rm.done();
+ }
+ tracker.close();
+ }
+ }
+
+ ThreadsQuery query = new ThreadsQuery();
+ try {
+ session.getExecutor().execute(query);
+ return query.get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ return new IExecutionDMContext[0];
+ }
+
+ private String syncGetContainerLabel(final IContainerDMContext container) {
+ final DsfSession session = DsfSession.getSession(container.getSessionId());
+ if (session == null) {
+ return "Error reading data"; //$NON-NLS-1$
+ }
+
+ class ContainerLabelQuery extends Query {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ if (!session.isActive()) {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IGDBBackend.class
+ .getName(), null);
+ tracker.open();
+ IGDBBackend backend = (IGDBBackend) tracker.getService();
+ if (backend != null) {
+ rm.setData(backend.getProgramPath().toOSString());
+ } else {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "GDB Backend not accessible.")); //$NON-NLS-1$
+ }
+ rm.done();
+ tracker.close();
+ }
+ }
+
+ ContainerLabelQuery query = new ContainerLabelQuery();
+ try {
+ session.getExecutor().execute(query);
+ return query.get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ return "Error reading data"; //$NON-NLS-1$
+ }
+
+ private String syncGetThreadLabel(final IExecutionDMContext thread) {
+ final DsfSession session = DsfSession.getSession(thread.getSessionId());
+ if (session == null) {
+ return "Error reading data"; //$NON-NLS-1$
+ }
+
+ class ThreadLabelQuery extends Query {
+ @Override
+ protected void execute(final DataRequestMonitor rm) {
+ if (!session.isActive()) {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "Container's session not active.")); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ ServiceTracker tracker = new ServiceTracker(GdbUIPlugin.getBundleContext(), IProcesses.class
+ .getName(), null);
+ tracker.open();
+ IProcesses procService = (IProcesses) tracker.getService();
+ if (procService != null) {
+ IThreadDMContext threadDmc = DMContexts.getAncestorOfType(thread, IThreadDMContext.class);
+ procService.getExecutionData(threadDmc, new DataRequestMonitor(
+ ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ final StringBuilder builder = new StringBuilder("Thread["); //$NON-NLS-1$
+ builder.append(((IMIExecutionDMContext)thread).getThreadId());
+ builder.append("] "); //$NON-NLS-1$
+ builder.append(getData().getId());
+ builder.append(getData().getName());
+
+ rm.setData(builder.toString());
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(getFailStatus(IDsfStatusConstants.INVALID_STATE, "IProcesses service not accessible.")); //$NON-NLS-1$
+ rm.done();
+ }
+ tracker.close();
+ }
+ }
+
+ ThreadLabelQuery query = new ThreadLabelQuery();
+ try {
+ session.getExecutor().execute(query);
+ return query.get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ return "Error reading data"; //$NON-NLS-1$
+ }
+
+ private Status getFailStatus(int code, String message) {
+ return new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, code, message, null);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/AbstractCDebuggerTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/AbstractCDebuggerTab.java
new file mode 100644
index 00000000000..99a5de88a7c
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/AbstractCDebuggerTab.java
@@ -0,0 +1,352 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * IBM Corporation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.util.Map;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.core.ICDebugConfiguration;
+import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
+import org.eclipse.cdt.debug.ui.ICDebuggerPage;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+
+public abstract class AbstractCDebuggerTab extends CLaunchConfigurationTab {
+
+ protected ILaunchConfiguration fLaunchConfiguration;
+ protected ILaunchConfigurationWorkingCopy fWorkingCopy;
+ protected ICDebugConfiguration fCurrentDebugConfig;
+
+ // Dynamic Debugger UI widgets
+ protected ICDebuggerPage fDynamicTab;
+ protected Composite fDynamicTabHolder;
+ private boolean fInitDefaults;
+ private Combo fDCombo;
+ private boolean fIsInitializing = false;
+ private boolean fPageUpdated;
+
+ protected void setDebugConfig(ICDebugConfiguration config) {
+ fCurrentDebugConfig = config;
+ }
+
+ protected ICDebugConfiguration getDebugConfig() {
+ return fCurrentDebugConfig;
+ }
+
+ protected ICDebuggerPage getDynamicTab() {
+ return fDynamicTab;
+ }
+
+ protected void setDynamicTab(ICDebuggerPage tab) {
+ fDynamicTab = tab;
+ }
+
+ protected Composite getDynamicTabHolder() {
+ return fDynamicTabHolder;
+ }
+
+ protected void setDynamicTabHolder(Composite tabHolder) {
+ fDynamicTabHolder = tabHolder;
+ }
+
+ protected ILaunchConfigurationWorkingCopy getLaunchConfigurationWorkingCopy() {
+ return fWorkingCopy;
+ }
+
+ protected void setLaunchConfiguration(ILaunchConfiguration launchConfiguration) {
+ fLaunchConfiguration = launchConfiguration;
+ setLaunchConfigurationWorkingCopy(null);
+ }
+
+ protected ILaunchConfiguration getLaunchConfiguration() {
+ return fLaunchConfiguration;
+ }
+
+ protected void setLaunchConfigurationWorkingCopy(ILaunchConfigurationWorkingCopy workingCopy) {
+ fWorkingCopy = workingCopy;
+ }
+
+ /**
+ * Overridden here so that any error message in the dynamic UI gets
+ * returned.
+ *
+ * @see ILaunchConfigurationTab#getErrorMessage()
+ */
+ @Override
+ public String getErrorMessage() {
+ ICDebuggerPage tab = getDynamicTab();
+ if ( (super.getErrorMessage() != null) || (tab == null)) {
+ return super.getErrorMessage();
+ }
+ return tab.getErrorMessage();
+ }
+
+ /**
+ * Notification that the user changed the selection of the Debugger.
+ */
+ protected void handleDebuggerChanged() {
+ loadDynamicDebugArea();
+
+ // always set the newly created area with defaults
+ ILaunchConfigurationWorkingCopy wc = getLaunchConfigurationWorkingCopy();
+ if (getDynamicTab() == null) {
+ // remove any debug specfic args from the config
+ if (wc == null) {
+ if (getLaunchConfiguration().isWorkingCopy()) {
+ wc = (ILaunchConfigurationWorkingCopy)getLaunchConfiguration();
+ }
+ }
+ if (wc != null) {
+ wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_SPECIFIC_ATTRS_MAP, (Map,?>)null);
+ }
+ } else {
+ if (wc == null) {
+ try {
+ if (getLaunchConfiguration().isWorkingCopy()) {
+ setLaunchConfigurationWorkingCopy((ILaunchConfigurationWorkingCopy)getLaunchConfiguration());
+ } else {
+ setLaunchConfigurationWorkingCopy(getLaunchConfiguration().getWorkingCopy());
+ }
+ wc = getLaunchConfigurationWorkingCopy();
+
+ } catch (CoreException e) {
+ return;
+ }
+ }
+ if (initDefaults()) {
+ getDynamicTab().setDefaults(wc);
+ }
+ setInitializeDefault(false);
+ getDynamicTab().initializeFrom(wc);
+ }
+ }
+
+ /**
+ * Show the contributed piece of UI that was registered for the debugger id
+ * of the currently selected debugger.
+ */
+ protected void loadDynamicDebugArea() {
+ // Dispose of any current child widgets in the tab holder area
+ Control[] children = getDynamicTabHolder().getChildren();
+ for (int i = 0; i < children.length; i++) {
+ children[i].dispose();
+ }
+
+ // Retrieve the dynamic UI for the current Debugger
+ ICDebugConfiguration debugConfig = getConfigForCurrentDebugger();
+ if (debugConfig == null) {
+ setDynamicTab(null);
+ } else {
+ ICDebuggerPage tab = null;
+ try {
+ tab = CDebugUIPlugin.getDefault().getDebuggerPage(debugConfig.getID());
+ } catch (CoreException e) {
+ GdbUIPlugin.errorDialog(LaunchMessages.getString("AbstractCDebuggerTab.ErrorLoadingDebuggerPage"), e.getStatus()); //$NON-NLS-1$
+ }
+ setDynamicTab(tab);
+ }
+ setDebugConfig(debugConfig);
+ if (getDynamicTab() == null) {
+ return;
+ }
+ // Ask the dynamic UI to create its Control
+ getDynamicTab().setLaunchConfigurationDialog(getLaunchConfigurationDialog());
+ getDynamicTab().createControl(getDynamicTabHolder());
+ getDynamicTab().getControl().setVisible(true);
+ getDynamicTabHolder().layout(true);
+ contentsChanged();
+ }
+
+ /**
+ * Called whenever the controls within the Debugger tab has changed.
+ */
+ protected void contentsChanged() {
+ }
+
+ abstract public void createControl(Composite parent);
+
+ @Override
+ public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
+ ICDebuggerPage dynamicTab = getDynamicTab();
+ if (dynamicTab != null) {
+ dynamicTab.activated(workingCopy);
+ }
+ }
+
+ public void initializeFrom(ILaunchConfiguration config) {
+ setLaunchConfiguration(config);
+ ICDebuggerPage dynamicTab = getDynamicTab();
+ if (dynamicTab != null) {
+ dynamicTab.initializeFrom(config);
+ }
+ }
+
+ public void performApply(ILaunchConfigurationWorkingCopy config) {
+ if (getDebugConfig() != null) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, getDebugConfig().getID());
+ ICDebuggerPage dynamicTab = getDynamicTab();
+ if (dynamicTab == null) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_SPECIFIC_ATTRS_MAP, (Map,?>)null);
+ } else {
+ dynamicTab.performApply(config);
+ }
+ }
+ }
+
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ setLaunchConfigurationWorkingCopy(config);
+ ICDebuggerPage dynamicTab = getDynamicTab();
+ if (dynamicTab != null) {
+ dynamicTab.setDefaults(config);
+ setInitializeDefault(false);
+ }
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+ setErrorMessage(null);
+ setMessage(null);
+ if (getDebugConfig() == null) {
+ setErrorMessage(LaunchMessages.getString("AbstractCDebuggerTab.No_debugger_available")); //$NON-NLS-1$
+ return false;
+ }
+
+ ICDebuggerPage dynamicTab = getDynamicTab();
+ if (dynamicTab != null) {
+ return dynamicTab.isValid(config);
+ }
+ return true;
+ }
+
+ protected void setInitializeDefault(boolean init) {
+ fInitDefaults = init;
+ }
+
+ protected boolean initDefaults() {
+ return fInitDefaults;
+ }
+
+ @Override
+ public Image getImage() {
+ return LaunchImages.get(LaunchImages.IMG_VIEW_DEBUGGER_TAB);
+ }
+
+ public String getName() {
+ return LaunchMessages.getString("AbstractCDebuggerTab.Debugger"); //$NON-NLS-1$
+ }
+
+ protected void createDebuggerCombo(Composite parent, int colspan) {
+ Composite comboComp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(2, false);
+ comboComp.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = colspan;
+ comboComp.setLayoutData(gd);
+ Label dlabel = new Label(comboComp, SWT.NONE);
+ dlabel.setText(LaunchMessages.getString("Launch.common.DebuggerColon")); //$NON-NLS-1$
+ fDCombo = new Combo(comboComp, SWT.READ_ONLY | SWT.DROP_DOWN);
+ fDCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ fDCombo.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ if (!isInitializing()) {
+ setInitializeDefault(true);
+ updateComboFromSelection();
+ }
+ }
+
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+
+ protected void loadDebuggerCombo(ICDebugConfiguration[] debugConfigs, String current) {
+ fDCombo.removeAll();
+ int select = -1;
+ for (int i = 0; i < debugConfigs.length; i++) {
+ fDCombo.add(debugConfigs[i].getName());
+ fDCombo.setData(Integer.toString(i), debugConfigs[i]);
+ if (debugConfigs[i].getID().equalsIgnoreCase(current)) {
+ select = i;
+ }
+ }
+
+ fPageUpdated = false;
+ if (select != -1) {
+ fDCombo.select(select);
+ } else {
+ fDCombo.select(0);
+ }
+ //The behaviour is undefined for if the callbacks should be triggered
+ // for this,
+ //so force page update if needed.
+ if (!fPageUpdated) {
+ updateComboFromSelection();
+ }
+ fPageUpdated = false;
+ getControl().getParent().layout(true);
+
+ }
+
+ protected void createDebuggerGroup(Composite parent, int colspan) {
+ Group debuggerGroup = new Group(parent, SWT.SHADOW_ETCHED_IN);
+ debuggerGroup.setText(LaunchMessages.getString("CDebuggerTab.Debugger_Options")); //$NON-NLS-1$
+ setDynamicTabHolder(debuggerGroup);
+ GridLayout tabHolderLayout = new GridLayout();
+ tabHolderLayout.marginHeight = 0;
+ tabHolderLayout.marginWidth = 0;
+ tabHolderLayout.numColumns = 1;
+ getDynamicTabHolder().setLayout(tabHolderLayout);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = colspan;
+ getDynamicTabHolder().setLayoutData(gd);
+ }
+
+ protected void updateComboFromSelection() {
+ fPageUpdated = true;
+ handleDebuggerChanged();
+ updateLaunchConfigurationDialog();
+ }
+
+ protected boolean isInitializing() {
+ return fIsInitializing;
+ }
+
+ protected void setInitializing(boolean isInitializing) {
+ fIsInitializing = isInitializing;
+ }
+
+ /**
+ * Return the class that implements ICDebuggerPage
+ * that is registered against the debugger id of the currently selected
+ * debugger.
+ */
+ protected ICDebugConfiguration getConfigForCurrentDebugger() {
+ int selectedIndex = fDCombo.getSelectionIndex();
+ return (ICDebugConfiguration)fDCombo.getData(Integer.toString(selectedIndex));
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CArgumentsTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CArgumentsTab.java
new file mode 100644
index 00000000000..24c95429e77
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CArgumentsTab.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 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
+ * IBM Corporation
+ * Ericsson - Updated for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.StringVariableSelectionDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+
+/**
+ * A launch configuration tab that displays and edits program arguments,
+ * and working directory launch configuration attributes.
+ *
+ * This class may be instantiated. This class is not intended to be subclassed.
+ *
+ */
+public class CArgumentsTab extends CLaunchConfigurationTab {
+
+ // Program arguments UI widgets
+ protected Label fPrgmArgumentsLabel;
+ protected Text fPrgmArgumentsText;
+ protected Button fArgumentVariablesButton;
+
+ // Working directory
+ protected WorkingDirectoryBlock fWorkingDirectoryBlock = new WorkingDirectoryBlock();
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ Font font = parent.getFont();
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(1, true);
+ comp.setLayout(layout);
+ comp.setFont(font);
+
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ comp.setLayoutData(gd);
+ setControl(comp);
+
+ GdbUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(getControl(), ICDTLaunchHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_ARGUMNETS_TAB);
+
+ createArgumentComponent(comp, 1);
+
+ fWorkingDirectoryBlock.createControl(comp);
+ }
+
+ protected void createArgumentComponent(Composite comp, int horizontalSpan) {
+ Font font = comp.getFont();
+ Group group = new Group(comp, SWT.NONE);
+ group.setFont(font);
+ group.setLayout(new GridLayout());
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.horizontalSpan = horizontalSpan;
+ group.setLayoutData(gd);
+
+ group.setText(LaunchMessages.getString("CArgumentsTab.C/C++_Program_Arguments")); //$NON-NLS-1$
+ fPrgmArgumentsText = new Text(group, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
+ fPrgmArgumentsText.getAccessible().addAccessibleListener(
+ new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = LaunchMessages.getString("CArgumentsTab.C/C++_Program_Arguments"); //$NON-NLS-1$
+ }
+ }
+ );
+ gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 40;
+ gd.widthHint = 100;
+ fPrgmArgumentsText.setLayoutData(gd);
+ fPrgmArgumentsText.setFont(font);
+ fPrgmArgumentsText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ fArgumentVariablesButton= createPushButton(group, LaunchMessages.getString("CArgumentsTab.Variables"), null); //$NON-NLS-1$
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ fArgumentVariablesButton.setLayoutData(gd);
+ fArgumentVariablesButton.addSelectionListener(new SelectionAdapter() {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(SelectionEvent arg0) {
+ handleVariablesButtonSelected(fPrgmArgumentsText);
+ }
+
+ });
+ addControlAccessibleListener(fArgumentVariablesButton, fArgumentVariablesButton.getText()); // need to strip the mnemonic from buttons
+ }
+
+ /**
+ * A variable entry button has been pressed for the given text
+ * field. Prompt the user for a variable and enter the result
+ * in the given field.
+ */
+ protected void handleVariablesButtonSelected(Text textField) {
+ String variable = getVariable();
+ if (variable != null) {
+ textField.append(variable);
+ }
+ }
+
+ /**
+ * Prompts the user to choose and configure a variable and returns
+ * the resulting string, suitable to be used as an attribute.
+ */
+ private String getVariable() {
+ StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell());
+ dialog.open();
+ return dialog.getVariableExpression();
+ }
+
+ public void addControlAccessibleListener(Control control, String controlName) {
+ //strip mnemonic (&)
+ String[] strs = controlName.split("&"); //$NON-NLS-1$
+ StringBuffer stripped = new StringBuffer();
+ for (int i = 0; i < strs.length; i++) {
+ stripped.append(strs[i]);
+ }
+ control.getAccessible().addAccessibleListener(new ControlAccessibleListener(stripped.toString()));
+ }
+
+ private class ControlAccessibleListener extends AccessibleAdapter {
+ private String controlName;
+ ControlAccessibleListener(String name) {
+ controlName = name;
+ }
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = controlName;
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+ return fWorkingDirectoryBlock.isValid(config);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, (String) null);
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String) null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ try {
+ fPrgmArgumentsText.setText(configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "")); //$NON-NLS-1$
+ fWorkingDirectoryBlock.initializeFrom(configuration);
+ }
+ catch (CoreException e) {
+ setErrorMessage(LaunchMessages.getFormattedString("Launch.common.Exception_occurred_reading_configuration_EXCEPTION", e.getStatus().getMessage())); //$NON-NLS-1$
+ GdbUIPlugin.log(e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(
+ ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
+ getAttributeValueFrom(fPrgmArgumentsText));
+ fWorkingDirectoryBlock.performApply(configuration);
+ }
+
+ /**
+ * Retuns the string in the text widget, or null
if empty.
+ *
+ * @return text or null
+ */
+ protected String getAttributeValueFrom(Text text) {
+ String content = text.getText().trim();
+ // bug #131513 - eliminate Windows \r line delimiter
+ content = content.replaceAll("\r\n", "\n"); //$NON-NLS-1$//$NON-NLS-2$
+ if (content.length() > 0) {
+ return content;
+ }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ public String getName() {
+ return LaunchMessages.getString("CArgumentsTab.Arguments"); //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setLaunchConfigurationDialog(org.eclipse.debug.ui.ILaunchConfigurationDialog)
+ */
+ @Override
+ public void setLaunchConfigurationDialog(ILaunchConfigurationDialog dialog) {
+ super.setLaunchConfigurationDialog(dialog);
+ fWorkingDirectoryBlock.setLaunchConfigurationDialog(dialog);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getErrorMessage()
+ */
+ @Override
+ public String getErrorMessage() {
+ String m = super.getErrorMessage();
+ if (m == null) {
+ return fWorkingDirectoryBlock.getErrorMessage();
+ }
+ return m;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getMessage()
+ */
+ @Override
+ public String getMessage() {
+ String m = super.getMessage();
+ if (m == null) {
+ return fWorkingDirectoryBlock.getMessage();
+ }
+ return m;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+ */
+ @Override
+ public Image getImage() {
+ return LaunchImages.get(LaunchImages.IMG_VIEW_ARGUMENTS_TAB);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog()
+ */
+ @Override
+ protected void updateLaunchConfigurationDialog() {
+ super.updateLaunchConfigurationDialog();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CDebuggerTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CDebuggerTab.java
new file mode 100644
index 00000000000..7660e19b6d7
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CDebuggerTab.java
@@ -0,0 +1,439 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * Ken Ryall (Nokia) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=118894
+ * IBM Corporation
+ * Ericsson
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.io.IOException;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.ICExtensionReference;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.core.ICDebugConfiguration;
+import org.eclipse.cdt.debug.core.ICDebugConstants;
+import org.eclipse.cdt.debug.ui.ICDebuggerPage;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class CDebuggerTab extends AbstractCDebuggerTab {
+
+ private final static String LOCAL_DEBUGGER_ID = "org.eclipse.cdt.dsf.gdb.GdbDebugger";//$NON-NLS-1$
+ private final static String REMOTE_DEBUGGER_ID = "org.eclipse.cdt.dsf.gdb.GdbServerDebugger";//$NON-NLS-1$
+
+ protected boolean fAttachMode = false;
+ protected boolean fRemoteMode = false;
+
+ protected Button fStopInMain;
+ protected Text fStopInMainSymbol;
+
+ private ScrolledComposite fContainer;
+
+ private Composite fContents;
+
+ public CDebuggerTab(SessionType sessionType, boolean attach) {
+ if (sessionType == SessionType.REMOTE) fRemoteMode = true;
+ fAttachMode = attach;
+
+ ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDefaultDebugConfiguration();
+ if (dc == null) {
+ CDebugCorePlugin.getDefault().getPluginPreferences().setDefault(ICDebugConstants.PREF_DEFAULT_DEBUGGER_TYPE,
+ LOCAL_DEBUGGER_ID);
+ }
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ fContainer = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL);
+ fContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fContainer.setLayout(new FillLayout());
+ fContainer.setExpandHorizontal(true);
+ fContainer.setExpandVertical(true);
+
+ fContents = new Composite(fContainer, SWT.NONE);
+ setControl(fContainer);
+ GdbUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(getControl(),
+ ICDTLaunchHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_DEBBUGER_TAB);
+ int numberOfColumns = (fAttachMode) ? 2 : 1;
+ GridLayout layout = new GridLayout(numberOfColumns, false);
+ fContents.setLayout(layout);
+ GridData gd = new GridData(GridData.BEGINNING, GridData.CENTER, true, false);
+ fContents.setLayoutData(gd);
+
+ createDebuggerCombo(fContents, (fAttachMode) ? 1 : 2);
+ createOptionsComposite(fContents);
+ createDebuggerGroup(fContents, 2);
+
+ fContainer.setContent(fContents);
+ }
+
+ protected void loadDebuggerComboBox(ILaunchConfiguration config, String selection) {
+// String configPlatform = getPlatform(config);
+ ICDebugConfiguration[] debugConfigs = CDebugCorePlugin.getDefault().getActiveDebugConfigurations();
+ Arrays.sort(debugConfigs, new Comparator() {
+ public int compare(ICDebugConfiguration c1, ICDebugConfiguration c2) {
+ return Collator.getInstance().compare(c1.getName(), c2.getName());
+ }
+ });
+ List list = new ArrayList();
+ if (selection.equals("")) { //$NON-NLS-1$
+ ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
+ if (dc == null) {
+ CDebugCorePlugin.getDefault().saveDefaultDebugConfiguration(LOCAL_DEBUGGER_ID);
+ dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
+ }
+ if (dc != null)
+ selection = dc.getID();
+ }
+ String defaultSelection = selection;
+ for (ICDebugConfiguration debugConfig: debugConfigs) {
+ if (((fRemoteMode || fAttachMode) && debugConfig.getID().equals(REMOTE_DEBUGGER_ID)) ||
+ (!fRemoteMode && debugConfig.getID().equals(LOCAL_DEBUGGER_ID))) {
+// String debuggerPlatform = debugConfig.getPlatform();
+// if (validatePlatform(config, debugConfig)) {
+ list.add(debugConfig);
+// // select first exact matching debugger for platform or
+// // requested selection
+// if ((defaultSelection.equals("") && debuggerPlatform.equalsIgnoreCase(configPlatform))) { //$NON-NLS-1$
+// defaultSelection = debugConfig.getID();
+// }
+// }
+ }
+ }
+ // if no selection meaning nothing in config the force initdefault on tab
+ setInitializeDefault(selection.equals("") ? true : false); //$NON-NLS-1$
+ loadDebuggerCombo(list.toArray(new ICDebugConfiguration[list.size()]), defaultSelection);
+ }
+
+ @Override
+ protected void updateComboFromSelection() {
+ super.updateComboFromSelection();
+ initializeCommonControls(getLaunchConfiguration());
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ super.setDefaults(config);
+ if (fAttachMode && fRemoteMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH);
+ } else if (fAttachMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH);
+ } else if (fRemoteMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE);
+ } else {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
+ }
+
+ if (!fAttachMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
+ ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT);
+ }
+
+ // Set the default debugger based on the active toolchain on the project (if possible)
+ String defaultDebugger = null;
+ try {
+ String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, "");//$NON-NLS-1$
+ if (projectName.length() > 0) {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project);
+ ICConfigurationDescription configDesc = projDesc.getActiveConfiguration();
+ String configId = configDesc.getId();
+ ICDebugConfiguration[] debugConfigs = CDebugCorePlugin.getDefault().getActiveDebugConfigurations();
+ outer: for (int i = 0; i < debugConfigs.length; ++i) {
+ ICDebugConfiguration debugConfig = debugConfigs[i];
+ String[] patterns = debugConfig.getSupportedBuildConfigPatterns();
+ if (patterns != null) {
+ for (int j = 0; j < patterns.length; ++j) {
+ if (configId.matches(patterns[j])) {
+ defaultDebugger = debugConfig.getID();
+ break outer;
+ }
+ }
+ }
+ }
+ }
+ } catch (CoreException e) {
+ }
+
+ if (defaultDebugger == null) {
+ ICDebugConfiguration dc = CDebugCorePlugin.getDefault().getDefaultDebugConfiguration();
+ if (dc != null) {
+ defaultDebugger = dc.getID();
+ }
+ }
+
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, defaultDebugger);
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration config) {
+ setInitializing(true);
+ super.initializeFrom(config);
+ try {
+ String id = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID, ""); //$NON-NLS-1$
+ loadDebuggerComboBox(config, id);
+ initializeCommonControls(config);
+ } catch (CoreException e) {
+ }
+ setInitializing(false);
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy config) {
+ super.performApply(config);
+
+ if (fAttachMode && fRemoteMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH);
+ } else if (fAttachMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH);
+ } else if (fRemoteMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE);
+ } else {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
+ ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN);
+ }
+ if (!fAttachMode) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
+ fStopInMain.getSelection());
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
+ fStopInMainSymbol.getText());
+
+ }
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+ if (!validateDebuggerConfig(config)) {
+ return false;
+ }
+// ICDebugConfiguration debugConfig = getDebugConfig();
+// if (fAttachMode && !debugConfig.supportsMode(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH)) {
+// setErrorMessage(MessageFormat.format(LaunchMessages.getString("CDebuggerTab.Mode_not_supported"), //$NON-NLS-1$
+// (Object[]) new String[]{ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH}));
+// return false;
+// }
+// if (fRemoteMode && !debugConfig.supportsMode(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)) {
+// setErrorMessage(MessageFormat.format(LaunchMessages.getString("CDebuggerTab.Mode_not_supported"), //$NON-NLS-1$
+// (Object[]) new String[]{IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE}));
+// return false;
+// }
+// if (!fAttachMode && !fRemoteMode && !debugConfig.supportsMode(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) {
+// setErrorMessage(MessageFormat.format(LaunchMessages.getString("CDebuggerTab.Mode_not_supported"), //$NON-NLS-1$
+// (Object[]) new String[]{ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN}));
+// return false;
+// }
+ if (fStopInMain != null && fStopInMainSymbol != null) {
+ // The "Stop on startup at" field must not be empty
+ String mainSymbol = fStopInMainSymbol.getText().trim();
+ if (fStopInMain.getSelection() && mainSymbol.length() == 0) {
+ setErrorMessage(LaunchMessages.getString("CDebuggerTab.Stop_on_startup_at_can_not_be_empty")); //$NON-NLS-1$
+ return false;
+ }
+ }
+ if (super.isValid(config) == false) {
+ return false;
+ }
+ return true;
+ }
+
+ protected boolean validatePlatform(ILaunchConfiguration config, ICDebugConfiguration debugConfig) {
+ String configPlatform = getPlatform(config);
+ String debuggerPlatform = debugConfig.getPlatform();
+ return (debuggerPlatform.equals("*") || debuggerPlatform.equalsIgnoreCase(configPlatform)); //$NON-NLS-1$
+ }
+
+ protected IBinaryObject getBinary(ILaunchConfiguration config) throws CoreException {
+ String programName = null;
+ String projectName = null;
+ try {
+ projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
+ programName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String)null);
+ } catch (CoreException e) {
+ }
+ if (programName != null) {
+ IPath exePath = new Path(programName);
+ if (projectName != null && !projectName.equals("")) { //$NON-NLS-1$
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ if (!project.isAccessible()) {
+ return null;
+ }
+ if (!exePath.isAbsolute()) {
+ exePath = project.getLocation().append(exePath);
+ }
+ ICExtensionReference[] parserRef = CCorePlugin.getDefault().getBinaryParserExtensions(project);
+ for (int i = 0; i < parserRef.length; i++) {
+ try {
+ IBinaryParser parser = (IBinaryParser)parserRef[i].createExtension();
+ IBinaryObject exe = (IBinaryObject)parser.getBinary(exePath);
+ if (exe != null) {
+ return exe;
+ }
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+ }
+ }
+ IBinaryParser parser = CCorePlugin.getDefault().getDefaultBinaryParser();
+ try {
+ IBinaryObject exe = (IBinaryObject)parser.getBinary(exePath);
+ return exe;
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+ }
+ return null;
+ }
+
+ protected boolean validateDebuggerConfig(ILaunchConfiguration config) {
+ ICDebugConfiguration debugConfig = getDebugConfig();
+ if (debugConfig == null) {
+ setErrorMessage(LaunchMessages.getString("CDebuggerTab.No_debugger_available")); //$NON-NLS-1$
+ return false;
+ }
+ // We do not validate platform and CPU compatibility to avoid accidentally disabling
+ // a valid configuration. It's much better to let an incompatible configuration through
+ // than to disable a valid one.
+ return true;
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog()
+ */
+ protected void update() {
+ if (!isInitializing()) {
+ super.updateLaunchConfigurationDialog();
+ }
+ }
+
+ protected void createOptionsComposite(Composite parent) {
+ Composite optionsComp = new Composite(parent, SWT.NONE);
+ int numberOfColumns = (fAttachMode) ? 1 : 3;
+ GridLayout layout = new GridLayout(numberOfColumns, false);
+ optionsComp.setLayout(layout);
+ optionsComp.setLayoutData(new GridData(GridData.BEGINNING, GridData.CENTER, true, false, 1, 1));
+ if (!fAttachMode) {
+ fStopInMain = createCheckButton(optionsComp, LaunchMessages.getString("CDebuggerTab.Stop_at_main_on_startup")); //$NON-NLS-1$
+ fStopInMain.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ fStopInMainSymbol.setEnabled(fStopInMain.getSelection());
+ update();
+ }
+ });
+ fStopInMainSymbol = new Text(optionsComp, SWT.SINGLE | SWT.BORDER);
+ final GridData gridData = new GridData(GridData.FILL, GridData.CENTER, false, false);
+ gridData.widthHint = 100;
+ fStopInMainSymbol.setLayoutData(gridData);
+ fStopInMainSymbol.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ update();
+ }
+ });
+ fStopInMainSymbol.getAccessible().addAccessibleListener(
+ new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = LaunchMessages.getString("CDebuggerTab.Stop_at_main_on_startup"); //$NON-NLS-1$
+ }
+ }
+ );
+ }
+ }
+
+ @Override
+ protected Shell getShell() {
+ return super.getShell();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose()
+ */
+ @Override
+ public void dispose() {
+ ICDebuggerPage debuggerPage = getDynamicTab();
+ if (debuggerPage != null)
+ debuggerPage.dispose();
+ super.dispose();
+ }
+
+ protected void initializeCommonControls(ILaunchConfiguration config) {
+ try {
+ if (!fAttachMode) {
+ fStopInMain.setSelection(config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN,
+ ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_DEFAULT));
+ fStopInMainSymbol.setText(config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN_SYMBOL,
+ ICDTLaunchConfigurationConstants.DEBUGGER_STOP_AT_MAIN_SYMBOL_DEFAULT));
+ fStopInMainSymbol.setEnabled(fStopInMain.getSelection());
+ } else {
+ // In attach mode, figure out if we are doing a remote connect based on the currently
+ // chosen debugger
+ if (getDebugConfig().getID().equals(REMOTE_DEBUGGER_ID)) fRemoteMode = true;
+ else fRemoteMode = false;
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ @Override
+ protected void setInitializeDefault(boolean init) {
+ super.setInitializeDefault(init);
+ }
+
+ @Override
+ protected void contentsChanged() {
+ fContainer.setMinSize(fContents.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ }
+}
\ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CLaunchConfigurationTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CLaunchConfigurationTab.java
new file mode 100644
index 00000000000..665c0b48e4a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CLaunchConfigurationTab.java
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * Ken Ryall (Nokia) - bug 178731
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.ICDescriptor;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+
+public abstract class CLaunchConfigurationTab extends AbstractLaunchConfigurationTab {
+
+ /**
+ * Returns the current C element context from which to initialize default
+ * settings, or null
if none. Note, if possible we will
+ * return the IBinary based on config entry as this may be more usefull then
+ * just the project.
+ *
+ * @return C element context.
+ */
+ protected ICElement getContext(ILaunchConfiguration config, String platform) {
+ String projectName = null;
+ String programName = null;
+ IWorkbenchPage page = GdbUIPlugin.getActivePage();
+ Object obj = null;
+ try {
+ projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
+ programName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String)null);
+ } catch (CoreException e) {
+ }
+ if (projectName != null && !projectName.equals("")) { //$NON-NLS-1$
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(project);
+ if (cProject != null && cProject.exists()) {
+ obj = cProject;
+ }
+ } else {
+ if (page != null) {
+ ISelection selection = page.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss = (IStructuredSelection)selection;
+ if (!ss.isEmpty()) {
+ obj = ss.getFirstElement();
+ }
+ }
+ }
+ }
+ if (obj instanceof IResource) {
+ ICElement ce = CoreModel.getDefault().create((IResource)obj);
+ if (ce == null) {
+ IProject pro = ((IResource)obj).getProject();
+ ce = CoreModel.getDefault().create(pro);
+ }
+ obj = ce;
+ }
+ if (obj instanceof ICElement) {
+ if (platform != null && !platform.equals("*")) { //$NON-NLS-1$
+ ICDescriptor descriptor;
+ try {
+ descriptor = CCorePlugin.getDefault().getCProjectDescription( ((ICElement)obj).getCProject().getProject(),
+ false);
+ if (descriptor != null) {
+ String projectPlatform = descriptor.getPlatform();
+ if (!projectPlatform.equals(platform) && !projectPlatform.equals("*")) { //$NON-NLS-1$
+ obj = null;
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ if (obj != null) {
+ if (programName == null || programName.equals("")) { //$NON-NLS-1$
+ return (ICElement)obj;
+ }
+ ICElement ce = (ICElement)obj;
+ IProject project;
+ project = (IProject)ce.getCProject().getResource();
+ IPath programFile = project.getFile(programName).getLocation();
+ ce = CCorePlugin.getDefault().getCoreModel().create(programFile);
+ if (ce != null && ce.exists()) {
+ return ce;
+ }
+ return (ICElement)obj;
+ }
+ }
+ IEditorPart part = page.getActiveEditor();
+ if (part != null) {
+ IEditorInput input = part.getEditorInput();
+ return (ICElement)input.getAdapter(ICElement.class);
+ }
+ return null;
+ }
+
+ /**
+ * Set the C project attribute based on the ICElement.
+ */
+ protected void initializeCProject(ICElement cElement, ILaunchConfigurationWorkingCopy config) {
+ ICProject cProject = cElement.getCProject();
+ String name = null;
+ if (cProject != null && cProject.exists()) {
+ name = cProject.getElementName();
+ config.setMappedResources(new IResource[] {cProject.getProject()});
+
+ ICProjectDescription projDes = CCorePlugin.getDefault().getProjectDescription(cProject.getProject());
+ String buildConfigID = projDes.getActiveConfiguration().getId();
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, buildConfigID);
+
+ }
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, name);
+
+ }
+
+ protected String getPlatform(ILaunchConfiguration config) {
+ String platform = Platform.getOS();
+ try {
+ return config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PLATFORM, platform);
+ } catch (CoreException e) {
+ return platform;
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java
new file mode 100644
index 00000000000..8178ab08caa
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/CMainTab.java
@@ -0,0 +1,728 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * Ken Ryall (Nokia) - bug 178731
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.ICDescriptor;
+import org.eclipse.cdt.core.ICExtensionReference;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.IBinary;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+import org.eclipse.cdt.ui.CElementLabelProvider;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+import org.eclipse.ui.dialogs.TwoPaneElementSelector;
+
+/**
+ * A launch configuration tab that displays and edits project and main type name launch
+ * configuration attributes.
+ *
+ * This class may be instantiated. This class is not intended to be subclassed.
+ *
+ */
+
+public class CMainTab extends CLaunchConfigurationTab {
+
+ // Project UI widgets
+ protected Label fProjLabel;
+ protected Text fProjText;
+ protected Button fProjButton;
+
+ // Main class UI widgets
+ protected Label fProgLabel;
+ protected Text fProgText;
+ protected Button fSearchButton;
+
+ private final boolean fWantsTerminalOption;
+ protected Button fTerminalButton;
+
+ private final boolean dontCheckProgram;
+
+ protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+ private String filterPlatform = EMPTY_STRING;
+
+ public static final int WANTS_TERMINAL = 1;
+ public static final int DONT_CHECK_PROGRAM = 2;
+
+ public CMainTab() {
+ this(0);
+ }
+
+ public CMainTab(boolean terminalOption) {
+ this(terminalOption ? WANTS_TERMINAL : 0);
+ }
+
+ public CMainTab(int flags) {
+ fWantsTerminalOption = (flags & WANTS_TERMINAL) != 0;
+ dontCheckProgram = (flags & DONT_CHECK_PROGRAM) != 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+
+ GdbUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(getControl(), ICDTLaunchHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_MAIN_TAB);
+
+ GridLayout topLayout = new GridLayout();
+ comp.setLayout(topLayout);
+
+ createVerticalSpacer(comp, 1);
+ createProjectGroup(comp, 1);
+ createExeFileGroup(comp, 1);
+ createVerticalSpacer(comp, 1);
+ if (wantsTerminalOption() /* && ProcessFactory.supportesTerminal() */) {
+ createTerminalOption(comp, 1);
+ }
+ GdbUIPlugin.setDialogShell(parent.getShell());
+ }
+
+ protected void createProjectGroup(Composite parent, int colSpan) {
+ Composite projComp = new Composite(parent, SWT.NONE);
+ GridLayout projLayout = new GridLayout();
+ projLayout.numColumns = 2;
+ projLayout.marginHeight = 0;
+ projLayout.marginWidth = 0;
+ projComp.setLayout(projLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = colSpan;
+ projComp.setLayoutData(gd);
+
+ fProjLabel = new Label(projComp, SWT.NONE);
+ fProjLabel.setText(LaunchMessages.getString("CMainTab.&ProjectColon")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalSpan = 2;
+ fProjLabel.setLayoutData(gd);
+
+ fProjText = new Text(projComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fProjText.setLayoutData(gd);
+ fProjText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ fProjButton = createPushButton(projComp, LaunchMessages.getString("Launch.common.Browse_1"), null); //$NON-NLS-1$
+ fProjButton.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleProjectButtonSelected();
+ updateLaunchConfigurationDialog();
+ }
+ });
+ }
+
+ protected void createExeFileGroup(Composite parent, int colSpan) {
+ Composite mainComp = new Composite(parent, SWT.NONE);
+ GridLayout mainLayout = new GridLayout();
+ mainLayout.numColumns = 3;
+ mainLayout.marginHeight = 0;
+ mainLayout.marginWidth = 0;
+ mainComp.setLayout(mainLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = colSpan;
+ mainComp.setLayoutData(gd);
+ fProgLabel = new Label(mainComp, SWT.NONE);
+ fProgLabel.setText(LaunchMessages.getString("CMainTab.C/C++_Application")); //$NON-NLS-1$
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ fProgLabel.setLayoutData(gd);
+ fProgText = new Text(mainComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fProgText.setLayoutData(gd);
+ fProgText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ fSearchButton = createPushButton(mainComp, LaunchMessages.getString("CMainTab.Search..."), null); //$NON-NLS-1$
+ fSearchButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleSearchButtonSelected();
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ Button fBrowseForBinaryButton;
+ fBrowseForBinaryButton = createPushButton(mainComp, LaunchMessages.getString("Launch.common.Browse_2"), null); //$NON-NLS-1$
+ fBrowseForBinaryButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleBinaryBrowseButtonSelected();
+ updateLaunchConfigurationDialog();
+ }
+ });
+ }
+
+ protected boolean wantsTerminalOption() {
+ return fWantsTerminalOption;
+ }
+
+ protected void createTerminalOption(Composite parent, int colSpan) {
+ Composite mainComp = new Composite(parent, SWT.NONE);
+ GridLayout mainLayout = new GridLayout();
+ mainLayout.numColumns = 1;
+ mainLayout.marginHeight = 0;
+ mainLayout.marginWidth = 0;
+ mainComp.setLayout(mainLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = colSpan;
+ mainComp.setLayoutData(gd);
+
+ fTerminalButton = createCheckButton(mainComp, LaunchMessages.getString("CMainTab.UseTerminal")); //$NON-NLS-1$
+ fTerminalButton.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ fTerminalButton.setEnabled(PTY.isSupported());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void initializeFrom(ILaunchConfiguration config) {
+ filterPlatform = getPlatform(config);
+ updateProjectFromConfig(config);
+ updateProgramFromConfig(config);
+ updateTerminalFromConfig(config);
+ }
+
+ protected void updateTerminalFromConfig(ILaunchConfiguration config) {
+ if (fTerminalButton != null) {
+ boolean useTerminal = true;
+ try {
+ useTerminal = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT);
+ } catch (CoreException e) {
+ GdbUIPlugin.log(e);
+ }
+ fTerminalButton.setSelection(useTerminal);
+ }
+ }
+
+ protected void updateProjectFromConfig(ILaunchConfiguration config) {
+ String projectName = EMPTY_STRING;
+ try {
+ projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, EMPTY_STRING);
+ } catch (CoreException ce) {
+ GdbUIPlugin.log(ce);
+ }
+ fProjText.setText(projectName);
+ }
+
+ protected void updateProgramFromConfig(ILaunchConfiguration config) {
+ String programName = EMPTY_STRING;
+ try {
+ programName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, EMPTY_STRING);
+ } catch (CoreException ce) {
+ GdbUIPlugin.log(ce);
+ }
+ fProgText.setText(programName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy config) {
+ ICProject cProject = this.getCProject();
+ if (cProject != null)
+ {
+ config.setMappedResources(new IResource[] { cProject.getProject() });
+ try { // Only initialize the build config ID once.
+ if (config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, "").length() == 0)//$NON-NLS-1$
+ {
+ ICProjectDescription projDes = CCorePlugin.getDefault().getProjectDescription(cProject.getProject());
+ if (projDes != null)
+ {
+ String buildConfigID = projDes.getActiveConfiguration().getId();
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, buildConfigID);
+ }
+ }
+ } catch (CoreException e) { e.printStackTrace(); }
+ } else {
+ config.setMappedResources(null);
+ }
+
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, fProjText.getText());
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, fProgText.getText());
+ if (fTerminalButton != null) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, fTerminalButton.getSelection());
+ }
+ }
+
+ /**
+ * Show a dialog that lists all main types
+ */
+ protected void handleSearchButtonSelected() {
+
+ if (getCProject() == null) {
+ MessageDialog.openInformation(getShell(), LaunchMessages.getString("CMainTab.Project_required"), //$NON-NLS-1$
+ LaunchMessages.getString("CMainTab.Enter_project_before_searching_for_program")); //$NON-NLS-1$
+ return;
+ }
+
+ ILabelProvider programLabelProvider = new CElementLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof IBinary) {
+ IBinary bin = (IBinary)element;
+ StringBuffer name = new StringBuffer();
+ name.append(bin.getPath().lastSegment());
+ return name.toString();
+ }
+ return super.getText(element);
+ }
+
+ @Override
+ public Image getImage(Object element) {
+ if (! (element instanceof ICElement)) {
+ return super.getImage(element);
+ }
+ ICElement celement = (ICElement)element;
+
+ if (celement.getElementType() == ICElement.C_BINARY) {
+ IBinary belement = (IBinary)celement;
+ if (belement.isExecutable()) {
+ return DebugUITools.getImage(IDebugUIConstants.IMG_ACT_RUN);
+ }
+ }
+
+ return super.getImage(element);
+ }
+ };
+
+ ILabelProvider qualifierLabelProvider = new CElementLabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof IBinary) {
+ IBinary bin = (IBinary)element;
+ StringBuffer name = new StringBuffer();
+ name.append(bin.getCPU() + (bin.isLittleEndian() ? "le" : "be")); //$NON-NLS-1$ //$NON-NLS-2$
+ name.append(" - "); //$NON-NLS-1$
+ name.append(bin.getPath().toString());
+ return name.toString();
+ }
+ return super.getText(element);
+ }
+ };
+
+ TwoPaneElementSelector dialog = new TwoPaneElementSelector(getShell(), programLabelProvider, qualifierLabelProvider);
+ dialog.setElements(getBinaryFiles(getCProject()));
+ dialog.setMessage(LaunchMessages.getString("CMainTab.Choose_program_to_run")); //$NON-NLS-1$
+ dialog.setTitle(LaunchMessages.getString("CMainTab.Program_Selection")); //$NON-NLS-1$
+ dialog.setUpperListLabel(LaunchMessages.getString("Launch.common.BinariesColon")); //$NON-NLS-1$
+ dialog.setLowerListLabel(LaunchMessages.getString("Launch.common.QualifierColon")); //$NON-NLS-1$
+ dialog.setMultipleSelection(false);
+ // dialog.set
+ if (dialog.open() == Window.OK) {
+ IBinary binary = (IBinary)dialog.getFirstResult();
+ fProgText.setText(binary.getResource().getProjectRelativePath().toString());
+ }
+
+ }
+
+ /**
+ * Show a dialog that lets the user select a project. This in turn provides context for the main
+ * type, allowing the user to key a main type name, or constraining the search for main types to
+ * the specified project.
+ */
+ protected void handleBinaryBrowseButtonSelected() {
+ final ICProject cproject = getCProject();
+ if (cproject == null) {
+ MessageDialog.openInformation(getShell(), LaunchMessages.getString("CMainTab.Project_required"), //$NON-NLS-1$
+ LaunchMessages.getString("CMainTab.Enter_project_before_browsing_for_program")); //$NON-NLS-1$
+ return;
+ }
+ FileDialog fileDialog = new FileDialog(getShell(), SWT.NONE);
+ fileDialog.setFileName(fProgText.getText());
+ String text= fileDialog.open();
+ if (text != null) {
+ fProgText.setText(text);
+ }
+ }
+
+ /**
+ * Iterate through and suck up all of the executable files that we can find.
+ */
+ protected IBinary[] getBinaryFiles(final ICProject cproject) {
+ final Display display;
+ if (cproject == null || !cproject.exists()) {
+ return null;
+ }
+ if (getShell() == null) {
+ display = GdbUIPlugin.getShell().getDisplay();
+ } else {
+ display = getShell().getDisplay();
+ }
+ final Object[] ret = new Object[1];
+ BusyIndicator.showWhile(display, new Runnable() {
+
+ public void run() {
+ try {
+ ret[0] = cproject.getBinaryContainer().getBinaries();
+ } catch (CModelException e) {
+ GdbUIPlugin.errorDialog("Launch UI internal error", e); //$NON-NLS-1$
+ }
+ }
+ });
+
+ return (IBinary[])ret[0];
+ }
+
+ /**
+ * Show a dialog that lets the user select a project. This in turn provides context for the main
+ * type, allowing the user to key a main type name, or constraining the search for main types to
+ * the specified project.
+ */
+ protected void handleProjectButtonSelected() {
+ ICProject project = chooseCProject();
+ if (project == null) {
+ return;
+ }
+
+ String projectName = project.getElementName();
+ fProjText.setText(projectName);
+ }
+
+ /**
+ * Realize a C Project selection dialog and return the first selected project, or null if there
+ * was none.
+ */
+ protected ICProject chooseCProject() {
+ try {
+ ICProject[] projects = getCProjects();
+
+ ILabelProvider labelProvider = new CElementLabelProvider();
+ ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
+ dialog.setTitle(LaunchMessages.getString("CMainTab.Project_Selection")); //$NON-NLS-1$
+ dialog.setMessage(LaunchMessages.getString("CMainTab.Choose_project_to_constrain_search_for_program")); //$NON-NLS-1$
+ dialog.setElements(projects);
+
+ ICProject cProject = getCProject();
+ if (cProject != null) {
+ dialog.setInitialSelections(new Object[]{cProject});
+ }
+ if (dialog.open() == Window.OK) {
+ return (ICProject)dialog.getFirstResult();
+ }
+ } catch (CModelException e) {
+ GdbUIPlugin.errorDialog("Launch UI internal error", e); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Return an array a ICProject whose platform match that of the runtime env.
+ */
+ protected ICProject[] getCProjects() throws CModelException {
+ ICProject cproject[] = CoreModel.getDefault().getCModel().getCProjects();
+ ArrayList list = new ArrayList(cproject.length);
+
+ for (int i = 0; i < cproject.length; i++) {
+ ICDescriptor cdesciptor = null;
+ try {
+ cdesciptor = CCorePlugin.getDefault().getCProjectDescription((IProject)cproject[i].getResource(), false);
+ if (cdesciptor != null) {
+ String projectPlatform = cdesciptor.getPlatform();
+ if (filterPlatform.equals("*") //$NON-NLS-1$
+ || projectPlatform.equals("*") //$NON-NLS-1$
+ || filterPlatform.equalsIgnoreCase(projectPlatform) == true) {
+ list.add(cproject[i]);
+ }
+ } else {
+ list.add(cproject[i]);
+ }
+ } catch (CoreException e) {
+ list.add(cproject[i]);
+ }
+ }
+ return list.toArray(new ICProject[list.size()]);
+ }
+
+ /**
+ * Return the ICProject corresponding to the project name in the project name text field, or
+ * null if the text does not match a project name.
+ */
+ protected ICProject getCProject() {
+ String projectName = fProjText.getText().trim();
+ if (projectName.length() < 1) {
+ return null;
+ }
+ return CoreModel.getDefault().getCModel().getCProject(projectName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ if (dontCheckProgram)
+ return true;
+
+ String name = fProjText.getText().trim();
+ if (name.length() == 0) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Project_not_specified")); //$NON-NLS-1$
+ return false;
+ }
+ if (!ResourcesPlugin.getWorkspace().getRoot().getProject(name).exists()) {
+ setErrorMessage(LaunchMessages.getString("Launch.common.Project_does_not_exist")); //$NON-NLS-1$
+ return false;
+ }
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
+ if (!project.isOpen()) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Project_must_be_opened")); //$NON-NLS-1$
+ return false;
+ }
+
+ name = fProgText.getText().trim();
+ if (name.length() == 0) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Program_not_specified")); //$NON-NLS-1$
+ return false;
+ }
+ if (name.equals(".") || name.equals("..")) { //$NON-NLS-1$ //$NON-NLS-2$
+ setErrorMessage(LaunchMessages.getString("CMainTab.Program_does_not_exist")); //$NON-NLS-1$
+ return false;
+ }
+ IPath exePath = new Path(name);
+ if (!exePath.isAbsolute()) {
+ if (!project.getFile(name).exists()) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Program_does_not_exist")); //$NON-NLS-1$
+ return false;
+ }
+ exePath = project.getFile(name).getLocation();
+ } else {
+ if (!exePath.toFile().exists()) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Program_does_not_exist")); //$NON-NLS-1$
+ return false;
+ }
+ }
+ try {
+ if (!isBinary(project, exePath)) {
+ setErrorMessage(LaunchMessages.getString("CMainTab.Program_is_not_a_recongnized_executable")); //$NON-NLS-1$
+ return false;
+ }
+ } catch (CoreException e) {
+ GdbUIPlugin.log(e);
+ setErrorMessage(e.getLocalizedMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @param project
+ * @param exePath
+ * @return
+ * @throws CoreException
+ */
+ protected boolean isBinary(IProject project, IPath exePath) throws CoreException {
+ ICExtensionReference[] parserRef = CCorePlugin.getDefault().getBinaryParserExtensions(project);
+ for (int i = 0; i < parserRef.length; i++) {
+ try {
+ IBinaryParser parser = (IBinaryParser)parserRef[i].createExtension();
+ IBinaryObject exe = (IBinaryObject)parser.getBinary(exePath);
+ if (exe != null) {
+ return true;
+ }
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+ }
+ IBinaryParser parser = CCorePlugin.getDefault().getDefaultBinaryParser();
+ try {
+ IBinaryObject exe = (IBinaryObject)parser.getBinary(exePath);
+ return exe != null;
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+ return false;
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ // We set empty attributes for project & program so that when one config
+ // is
+ // compared to another, the existence of empty attributes doesn't cause
+ // an
+ // incorrect result (the performApply() method can result in empty
+ // values
+ // for these attributes being set on a config if there is nothing in the
+ // corresponding text boxes)
+ // plus getContext will use this to base context from if set.
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, EMPTY_STRING);
+ ICElement cElement = null;
+ cElement = getContext(config, getPlatform(config));
+ if (cElement != null) {
+ initializeCProject(cElement, config);
+ initializeProgramName(cElement, config);
+ }
+ if (wantsTerminalOption()) {
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_USE_TERMINAL, ICDTLaunchConfigurationConstants.USE_TERMINAL_DEFAULT);
+ }
+ }
+
+ /**
+ * Set the program name attributes on the working copy based on the ICElement
+ */
+ protected void initializeProgramName(ICElement cElement, ILaunchConfigurationWorkingCopy config) {
+
+ boolean renamed = false;
+
+ if (!(cElement instanceof IBinary))
+ {
+ cElement = cElement.getCProject();
+ }
+
+ if (cElement instanceof ICProject) {
+
+ IProject project = cElement.getCProject().getProject();
+ String name = project.getName();
+ ICProjectDescription projDes = CCorePlugin.getDefault().getProjectDescription(project);
+ if (projDes != null) {
+ String buildConfigName = projDes.getActiveConfiguration().getName();
+ name = name + " " + buildConfigName; //$NON-NLS-1$
+ }
+ name = getLaunchConfigurationDialog().generateName(name);
+ config.rename(name);
+ renamed = true;
+ }
+
+ IBinary binary = null;
+ if (cElement instanceof ICProject) {
+ IBinary[] bins = getBinaryFiles((ICProject)cElement);
+ if (bins != null && bins.length == 1) {
+ binary = bins[0];
+ }
+ } else if (cElement instanceof IBinary) {
+ binary = (IBinary)cElement;
+ }
+
+ if (binary != null) {
+ String path;
+ path = binary.getResource().getProjectRelativePath().toOSString();
+ config.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, path);
+ if (!renamed)
+ {
+ String name = binary.getElementName();
+ int index = name.lastIndexOf('.');
+ if (index > 0) {
+ name = name.substring(0, index);
+ }
+ name = getLaunchConfigurationDialog().generateName(name);
+ config.rename(name);
+ renamed = true;
+ }
+ }
+
+ if (!renamed)
+ {
+ String name = getLaunchConfigurationDialog().generateName(cElement.getCProject().getElementName());
+ config.rename(name);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ public String getName() {
+ return LaunchMessages.getString("CMainTab.Main"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+ */
+ @Override
+ public Image getImage() {
+ return LaunchImages.get(LaunchImages.IMG_VIEW_MAIN_TAB);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog()
+ */
+ @Override
+ protected void updateLaunchConfigurationDialog() {
+ super.updateLaunchConfigurationDialog();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GDBSolibBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GDBSolibBlock.java
new file mode 100644
index 00000000000..6a5bd6a1023
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GDBSolibBlock.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The content of the Shared Libraries
tab of the GDBDebuggerPage
.
+ */
+public class GDBSolibBlock extends Observable implements IMILaunchConfigurationComponent, Observer {
+
+ private IMILaunchConfigurationComponent fSolibSearchPathBlock;
+
+ private Button fAutoSoLibButton;
+
+ private Button fUseSolibForAppButton;
+
+ private Composite fControl;
+
+ private boolean fAutoSolib = false;
+
+ private boolean fUseSolibForApp = true;
+
+ public GDBSolibBlock( IMILaunchConfigurationComponent solibSearchBlock, boolean autoSolib, boolean stopOnSolibEvents ) {
+ super();
+ fSolibSearchPathBlock = solibSearchBlock;
+ fAutoSolib = autoSolib;
+ }
+
+ public void createControl( Composite parent ) {
+ Composite subComp = ControlFactory.createCompositeEx( parent, 1, GridData.FILL_HORIZONTAL );
+ ((GridLayout)subComp.getLayout()).makeColumnsEqualWidth = false;
+ ((GridLayout)subComp.getLayout()).marginHeight = 0;
+ ((GridLayout)subComp.getLayout()).marginWidth = 0;
+ if ( fSolibSearchPathBlock != null ) {
+ fSolibSearchPathBlock.createControl( subComp );
+ if ( fSolibSearchPathBlock instanceof Observable )
+ ((Observable)fSolibSearchPathBlock).addObserver( this );
+ }
+ if ( fAutoSolib ) {
+ fAutoSoLibButton = ControlFactory.createCheckBox( subComp, LaunchUIMessages.getString( "GDBSolibBlock.0" ) ); //$NON-NLS-1$
+ fAutoSoLibButton.addSelectionListener( new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected( SelectionEvent e ) {
+ updateButtons();
+ changed();
+ }
+ } );
+ }
+ if ( fUseSolibForApp ) {
+ fUseSolibForAppButton = ControlFactory.createCheckBox( subComp, LaunchUIMessages.getString( "GDBSolibBlock.2" ) ); //$NON-NLS-1$
+ fUseSolibForAppButton.addSelectionListener( new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected( SelectionEvent e ) {
+ updateButtons();
+ changed();
+ }
+ } );
+ }
+ fControl = subComp;
+ }
+
+ public void initializeFrom( ILaunchConfiguration configuration ) {
+ if ( fSolibSearchPathBlock != null )
+ fSolibSearchPathBlock.initializeFrom( configuration );
+ try {
+ if ( fAutoSoLibButton != null )
+ fAutoSoLibButton.setSelection( configuration.getAttribute( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB, IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT ) );
+ if ( fUseSolibForAppButton != null )
+ fUseSolibForAppButton.setSelection( configuration.getAttribute( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP, IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT ) );
+ initializeButtons( configuration );
+ updateButtons();
+ }
+ catch( CoreException e ) {
+ }
+ }
+
+ public void performApply( ILaunchConfigurationWorkingCopy configuration ) {
+ if ( fSolibSearchPathBlock != null )
+ fSolibSearchPathBlock.performApply( configuration );
+ try {
+ @SuppressWarnings("unchecked")
+ Map attrs = configuration.getAttributes();
+
+ if ( fAutoSoLibButton != null )
+ attrs.put( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB, Boolean.valueOf( fAutoSoLibButton.getSelection() ) );
+ if ( fUseSolibForAppButton != null )
+ attrs.put( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP, Boolean.valueOf( fUseSolibForAppButton.getSelection() ) );
+ configuration.setAttributes( attrs );
+ }
+ catch( CoreException e ) {
+ }
+ }
+
+ public void setDefaults( ILaunchConfigurationWorkingCopy configuration ) {
+ if ( fSolibSearchPathBlock != null )
+ fSolibSearchPathBlock.setDefaults( configuration );
+ configuration.setAttribute( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB, IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT );
+ configuration.setAttribute( IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP, IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT );
+ }
+
+ protected void updateButtons() {
+ }
+
+ public void dispose() {
+ deleteObservers();
+ if ( fSolibSearchPathBlock != null ) {
+ if ( fSolibSearchPathBlock instanceof Observable )
+ ((Observable)fSolibSearchPathBlock).deleteObserver( this );
+ fSolibSearchPathBlock.dispose();
+ }
+ }
+
+ public void update( Observable o, Object arg ) {
+ changed();
+ }
+
+ protected void changed() {
+ setChanged();
+ notifyObservers();
+ }
+
+ protected void initializeButtons( ILaunchConfiguration configuration ) {
+ try {
+ boolean enable = !ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE.equals( configuration.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, "" ) ); //$NON-NLS-1$
+ if ( fAutoSoLibButton != null )
+ fAutoSoLibButton.setEnabled( enable );
+ if ( fUseSolibForAppButton != null )
+ fUseSolibForAppButton.setEnabled( enable );
+ }
+ catch( CoreException e ) {
+ }
+ }
+
+ public Control getControl() {
+ return fControl;
+ }
+
+ public boolean isValid( ILaunchConfiguration launchConfig ) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbAttachLaunchConfigurationTabGroup.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbAttachLaunchConfigurationTabGroup.java
new file mode 100644
index 00000000000..f72f9845179
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbAttachLaunchConfigurationTabGroup.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
+
+public class GdbAttachLaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
+ */
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+ new CMainTab(2), // In some case, we don't need to specify an executable
+ // We don't know yet if we are going to do a remote or local session
+ new CDebuggerTab(null, true),
+ new SourceLookupTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java
new file mode 100644
index 00000000000..8a6a1478ad8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbDebuggerPage.java
@@ -0,0 +1,365 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.io.File;
+import java.util.Observable;
+import java.util.Observer;
+
+import org.eclipse.cdt.debug.ui.AbstractCDebuggerPage;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * The dynamic tab for gdb-based debugger implementations.
+ */
+public class GdbDebuggerPage extends AbstractCDebuggerPage implements Observer {
+
+ protected TabFolder fTabFolder;
+ protected Text fGDBCommandText;
+ protected Text fGDBInitText;
+ protected Button fNonStopCheckBox;
+ protected Button fVerboseModeButton;
+
+ private IMILaunchConfigurationComponent fSolibBlock;
+ private boolean fIsInitializing = false;
+
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ comp.setLayout(new GridLayout());
+ comp.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fTabFolder = new TabFolder(comp, SWT.NONE);
+ fTabFolder.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_VERTICAL));
+ createTabs(fTabFolder);
+ fTabFolder.setSelection(0);
+ setControl(parent);
+ }
+
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
+ IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
+ IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT);
+
+ if (fSolibBlock != null)
+ fSolibBlock.setDefaults(configuration);
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ boolean valid = fGDBCommandText.getText().length() != 0;
+ if (valid) {
+ setErrorMessage(null);
+ setMessage(null);
+ }
+ else {
+ setErrorMessage(LaunchUIMessages.getString("GDBDebuggerPage.0")); //$NON-NLS-1$
+ setMessage(null);
+ }
+ return valid;
+ }
+
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ setInitializing(true);
+ String gdbCommand = IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT;
+ String gdbInit = IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT;
+ boolean nonStopMode = IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT;
+ boolean verboseMode = IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT;
+
+ try {
+ gdbCommand = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
+ IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
+ }
+ catch(CoreException e) {
+ }
+ try {
+ gdbInit = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
+ IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
+ }
+ catch(CoreException e) {
+ }
+
+ try {
+ nonStopMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
+ }
+ catch(CoreException e) {
+ }
+ try {
+ verboseMode = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT );
+ }
+ catch(CoreException e) {
+ }
+
+ if (fSolibBlock != null)
+ fSolibBlock.initializeFrom(configuration);
+ fGDBCommandText.setText(gdbCommand);
+ fGDBInitText.setText(gdbInit);
+ fNonStopCheckBox.setSelection(nonStopMode);
+ fVerboseModeButton.setSelection(verboseMode);
+
+ setInitializing(false);
+ }
+
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
+ fGDBCommandText.getText().trim());
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
+ fGDBInitText.getText().trim());
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ fNonStopCheckBox.getSelection());
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
+ fVerboseModeButton.getSelection() );
+
+ if (fSolibBlock != null)
+ fSolibBlock.performApply(configuration);
+ }
+
+ public String getName() {
+ return LaunchUIMessages.getString("GDBDebuggerPage.1"); //$NON-NLS-1$
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getShell()
+ */
+ @Override
+ protected Shell getShell() {
+ return super.getShell();
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog()
+ */
+ @Override
+ protected void updateLaunchConfigurationDialog() {
+ super.updateLaunchConfigurationDialog();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
+ */
+ public void update(Observable o, Object arg) {
+ if (!isInitializing())
+ updateLaunchConfigurationDialog();
+ }
+
+ public IMILaunchConfigurationComponent createSolibBlock(Composite parent) {
+ IMILaunchConfigurationComponent block = new GDBSolibBlock( new SolibSearchPathBlock(), true, true);
+ block.createControl(parent);
+ return block;
+ }
+
+ public void createTabs(TabFolder tabFolder) {
+ createMainTab(tabFolder);
+ createSolibTab(tabFolder);
+ }
+
+ public void createMainTab(TabFolder tabFolder) {
+ TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
+ tabItem.setText(LaunchUIMessages.getString("GDBDebuggerPage.2")); //$NON-NLS-1$
+ Composite comp = ControlFactory.createCompositeEx(tabFolder, 1, GridData.FILL_BOTH);
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ comp.setFont(tabFolder.getFont());
+ tabItem.setControl(comp);
+ Composite subComp = ControlFactory.createCompositeEx(comp, 3, GridData.FILL_HORIZONTAL);
+ ((GridLayout)subComp.getLayout()).makeColumnsEqualWidth = false;
+ subComp.setFont(tabFolder.getFont());
+ Label label = ControlFactory.createLabel(subComp, LaunchUIMessages.getString("GDBDebuggerPage.3")); //$NON-NLS-1$
+ GridData gd = new GridData();
+ // gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+ fGDBCommandText = ControlFactory.createTextField(subComp, SWT.SINGLE | SWT.BORDER);
+ fGDBCommandText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ if (!isInitializing())
+ updateLaunchConfigurationDialog();
+ }
+ });
+ Button button = createPushButton(subComp, LaunchUIMessages.getString("GDBDebuggerPage.4"), null); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleGDBButtonSelected();
+ updateLaunchConfigurationDialog();
+ }
+
+ private void handleGDBButtonSelected() {
+ FileDialog dialog = new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(LaunchUIMessages.getString("GDBDebuggerPage.5")); //$NON-NLS-1$
+ String gdbCommand = fGDBCommandText.getText().trim();
+ int lastSeparatorIndex = gdbCommand.lastIndexOf(File.separator);
+ if (lastSeparatorIndex != -1) {
+ dialog.setFilterPath(gdbCommand.substring(0, lastSeparatorIndex));
+ }
+ String res = dialog.open();
+ if (res == null) {
+ return;
+ }
+ fGDBCommandText.setText(res);
+ }
+ });
+ label = ControlFactory.createLabel(subComp, LaunchUIMessages.getString("GDBDebuggerPage.6")); //$NON-NLS-1$
+ gd = new GridData();
+ // gd.horizontalSpan = 2;
+ label.setLayoutData(gd);
+ fGDBInitText = ControlFactory.createTextField(subComp, SWT.SINGLE | SWT.BORDER);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fGDBInitText.setLayoutData(gd);
+ fGDBInitText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent evt) {
+ if (!isInitializing())
+ updateLaunchConfigurationDialog();
+ }
+ });
+ button = createPushButton(subComp, LaunchUIMessages.getString("GDBDebuggerPage.7"), null); //$NON-NLS-1$
+ button.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleGDBInitButtonSelected();
+ updateLaunchConfigurationDialog();
+ }
+
+ private void handleGDBInitButtonSelected() {
+ FileDialog dialog = new FileDialog(getShell(), SWT.NONE);
+ dialog.setText(LaunchUIMessages.getString("GDBDebuggerPage.8")); //$NON-NLS-1$
+ String gdbCommand = fGDBInitText.getText().trim();
+ int lastSeparatorIndex = gdbCommand.lastIndexOf(File.separator);
+ if (lastSeparatorIndex != -1) {
+ dialog.setFilterPath(gdbCommand.substring(0, lastSeparatorIndex));
+ }
+ String res = dialog.open();
+ if (res == null) {
+ return;
+ }
+ fGDBInitText.setText(res);
+ }
+ });
+
+ label = ControlFactory.createLabel(subComp, LaunchUIMessages.getString("GDBDebuggerPage.9"), //$NON-NLS-1$
+ 200, SWT.DEFAULT, SWT.WRAP);
+
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 3;
+ gd.widthHint = 200;
+ label.setLayoutData(gd);
+
+ // TODO: Ideally, this field should be disabled if the back-end doesn't support non-stop debugging
+ // TODO: Find a way to determine if non-stop is supported (i.e. find the GDB version) then grey out the check box if necessary
+ fNonStopCheckBox = ControlFactory.createCheckBox(subComp, LaunchUIMessages.getString("GDBDebuggerPage.13")); //$NON-NLS-1$
+ fNonStopCheckBox.addSelectionListener( new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ fVerboseModeButton = ControlFactory.createCheckBox( subComp, LaunchUIMessages.getString( "StandardGDBDebuggerPage.13" ) ); //$NON-NLS-1$
+ fVerboseModeButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ if (!isInitializing())
+ updateLaunchConfigurationDialog();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (!isInitializing())
+ updateLaunchConfigurationDialog();
+ }
+ });
+
+ // fit options one per line
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ fNonStopCheckBox.setLayoutData(gd);
+ gd = new GridData();
+ gd.horizontalSpan = 3;
+ fVerboseModeButton.setLayoutData(gd);
+
+ // Grayed out until bug 249227 is resolved
+ //
+ fVerboseModeButton.setVisible(false);
+ //
+
+ }
+
+ public void createSolibTab(TabFolder tabFolder) {
+ TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
+ tabItem.setText(LaunchUIMessages.getString("GDBDebuggerPage.10")); //$NON-NLS-1$
+ Composite comp = ControlFactory.createCompositeEx(fTabFolder, 1, GridData.FILL_BOTH);
+ comp.setFont(tabFolder.getFont());
+ tabItem.setControl(comp);
+ fSolibBlock = createSolibBlock(comp);
+ if (fSolibBlock instanceof Observable)
+ ((Observable)fSolibBlock).addObserver(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose()
+ */
+ @Override
+ public void dispose() {
+ if (fSolibBlock != null) {
+ if (fSolibBlock instanceof Observable)
+ ((Observable)fSolibBlock).deleteObserver(this);
+ fSolibBlock.dispose();
+ }
+ super.dispose();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#activated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ @Override
+ public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
+ // Override the default behavior
+ }
+
+ protected boolean isInitializing() {
+ return fIsInitializing;
+ }
+
+ private void setInitializing(boolean isInitializing) {
+ fIsInitializing = isInitializing;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbLocalRunLaunchConfigurationTabGroup.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbLocalRunLaunchConfigurationTabGroup.java
new file mode 100644
index 00000000000..cfeb8ae04bc
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbLocalRunLaunchConfigurationTabGroup.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
+
+public class GdbLocalRunLaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
+ */
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+ new CMainTab(),
+ new CArgumentsTab(),
+ new CDebuggerTab(SessionType.LOCAL, false),
+ new SourceLookupTab(),
+// new EnvironmentTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbRemoteRunLaunchConfigurationTabGroup.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbRemoteRunLaunchConfigurationTabGroup.java
new file mode 100644
index 00000000000..25f35df62be
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbRemoteRunLaunchConfigurationTabGroup.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.CommonTab;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.debug.ui.sourcelookup.SourceLookupTab;
+
+public class GdbRemoteRunLaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTabGroup#createTabs(org.eclipse.debug.ui.ILaunchConfigurationDialog, java.lang.String)
+ */
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {
+ new CMainTab(),
+ new CDebuggerTab(SessionType.REMOTE, false),
+ new SourceLookupTab(),
+ new CommonTab()
+ };
+ setTabs(tabs);
+ }
+}
\ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbServerDebuggerPage.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbServerDebuggerPage.java
new file mode 100644
index 00000000000..420fc982048
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/GdbServerDebuggerPage.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * IBM Corporation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.debug.internal.ui.dialogfields.ComboDialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.DialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.IDialogFieldListener;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+
+/**
+ * The dynamic debugger tab for remote launches using gdb server.
+ */
+public class GdbServerDebuggerPage extends GdbDebuggerPage {
+
+ private final static String CONNECTION_TCP = LaunchUIMessages.getString("GDBServerDebuggerPage.0"); //$NON-NLS-1$
+
+ private final static String CONNECTION_SERIAL = LaunchUIMessages.getString("GDBServerDebuggerPage.1"); //$NON-NLS-1$
+
+ private ComboDialogField fConnectionField;
+
+ private String[] fConnections = new String[]{ CONNECTION_TCP, CONNECTION_SERIAL };
+
+ private TCPSettingsBlock fTCPBlock;
+
+ private SerialPortSettingsBlock fSerialBlock;
+
+ private Composite fConnectionStack;
+
+ private boolean fIsInitializing = false;
+
+ public GdbServerDebuggerPage() {
+ super();
+ fConnectionField = createConnectionField();
+ fTCPBlock = new TCPSettingsBlock();
+ fSerialBlock = new SerialPortSettingsBlock();
+ fTCPBlock.addObserver(this);
+ fSerialBlock.addObserver(this);
+ }
+
+ protected void createConnectionTab(TabFolder tabFolder) {
+ TabItem tabItem = new TabItem(tabFolder, SWT.NONE);
+ tabItem.setText(LaunchUIMessages.getString("GDBServerDebuggerPage.10")); //$NON-NLS-1$
+ Composite comp1 = ControlFactory.createCompositeEx(tabFolder, 1, GridData.FILL_BOTH);
+ ((GridLayout)comp1.getLayout()).makeColumnsEqualWidth = false;
+ comp1.setFont(tabFolder.getFont());
+ tabItem.setControl(comp1);
+ Composite comp = ControlFactory.createCompositeEx(comp1, 2, GridData.FILL_BOTH);
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ comp.setFont(comp1.getFont());
+ fConnectionField.doFillIntoGrid(comp, 2);
+ ((GridData)fConnectionField.getComboControl(null).getLayoutData()).horizontalAlignment = GridData.BEGINNING;
+ fConnectionStack = ControlFactory.createCompositeEx(comp, 1, GridData.FILL_BOTH);
+ StackLayout stackLayout = new StackLayout();
+ fConnectionStack.setLayout(stackLayout);
+ ((GridData)fConnectionStack.getLayoutData()).horizontalSpan = 2;
+ fTCPBlock.createBlock(fConnectionStack);
+ fSerialBlock.createBlock(fConnectionStack);
+ }
+
+ private ComboDialogField createConnectionField() {
+ ComboDialogField field = new ComboDialogField(SWT.DROP_DOWN | SWT.READ_ONLY);
+ field.setLabelText(LaunchUIMessages.getString("GDBServerDebuggerPage.9")); //$NON-NLS-1$
+ field.setItems(fConnections);
+ field.setDialogFieldListener(new IDialogFieldListener() {
+
+ public void dialogFieldChanged(DialogField f) {
+ if (!isInitializing())
+ connectionTypeChanged();
+ }
+ });
+ return field;
+ }
+
+ protected void connectionTypeChanged() {
+ connectionTypeChanged0();
+ updateLaunchConfigurationDialog();
+ }
+
+ private void connectionTypeChanged0() {
+ ((StackLayout)fConnectionStack.getLayout()).topControl = null;
+ int index = fConnectionField.getSelectionIndex();
+ if (index >= 0 && index < fConnections.length) {
+ String[] connTypes = fConnectionField.getItems();
+ if (CONNECTION_TCP.equals(connTypes[index]))
+ ((StackLayout)fConnectionStack.getLayout()).topControl = fTCPBlock.getControl();
+ else if (CONNECTION_SERIAL.equals(connTypes[index]))
+ ((StackLayout)fConnectionStack.getLayout()).topControl = fSerialBlock.getControl();
+ }
+ fConnectionStack.layout();
+ }
+
+ @Override
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ if (super.isValid(launchConfig)) {
+ setErrorMessage(null);
+ setMessage(null);
+ int index = fConnectionField.getSelectionIndex();
+ if (index >= 0 && index < fConnections.length) {
+ String[] connTypes = fConnectionField.getItems();
+ if (CONNECTION_TCP.equals(connTypes[index])) {
+ if (!fTCPBlock.isValid(launchConfig)) {
+ setErrorMessage(fTCPBlock.getErrorMessage());
+ return false;
+ }
+ }
+ else if (CONNECTION_SERIAL.equals(connTypes[index])) {
+ if (!fSerialBlock.isValid(launchConfig)) {
+ setErrorMessage(fSerialBlock.getErrorMessage());
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ setInitializing(true);
+ super.initializeFrom(configuration);
+ boolean isTcp = false;
+ try {
+ isTcp = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, false);
+ }
+ catch(CoreException e) {
+ }
+ fTCPBlock.initializeFrom(configuration);
+ fSerialBlock.initializeFrom(configuration);
+ fConnectionField.selectItem((isTcp) ? 0 : 1);
+ connectionTypeChanged0();
+ setInitializing(false);
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ super.performApply(configuration);
+ if (fConnectionField != null)
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, fConnectionField.getSelectionIndex() == 0);
+ fTCPBlock.performApply(configuration);
+ fSerialBlock.performApply(configuration);
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ super.setDefaults(configuration);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, false);
+ fTCPBlock.setDefaults(configuration);
+ fSerialBlock.setDefaults(configuration);
+ }
+
+ @Override
+ protected boolean isInitializing() {
+ return fIsInitializing;
+ }
+
+ private void setInitializing(boolean isInitializing) {
+ fIsInitializing = isInitializing;
+ }
+
+ @Override
+ public void createTabs(TabFolder tabFolder) {
+ super.createTabs(tabFolder);
+ createConnectionTab(tabFolder);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ICDTLaunchHelpContextIds.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ICDTLaunchHelpContextIds.java
new file mode 100644
index 00000000000..8ffc588f17f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ICDTLaunchHelpContextIds.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+
+public interface ICDTLaunchHelpContextIds {
+
+ public static final String PREFIX = GdbUIPlugin.PLUGIN_ID + "."; //$NON-NLS-1$
+
+ // Launch configuration dialog pages
+ public static final String LAUNCH_CONFIGURATION_DIALOG_MAIN_TAB = PREFIX + "launch_configuration_dialog_main_tab"; //$NON-NLS-1$
+ public static final String LAUNCH_CONFIGURATION_DIALOG_ARGUMNETS_TAB = PREFIX + "launch_configuration_dialog_arguments_tab"; //$NON-NLS-1$
+ public static final String LAUNCH_CONFIGURATION_DIALOG_ENVIRONMENT_TAB = PREFIX + "launch_configuration_dialog_environment_tab"; //$NON-NLS-1$
+ public static final String LAUNCH_CONFIGURATION_DIALOG_DEBBUGER_TAB = PREFIX + "launch_configuration_dialog_debugger_tab"; //$NON-NLS-1$
+ public static final String LAUNCH_CONFIGURATION_DIALOG_SOURCELOOKUP_TAB = PREFIX + "launch_configuration_dialog_source_tab"; //$NON-NLS-1$
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/IMILaunchConfigurationComponent.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/IMILaunchConfigurationComponent.java
new file mode 100644
index 00000000000..3f7d8df058d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/IMILaunchConfigurationComponent.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * The common interface for UI components of the launch configuration tabs.
+ */
+public interface IMILaunchConfigurationComponent {
+
+ /**
+ * Creates the top level control for this component under the given parent composite.
+ *
+ * Implementors are responsible for ensuring that the created control can be accessed via getControl
+ *
+ *
+ * @param parent the parent composite
+ */
+ public void createControl( Composite parent );
+
+ /**
+ * Returns the top level control for this component.
+ *
+ * May return null
if the control has not been created yet.
+ *
+ *
+ * @return the top level control or null
+ */
+ public Control getControl();
+
+ /**
+ * Initializes the given component with default values.
+ * This method may be called before this tab's control is created.
+ *
+ * @param configuration launch configuration
+ */
+ public void setDefaults( ILaunchConfigurationWorkingCopy configuration );
+
+ /**
+ * Initializes this component's controls with values from the given
+ * launch configuration.
+ *
+ * @param configuration launch configuration
+ */
+ public void initializeFrom( ILaunchConfiguration configuration );
+
+ /**
+ * Notifies this component that it has been disposed.
+ * Marks the end of this component's lifecycle, allowing
+ * to perform any cleanup required.
+ */
+ public void dispose();
+
+ /**
+ * Copies values from this component into the given launch configuration.
+ *
+ * @param configuration launch configuration
+ */
+ public void performApply( ILaunchConfigurationWorkingCopy configuration );
+
+ /**
+ * Returns whether this component is in a valid state in the context
+ * of the specified launch configuration.
+ *
+ * @param launchConfig launch configuration which provides context
+ * for validating this component.
+ * This value must not be null
.
+ *
+ * @return whether this component is in a valid state
+ */
+ public boolean isValid(ILaunchConfiguration launchConfig);
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchImages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchImages.java
new file mode 100644
index 00000000000..453a4db3a1f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchImages.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.graphics.Image;
+
+public class LaunchImages {
+ private static final String NAME_PREFIX= GdbUIPlugin.PLUGIN_ID + '.';
+ private static final int NAME_PREFIX_LENGTH= NAME_PREFIX.length();
+
+ // The plugin registry
+ private static ImageRegistry imageRegistry = new ImageRegistry();
+
+ // Subdirectory (under the package containing this class) where 16 color images are
+ private static URL fgIconBaseURL;
+ static {
+ fgIconBaseURL= Platform.getBundle(GdbUIPlugin.PLUGIN_ID).getEntry("/icons/"); //$NON-NLS-1$
+ }
+
+ private static final String T_TABS = "full/view16/"; //$NON-NLS-1$
+ private static final String T_OBJS = "full/obj16/"; //$NON-NLS-1$
+
+ public static String IMG_VIEW_MAIN_TAB = NAME_PREFIX + "main_tab.gif"; //$NON-NLS-1$
+ public static String IMG_VIEW_ARGUMENTS_TAB = NAME_PREFIX + "arguments_tab.gif"; //$NON-NLS-1$
+ public static String IMG_VIEW_DEBUGGER_TAB = NAME_PREFIX + "debugger_tab.gif"; //$NON-NLS-1$
+
+ public static final ImageDescriptor DESC_TAB_MAIN= createManaged(T_TABS, IMG_VIEW_MAIN_TAB);
+ public static final ImageDescriptor DESC_TAB_ARGUMENTS = createManaged(T_TABS, IMG_VIEW_ARGUMENTS_TAB);
+ public static final ImageDescriptor DESC_TAB_DEBUGGER = createManaged(T_TABS, IMG_VIEW_DEBUGGER_TAB);
+
+ public static String IMG_OBJS_EXEC= NAME_PREFIX + "exec_obj.gif"; //$NON-NLS-1$
+ public static final ImageDescriptor DESC_OBJS_EXEC = createManaged(T_OBJS, IMG_OBJS_EXEC);
+
+ public static void initialize() {
+ }
+
+ private static ImageDescriptor createManaged(String prefix, String name) {
+ return createManaged(imageRegistry, prefix, name);
+ }
+
+ private static ImageDescriptor createManaged(ImageRegistry registry, String prefix, String name) {
+ ImageDescriptor result= ImageDescriptor.createFromURL(makeIconFileURL(prefix, name.substring(NAME_PREFIX_LENGTH)));
+ registry.put(name, result);
+ return result;
+ }
+
+ public static Image get(String key) {
+ return imageRegistry.get(key);
+ }
+
+
+ private static URL makeIconFileURL(String prefix, String name) {
+ StringBuffer buffer= new StringBuffer(prefix);
+ buffer.append(name);
+ try {
+ return new URL(fgIconBaseURL, buffer.toString());
+ } catch (MalformedURLException e) {
+ GdbUIPlugin.log(e);
+ return null;
+ }
+ }
+
+ /**
+ * Helper method to access the image registry from the JavaPlugin class.
+ */
+ static ImageRegistry getImageRegistry() {
+ return imageRegistry;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.java
new file mode 100644
index 00000000000..1b428fbd62f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.internal.ui.launching;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class LaunchUIMessages {
+
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages";//$NON-NLS-1$
+
+ private static ResourceBundle RESOURCE_BUNDLE = null;
+
+ static {
+ try {
+ RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+ }
+ catch (MissingResourceException x) {
+ }
+ }
+
+ private LaunchUIMessages() {}
+
+ public static String getFormattedString(String key, String arg) {
+ return MessageFormat.format(getString(key), (Object[])new String[]{arg});
+ }
+
+ public static String getFormattedString(String key, String[] args) {
+ return MessageFormat.format(getString(key), (Object[])args);
+ }
+
+ public static String getString(String key) {
+ if (RESOURCE_BUNDLE == null) return '!' + key + '!';
+ return RESOURCE_BUNDLE.getString(key);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties
new file mode 100644
index 00000000000..d317535bfd3
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties
@@ -0,0 +1,225 @@
+###############################################################################
+# Copyright (c) 2003, 2008 QNX Software Systems and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# QNX Software Systems - initial API and implementation
+# Ericsson - Updated for DSF
+###############################################################################
+
+CygwinDebuggerPage.0=Cygwin GDB Debugger Options
+GDBDebuggerPage.0=Debugger executable must be specified.
+GDBDebuggerPage.1=GDB Debugger Options
+GDBDebuggerPage.2=Main
+GDBDebuggerPage.3=GDB debugger:
+GDBDebuggerPage.4=&Browse...
+GDBDebuggerPage.5=GDB Debugger
+GDBDebuggerPage.6=GDB command file:
+GDBDebuggerPage.7=B&rowse...
+GDBDebuggerPage.8=GDB Command File
+GDBDebuggerPage.9=(Warning: Some commands in this file may interfere with the startup operation of the debugger, for example "run".)
+GDBDebuggerPage.10=Shared Libraries
+GDBDebuggerPage.11=Protocol:
+GDBDebuggerPage.12=Default
+GDBDebuggerPage.13=Non-stop mode (Note: Requires non-stop GDB)
+StandardGDBDebuggerPage.0=Debugger executable must be specified.
+StandardGDBDebuggerPage.1=GDB Debugger Options
+StandardGDBDebuggerPage.2=Main
+StandardGDBDebuggerPage.3=GDB debugger:
+StandardGDBDebuggerPage.4=&Browse...
+StandardGDBDebuggerPage.5=GDB Debugger
+StandardGDBDebuggerPage.6=GDB command file:
+StandardGDBDebuggerPage.7=B&rowse...
+StandardGDBDebuggerPage.8=GDB Command File
+StandardGDBDebuggerPage.9=(Warning: Some commands in this file may interfere with the startup operation of the debugger, for example "run".)
+StandardGDBDebuggerPage.10=Shared Libraries
+StandardGDBDebuggerPage.11=Protocol:
+StandardGDBDebuggerPage.12=GDB command set:
+StandardGDBDebuggerPage.13=Verbose console mode
+StandardGDBDebuggerPage.14=Use full file path to set breakpoints
+GDBServerDebuggerPage.0=TCP
+GDBServerDebuggerPage.1=Serial
+GDBServerDebuggerPage.10=Connection
+GDBServerDebuggerPage.2=Main
+GDBServerDebuggerPage.3=GDB debugger
+GDBServerDebuggerPage.4=&Browse...
+GDBServerDebuggerPage.5=GDB Debugger
+GDBServerDebuggerPage.6=GDB command file:
+GDBServerDebuggerPage.7=B&rowse...
+GDBServerDebuggerPage.8=GDB Command File
+GDBServerDebuggerPage.9=Type:
+GDBSolibBlock.0=Load shared library symbols automatically
+GDBSolibBlock.1=Stop on shared library events
+GDBSolibBlock.2=Use shared library symbols for debugged applications
+SerialPortSettingsBlock.0=Device:
+SerialPortSettingsBlock.1=Speed:
+SerialPortSettingsBlock.2=Device must be specified.
+SerialPortSettingsBlock.3=Invalid device.
+SerialPortSettingsBlock.4=Speed must be specified.
+SolibSearchPathBlock.0=Add...
+SolibSearchPathBlock.1=Up
+SolibSearchPathBlock.2=Down
+SolibSearchPathBlock.3=Remove
+SolibSearchPathBlock.4=Directories:
+SolibSearchPathBlock.5=Select directory that contains shared library.
+SolibSearchPathBlock.6=Select From List
+SolibSearchPathBlock.7=Select Libraries
+SolibSearchPathBlock.8=Select libraries to load symbols automatically.
+SolibSearchPathBlock.9=No libraries found.
+SolibSearchPathBlock.Add_Directory=Add Directory
+TCPSettingsBlock.0=Host name or IP address:
+TCPSettingsBlock.1=Port number:
+TCPSettingsBlock.2=Host name or IP address must be specified.
+TCPSettingsBlock.3=Invalid host name or IP address.
+TCPSettingsBlock.4=Port number must be specified.
+TCPSettingsBlock.5=Invalid port number.
+
+AbstractCLaunchDelegate.Debugger_not_installed=CDT Debugger not installed
+AbstractCLaunchDelegate.C_Project_not_specified=C Project not specified
+AbstractCLaunchDelegate.Not_a_C_CPP_project=Project is not a C/C++ project
+AbstractCLaunchDelegate.Program_file_not_specified=Program file not specified
+AbstractCLaunchDelegate.Program_file_does_not_exist=Program file does not exist
+AbstractCLaunchDelegate.PROGRAM_PATH_not_found={0} not found
+AbstractCLaunchDelegate.Working_directory_does_not_exist=Working directory does not exist
+AbstractCLaunchDelegate.WORKINGDIRECTORY_PATH_not_found=The working directory {0} does not exist.
+AbstractCLaunchDelegate.Project_NAME_does_not_exist=Project {0} does not exist. Please check that your launch configuration specifies a valid project in your workspace.
+AbstractCLaunchDelegate.Project_NAME_is_closed=Project {0} is closed
+AbstractCLaunchDelegate.Debugger_Process=Debugger Process
+AbstractCLaunchDelegate.building_projects=Building prerequisite project list
+AbstractCLaunchDelegate.building=Building
+AbstractCLaunchDelegate.searching_for_errors=Searching for compile errors
+AbstractCLaunchDelegate.searching_for_errors_in=Searching for compile errors in
+AbstractCLaunchDelegate.20=Building prerequisite project list
+AbstractCLaunchDelegate.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
+
+LocalRunLaunchDelegate.Launching_Local_C_Application=Launching Local C/C++ Application
+LocalRunLaunchDelegate.Failed_setting_runtime_option_though_debugger=Failed to set program arguments, environment or working directory.
+LocalRunLaunchDelegate.Error_starting_process=Error starting process
+LocalRunLaunchDelegate.Does_not_support_working_dir=Eclipse runtime does not support working directory
+
+LocalAttachLaunchDelegate.Attaching_to_Local_C_Application=Attaching to Local C/C++ Application
+LocalAttachLaunchDelegate.No_Process_ID_selected=No Process ID selected
+LocalAttachLaunchDelegate.Select_Process=Select Process
+LocalAttachLaunchDelegate.Platform_cannot_list_processes=Current platform does not support listing processes
+LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to=Select a Process to attach debugger to:
+LocalAttachLaunchDelegate.CDT_Launch_Error=CDT Launch Error
+
+CoreFileLaunchDelegate.Launching_postmortem_debugger=Launching postmortem debugger
+CoreFileLaunchDelegate.No_Corefile_selected=No Corefile selected
+CoreFileLaunchDelegate.No_Shell_available_in_Launch=No Shell available in Launch
+CoreFileLaunchDelegate.Select_Corefile=Select Corefile
+CoreFileLaunchDelegate.Corefile_not_accessible=Core file is not accessible.
+CoreFileLaunchDelegate.Corefile_not_readable=Core file does not exist or is not readable.
+CoreFileLaunchDelegate.postmortem_debugging_failed=Post-mortem debugging failed
+
+CApplicationLaunchShortcut.Application_Launcher=Application Launcher
+CApplicationLaunchShortcut.ChooseConfigToDebug=Choose a debug configuration to debug
+CApplicationLaunchShortcut.ChooseConfigToRun=Choose a configuration to run
+CApplicationLaunchShortcut.CLocalApplication=C Local Application
+CApplicationLaunchShortcut.ChooseLocalAppToDebug=Choose a local application to debug
+CApplicationLaunchShortcut.ChooseLocalAppToRun=Choose a local application to run
+CApplicationLaunchShortcut.Launch_failed_no_binaries=Launch failed. Binary not found.
+CApplicationLaunchShortcut.LaunchFailed=Launch failed
+CApplicationLaunchShortcut.LaunchDebugConfigSelection=Launch Debug Configuration Selection
+CApplicationLaunchShortcut.LaunchConfigSelection=Launch Configuration Selection
+CApplicationLaunchShortcut.Invalid_launch_mode_1=Invalid launch mode
+CApplicationLaunchShortcut.Invalid_launch_mode_2=Invalid launch mode.
+CApplicationLaunchShortcut.Invalid_launch_mode_3=Invalid launch mode.
+CApplicationLaunchShortcut.ChooseLaunchConfigToDebug=Choose a launch configuration to debug
+CApplicationLaunchShortcut.ChooseLaunchConfigToRun=Choose a launch configuration to run
+CApplicationLaunchShortcut.Launch_failed_no_project_selected=Launch failed no project selected
+
+AbstractCDebuggerTab.No_debugger_available=No debugger available
+AbstractCDebuggerTab.Debugger=Debugger
+AbstractCDebuggerTab.ErrorLoadingDebuggerPage=Error Loading Debugger UI Component.
+
+LaunchUIPlugin.Error=Error
+
+CMainTab.Project_required=Project required
+CMainTab.Enter_project_before_searching_for_program=Project must first be entered before searching for a program
+CMainTab.Program_Selection=Program Selection
+CMainTab.Enter_project_before_browsing_for_program=Project must first be entered before browsing for a program
+CMainTab.Program_selection=Program selection
+CMainTab.Selection_must_be_file=Selection must be a file
+CMainTab.Selection_must_be_binary_file=Selection must be a binary file
+CMainTab.Project_Selection=Project Selection
+CMainTab.Choose_project_to_constrain_search_for_program=Choose a &project to constrain the search for a program
+CMainTab.Project_not_specified=Project not specified
+CMainTab.Program_not_specified=Program not specified
+CMainTab.Project_must_be_opened=Project must be opened
+CMainTab.Program_does_not_exist=Program does not exist
+CMainTab.Main=Main
+CMainTab.&ProjectColon=&Project:
+CMainTab.C/C++_Application=C/C++ Application:
+CMainTab.Search...=Searc&h Project...
+CMainTab.Choose_program_to_run=Choose a &program to run:
+CMainTab.Choose_program_to_run_from_NAME=Choose a program to run from {0}:
+CMainTab.UseTerminal=Connect process input & output to a terminal.
+CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
+
+CDebuggerTab.Advanced_Options_Dialog_Title=Advanced Options
+CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:
+CDebuggerTab.Automatically_track_values_of=Automatically track the values of
+CDebuggerTab.Stop_on_startup_at_can_not_be_empty=The "Stop on startup at" field can not be empty.
+CDebuggerTab.Debugger_Options=Debugger Options
+CDebuggerTab.Mode_not_supported=Mode ''{0}'' is not supported by the selected debugger
+CDebuggerTab.Advanced=Advanced...
+CDebuggerTab.Variables=Variables
+CDebuggerTab.Registers=Registers
+CDebuggerTab.No_debugger_available=No debugger available
+CDebuggerTab.CPU_is_not_supported=The CPU is not supported by the selected debugger.
+CDebuggerTab.Platform_is_not_supported=The project platform is not supported by the selected debugger.
+
+CoreFileDebuggerTab.No_debugger_available=No debugger available
+CoreFileDebuggerTab.platform_is_not_supported=The project platform is not supported by the selected debugger.
+
+CEnvironmentTab.Edit_Variable=Edit Variable
+CEnvironmentTab.New_Variable=New Variable
+CEnvironmentTab.NameColon=Name:
+CEnvironmentTab.ValueColon=Value:
+CEnvironmentTab.Name=Name
+CEnvironmentTab.Value=Value
+CEnvironmentTab.New...=New...
+CEnvironmentTab.Import...=Import...
+CEnvironmentTab.Edit...=Edit...
+CEnvironmentTab.Remove=Remove
+CEnvironmentTab.Environment=Environment
+CEnvironmentTab.Existing_Environment_Variable=Existing Environment Variable
+CEnvironmentTab.Environment_variable_NAME_exists=Environment variable \" {0} \" exists.\nDo you want to overwrite?
+
+CArgumentsTab.C/C++_Program_Arguments=Program arguments:
+CArgumentsTab.Arguments=Arguments
+CArgumentsTab.Variables=Variables...
+
+WorkingDirectoryBlock.4=Select a &workspace relative working directory:
+WorkingDirectoryBlock.7=Select a working directory for the launch configuration:
+WorkingDirectoryBlock.0=W&orkspace...
+WorkingDirectoryBlock.Working_Directory_8=Working Directory
+WorkingDirectoryBlock.Working_directory=Working directory:
+WorkingDirectoryBlock.10=Working directory does not exist
+WorkingDirectoryBlock.Use_default=Use de&fault
+WorkingDirectoryBlock.17=Variabl&es...
+WorkingDirectoryBlock.1=File S&ystem...
+WorkingDirectoryBlock.Exception_occurred_reading_configuration___15=Exception occurred reading configuration:
+
+Launch.common.Exception_occurred_reading_configuration_EXCEPTION=Exception occurred reading configuration {0}
+Launch.common.DebuggerColon=Debugger:
+Launch.common.BinariesColon=Binaries:
+Launch.common.QualifierColon=Qualifier:
+Launch.common.Browse_1=&Browse...
+Launch.common.Browse_2=B&rowse...
+Launch.common.Project_does_not_exist=Project does not exist
+LocalCDILaunchDelegate.0=Launching Local C/C++ Application
+LocalCDILaunchDelegate.1=Launching debugger session
+LocalCDILaunchDelegate.2=Debugging local C/C++ application
+LocalCDILaunchDelegate.3=Attaching to Local C/C++ Application
+LocalCDILaunchDelegate.4=No Process ID selected.
+LocalCDILaunchDelegate.5=Launching postmortem debugger session
+LocalCDILaunchDelegate.6=No core file selected
+LocalCDILaunchDelegate.7=Core file does not exist or is not readable.
+LocalCDILaunchDelegate.8=Error starting process.
+LocalCDILaunchDelegate.9=Eclipse runtime does not support working directory.
+LocalCDILaunchDelegate.10=Failed to set program arguments, environment or working directory.
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java
new file mode 100644
index 00000000000..7223ac28520
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import org.eclipse.cdt.core.IProcessInfo;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
+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.debug.core.IStatusHandler;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.TwoPaneElementSelector;
+
+public class ProcessPrompter implements IStatusHandler {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.core.IStatusHandler#handleStatus(org.eclipse.core.runtime.IStatus,
+ * java.lang.Object)
+ */
+ public Object handleStatus(IStatus status, Object processList) throws CoreException {
+ Shell shell = GdbUIPlugin.getShell();
+ if (shell == null) {
+ IStatus error = new Status(IStatus.ERROR, GdbUIPlugin.getUniqueIdentifier(),
+ ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR,
+ LaunchMessages.getString("CoreFileLaunchDelegate.No_Shell_available_in_Launch"), null); //$NON-NLS-1$
+ throw new CoreException(error);
+ }
+
+ IProcessInfo[] plist = (IProcessInfo[])processList;
+ if (plist == null) {
+ MessageDialog.openError(
+ shell,
+ LaunchMessages.getString("LocalAttachLaunchDelegate.CDT_Launch_Error"), LaunchMessages.getString("LocalAttachLaunchDelegate.Platform_cannot_list_processes")); //$NON-NLS-1$ //$NON-NLS-2$
+ return null;
+ }
+
+ if (plist.length == 0) {
+ // No list available, just let the user put in a pid directly
+ InputDialog dialog = new InputDialog(shell,
+ LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process"), //$NON-NLS-1$
+ LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to"), //$NON-NLS-1$
+ null, null);
+
+ if (dialog.open() == Window.OK) {
+ String pidStr = dialog.getValue();
+ try {
+ return Integer.parseInt(pidStr);
+ } catch (NumberFormatException e) {
+ }
+ }
+ } else {
+ ILabelProvider provider = new LabelProvider() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ @Override
+ public String getText(Object element) {
+ IProcessInfo info = (IProcessInfo)element;
+ IPath path = new Path(info.getName());
+ return path.lastSegment() + " - " + info.getPid(); //$NON-NLS-1$
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+ */
+ @Override
+ public Image getImage(Object element) {
+ return LaunchImages.get(LaunchImages.IMG_OBJS_EXEC);
+ }
+ };
+ ILabelProvider qprovider = new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ IProcessInfo info = (IProcessInfo)element;
+ return info.getName();
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+ */
+ @Override
+ public Image getImage(Object element) {
+ return LaunchImages.get(LaunchImages.IMG_OBJS_EXEC);
+ }
+ };
+
+ // Display the list of processes and have the user choose
+ TwoPaneElementSelector dialog = new TwoPaneElementSelector(shell, provider, qprovider);
+ dialog.setTitle(LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process")); //$NON-NLS-1$
+ dialog.setMessage(LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to")); //$NON-NLS-1$
+
+ dialog.setElements(plist);
+ if (dialog.open() == Window.OK) {
+ IProcessInfo info = (IProcessInfo)dialog.getFirstResult();
+ if (info != null) {
+ return new Integer(info.getPid());
+ }
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SerialPortSettingsBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SerialPortSettingsBlock.java
new file mode 100644
index 00000000000..4f537d12a5d
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SerialPortSettingsBlock.java
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.util.Observable;
+
+import org.eclipse.cdt.debug.internal.ui.PixelConverter;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.ComboDialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.DialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.IDialogFieldListener;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.LayoutUtil;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.StringDialogField;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+public class SerialPortSettingsBlock extends Observable {
+
+ private final static String DEFAULT_ASYNC_DEVICE = "/dev/ttyS0"; //$NON-NLS-1$
+
+ private final static String DEFAULT_ASYNC_DEVICE_SPEED = "115200"; //$NON-NLS-1$
+
+ private Shell fShell;
+
+ private StringDialogField fDeviceField;
+
+ private ComboDialogField fSpeedField;
+
+ private String fSpeedChoices[] = { "9600", "19200", "38400", "57600", "115200" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
+ private Control fControl;
+
+ private String fErrorMessage = null;
+
+ public SerialPortSettingsBlock() {
+ super();
+ fDeviceField = createDeviceField();
+ fSpeedField = createSpeedField();
+ }
+
+ public void createBlock(Composite parent) {
+ fShell = parent.getShell();
+ Composite comp = ControlFactory.createCompositeEx(parent, 2, GridData.FILL_BOTH);
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ ((GridLayout)comp.getLayout()).marginHeight = 0;
+ ((GridLayout)comp.getLayout()).marginWidth = 0;
+ comp.setFont(parent.getFont());
+ PixelConverter converter = new PixelConverter(comp);
+ fDeviceField.doFillIntoGrid(comp, 2);
+ LayoutUtil.setWidthHint(fDeviceField.getTextControl(null), converter.convertWidthInCharsToPixels(20));
+ fSpeedField.doFillIntoGrid(comp, 2);
+ ((GridData)fSpeedField.getComboControl(null).getLayoutData()).horizontalAlignment = GridData.BEGINNING;
+ setControl(comp);
+ }
+
+ protected Shell getShell() {
+ return fShell;
+ }
+
+ public void dispose() {
+ deleteObservers();
+ }
+
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ initializeDevice(configuration);
+ initializeSpeed(configuration);
+ }
+
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV, DEFAULT_ASYNC_DEVICE);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV_SPEED, DEFAULT_ASYNC_DEVICE_SPEED);
+ }
+
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ if (fDeviceField != null)
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV, fDeviceField.getText().trim());
+ if (fSpeedField != null) {
+ int index = fSpeedField.getSelectionIndex();
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV_SPEED, getSpeedItem(index));
+ }
+ }
+
+ private StringDialogField createDeviceField() {
+ StringDialogField field = new StringDialogField();
+ field.setLabelText(LaunchUIMessages.getString("SerialPortSettingsBlock.0")); //$NON-NLS-1$
+ field.setDialogFieldListener(new IDialogFieldListener() {
+
+ public void dialogFieldChanged(DialogField f) {
+ deviceFieldChanged();
+ }
+ });
+ return field;
+ }
+
+ private ComboDialogField createSpeedField() {
+ ComboDialogField field = new ComboDialogField(SWT.DROP_DOWN | SWT.READ_ONLY);
+ field.setLabelText(LaunchUIMessages.getString("SerialPortSettingsBlock.1")); //$NON-NLS-1$
+ field.setItems(fSpeedChoices);
+ field.setDialogFieldListener(new IDialogFieldListener() {
+
+ public void dialogFieldChanged(DialogField f) {
+ speedFieldChanged();
+ }
+ });
+ return field;
+ }
+
+ protected void deviceFieldChanged() {
+ updateErrorMessage();
+ setChanged();
+ notifyObservers();
+ }
+
+ protected void speedFieldChanged() {
+ updateErrorMessage();
+ setChanged();
+ notifyObservers();
+ }
+
+ private void initializeDevice(ILaunchConfiguration configuration) {
+ if (fDeviceField != null) {
+ try {
+ fDeviceField.setText(configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV, DEFAULT_ASYNC_DEVICE));
+ }
+ catch(CoreException e) {
+ }
+ }
+ }
+
+ private void initializeSpeed(ILaunchConfiguration configuration) {
+ if (fSpeedField != null) {
+ int index = 0;
+ try {
+ index = getSpeedItemIndex(configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEV_SPEED, DEFAULT_ASYNC_DEVICE_SPEED));
+ }
+ catch(CoreException e) {
+ }
+ fSpeedField.selectItem(index);
+ }
+ }
+
+ private String getSpeedItem(int index) {
+ return (index >= 0 && index < fSpeedChoices.length) ? fSpeedChoices[index] : null;
+ }
+
+ private int getSpeedItemIndex(String item) {
+ for(int i = 0; i < fSpeedChoices.length; ++i)
+ if (fSpeedChoices[i].equals(item))
+ return i;
+ return 0;
+ }
+
+ public Control getControl() {
+ return fControl;
+ }
+
+ protected void setControl(Control control) {
+ fControl = control;
+ }
+
+ public boolean isValid(ILaunchConfiguration configuration) {
+ updateErrorMessage();
+ return (getErrorMessage() == null);
+ }
+
+ private void updateErrorMessage() {
+ setErrorMessage(null);
+ if (fDeviceField != null && fSpeedField != null) {
+ if (fDeviceField.getText().trim().length() == 0)
+ setErrorMessage(LaunchUIMessages.getString("SerialPortSettingsBlock.2")); //$NON-NLS-1$
+ else if (!deviceIsValid(fDeviceField.getText().trim()))
+ setErrorMessage(LaunchUIMessages.getString("SerialPortSettingsBlock.3")); //$NON-NLS-1$
+ else if (fSpeedField.getSelectionIndex() < 0)
+ setErrorMessage(LaunchUIMessages.getString("SerialPortSettingsBlock.4")); //$NON-NLS-1$
+ }
+ }
+
+ public String getErrorMessage() {
+ return fErrorMessage;
+ }
+
+ private void setErrorMessage(String string) {
+ fErrorMessage = string;
+ }
+
+ private boolean deviceIsValid(String hostName) {
+ return true;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SolibSearchPathBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SolibSearchPathBlock.java
new file mode 100644
index 00000000000..6faa7b7dfc2
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/SolibSearchPathBlock.java
@@ -0,0 +1,620 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * IBM Corporation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Observable;
+import java.util.Set;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.ICExtensionReference;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryShared;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.debug.internal.ui.PixelConverter;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.DialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.IDialogFieldListener;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.IListAdapter;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.LayoutUtil;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.ListDialogField;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog;
+
+/**
+ * The UI component to access the shared libraries search path.
+ */
+public class SolibSearchPathBlock extends Observable implements IMILaunchConfigurationComponent, IDialogFieldListener {
+
+ class AddDirectoryDialog extends Dialog {
+
+ protected Text fText;
+
+ private Button fBrowseButton;
+
+ private IPath fValue;
+
+ /**
+ * Constructor for AddDirectoryDialog.
+ */
+ public AddDirectoryDialog(Shell parentShell) {
+ super(parentShell);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite)super.createDialogArea(parent);
+
+ Composite subComp = ControlFactory.createCompositeEx(composite, 2, GridData.FILL_HORIZONTAL);
+ ((GridLayout)subComp.getLayout()).makeColumnsEqualWidth = false;
+ GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
+ data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
+ subComp.setLayoutData(data);
+ subComp.setFont(parent.getFont());
+
+ fText = new Text(subComp, SWT.SINGLE | SWT.BORDER);
+ fText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
+ fText.addModifyListener(new ModifyListener() {
+
+ public void modifyText(ModifyEvent e) {
+ updateOKButton();
+ }
+ });
+
+ fBrowseButton = ControlFactory.createPushButton(subComp, LaunchUIMessages.getString("GDBServerDebuggerPage.7")); //$NON-NLS-1$
+ data = new GridData();
+ data.horizontalAlignment = GridData.FILL;
+ fBrowseButton.setLayoutData(data);
+ fBrowseButton.addSelectionListener(new SelectionAdapter() {
+
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ DirectoryDialog dialog = new DirectoryDialog(AddDirectoryDialog.this.getShell());
+ dialog.setMessage(LaunchUIMessages.getString("SolibSearchPathBlock.5")); //$NON-NLS-1$
+ String res = dialog.open();
+ if (res != null) {
+ fText.setText(res);
+ }
+ }
+ });
+
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(LaunchUIMessages.getString("SolibSearchPathBlock.Add_Directory")); //$NON-NLS-1$
+ }
+
+ public IPath getValue() {
+ return fValue;
+ }
+
+ private void setValue(String value) {
+ fValue = (value != null) ? new Path(value) : null;
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.OK_ID) {
+ setValue(fText.getText());
+ }
+ else {
+ setValue(null);
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ protected void updateOKButton() {
+ Button okButton = getButton(IDialogConstants.OK_ID);
+ String text = fText.getText();
+ okButton.setEnabled(isValid(text));
+ }
+
+ protected boolean isValid(String text) {
+ return (text.trim().length() > 0);
+ }
+
+ @Override
+ protected Control createButtonBar(Composite parent) {
+ Control control = super.createButtonBar(parent);
+ updateOKButton();
+ return control;
+ }
+ }
+
+ private Composite fControl;
+
+ public class SolibSearchPathListDialogField extends ListDialogField {
+
+ public SolibSearchPathListDialogField(IListAdapter adapter, String[] buttonLabels, ILabelProvider lprovider) {
+ super(adapter, buttonLabels, lprovider);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.internal.ui.dialogfields.ListDialogField#managedButtonPressed(int)
+ */
+ @Override
+ protected boolean managedButtonPressed(int index) {
+ boolean result = super.managedButtonPressed(index);
+ if (result)
+ buttonPressed(index);
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.dialogfields.ListDialogField#getManagedButtonState(org.eclipse.jface.viewers.ISelection, int)
+ */
+ @Override
+ protected boolean getManagedButtonState(ISelection sel, int index) {
+ if (index > 3)
+ return getButtonState(sel, index);
+ return super.getManagedButtonState(sel, index);
+ }
+ }
+
+ private static String[] fgStaticButtonLabels = new String[] {
+ LaunchUIMessages.getString("SolibSearchPathBlock.0"), //$NON-NLS-1$
+ LaunchUIMessages.getString("SolibSearchPathBlock.1"), //$NON-NLS-1$
+ LaunchUIMessages.getString("SolibSearchPathBlock.2"), //$NON-NLS-1$
+ LaunchUIMessages.getString("SolibSearchPathBlock.3"), //$NON-NLS-1$
+ LaunchUIMessages.getString("SolibSearchPathBlock.6"), //$NON-NLS-1$
+ null, // separator
+ };
+
+ private IProject fProject;
+
+ private Shell fShell;
+
+ private SolibSearchPathListDialogField fDirList;
+
+ private IListAdapter fCustomListAdapter;
+
+ private File[] fAutoSolibs = new File[0];
+
+ public SolibSearchPathBlock() {
+ this(new String[0], null);
+ }
+
+ public SolibSearchPathBlock(String[] customButtonLabels, IListAdapter customListAdapter) {
+ super();
+ fCustomListAdapter = customListAdapter;
+ int length = fgStaticButtonLabels.length;
+ if (customButtonLabels.length > 0)
+ length += customButtonLabels.length;
+ String[] buttonLabels = new String[length];
+ System.arraycopy(fgStaticButtonLabels, 0, buttonLabels, 0, fgStaticButtonLabels.length);
+ if (length > fgStaticButtonLabels.length) {
+ for (int i = fgStaticButtonLabels.length; i < length; ++i)
+ buttonLabels[i] = customButtonLabels[i - fgStaticButtonLabels.length];
+ }
+ IListAdapter listAdapter = new IListAdapter() {
+ public void customButtonPressed(DialogField field, int index) {
+ buttonPressed(index);
+ }
+ public void selectionChanged(DialogField field) {
+ }
+ };
+ ILabelProvider lp = new LabelProvider() {
+ @Override
+ public String getText(Object element) {
+ if (element instanceof IPath)
+ return ((IPath)element).toOSString();
+ return super.getText(element);
+ }
+ };
+ fDirList = new SolibSearchPathListDialogField(listAdapter, buttonLabels, lp);
+ fDirList.setLabelText(LaunchUIMessages.getString("SolibSearchPathBlock.4")); //$NON-NLS-1$
+ fDirList.setUpButtonIndex(1);
+ fDirList.setDownButtonIndex(2);
+ fDirList.setRemoveButtonIndex(3);
+
+ fDirList.setDialogFieldListener(this);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ fShell = parent.getShell();
+ Composite comp = ControlFactory.createCompositeEx(parent, 2, GridData.FILL_BOTH);
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ ((GridLayout)comp.getLayout()).marginHeight = 0;
+ ((GridLayout)comp.getLayout()).marginWidth = 0;
+ comp.setFont(parent.getFont());
+ PixelConverter converter = new PixelConverter(comp);
+ fDirList.doFillIntoGrid(comp, 3);
+ LayoutUtil.setHorizontalSpan(fDirList.getLabelControl(null), 2);
+ LayoutUtil.setWidthHint(fDirList.getLabelControl(null), converter.convertWidthInCharsToPixels(30));
+ LayoutUtil.setHorizontalGrabbing(fDirList.getListControl(null));
+ fControl = comp;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ IProject project = null;
+ try {
+ String projectName = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
+ if (projectName != null) {
+ projectName = projectName.trim();
+ if (projectName.length() > 0) {
+ project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ }
+ }
+ }
+ catch(CoreException e) {
+ }
+ setProject(project);
+
+ if (fDirList != null) {
+ try {
+ @SuppressWarnings("unchecked")
+ List values = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
+ Collections.EMPTY_LIST);
+ ArrayList paths = new ArrayList(values.size());
+ Iterator it = values.iterator();
+ while(it.hasNext()) {
+ paths.add(new Path(it.next()));
+ }
+ fDirList.addElements(paths);
+ }
+ catch(CoreException e) {
+ }
+ }
+
+ try {
+ fAutoSolibs = getAutoSolibs(configuration);
+ }
+ catch(CoreException e) {
+ }
+ }
+
+ public static File[] getAutoSolibs(ILaunchConfiguration configuration) throws CoreException {
+ @SuppressWarnings("unchecked")
+ List autoSolibs = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB_LIST, Collections.EMPTY_LIST );
+
+ List list = new ArrayList(autoSolibs.size());
+ Iterator it = autoSolibs.iterator();
+ while(it.hasNext()) {
+ list.add(new File(it.next()));
+ }
+ return list.toArray(new File[list.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH, Collections.EMPTY_LIST);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ if (fDirList != null) {
+
+ @SuppressWarnings("unchecked")
+ List elements = fDirList.getElements();
+
+ ArrayList values = new ArrayList(elements.size());
+ Iterator it = elements.iterator();
+ while(it.hasNext()) {
+ values.add((it.next()).toOSString());
+ }
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH, values);
+ }
+ ArrayList autoLibs = new ArrayList(fAutoSolibs.length);
+ for (int i = 0; i < fAutoSolibs.length; ++i)
+ autoLibs.add(fAutoSolibs[i].getPath());
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB_LIST, autoLibs);
+ }
+
+ protected void buttonPressed(int index) {
+ boolean changed = false;
+ if (index == 0) { // Add button
+ changed = addDirectory();
+ }
+ else if (index == 4) { //Select from list
+ changed = selectFromList();
+ }
+ else if (index >= fgStaticButtonLabels.length && fCustomListAdapter != null) {
+ fCustomListAdapter.customButtonPressed(fDirList, index);
+ changed = true;
+ }
+ if (changed) {
+ setChanged();
+ notifyObservers();
+ }
+ }
+
+ protected boolean getButtonState(ISelection sel, int index) {
+ if (index == 4) { // select from list
+ return (!sel.isEmpty());
+ }
+ return true;
+ }
+
+ protected Shell getShell() {
+ return fShell;
+ }
+
+ private boolean addDirectory() {
+ boolean changed = false;
+ AddDirectoryDialog dialog = new AddDirectoryDialog(getShell());
+ dialog.open();
+ IPath result = dialog.getValue();
+ if (result != null && !contains(result)) {
+ fDirList.addElement(result);
+ changed = true;
+ }
+ return changed;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#dispose()
+ */
+ public void dispose() {
+ deleteObservers();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#getControl()
+ */
+ public Control getControl() {
+ return fControl;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.mi.internal.ui.IMILaunchConfigurationComponent#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private boolean contains(IPath path) {
+ @SuppressWarnings("unchecked")
+ List list = fDirList.getElements();
+
+ Iterator it = list.iterator();
+ while(it.hasNext()) {
+ IPath p = it.next();
+ if (p.toFile().equals(path.toFile()))
+ return true;
+ }
+ return false;
+ }
+
+ protected IProject getProject() {
+ return fProject;
+ }
+
+ private void setProject(IProject project) {
+ fProject = project;
+ }
+
+ protected boolean selectFromList() {
+ boolean changed = false;
+
+ @SuppressWarnings("unchecked")
+ List dirList = fDirList.getSelectedElements();
+
+ final HashSet libs = new HashSet(10);
+ if (generateLibraryList(dirList.toArray(new IPath[dirList.size()]), libs)) {
+ ITreeContentProvider cp = new ITreeContentProvider() {
+
+ public Object[] getChildren(Object parentElement) {
+ return getElements(parentElement);
+ }
+
+ public Object getParent(Object element) {
+ if (libs.contains(element))
+ return libs;
+ return null;
+ }
+
+ public boolean hasChildren(Object element) {
+ return false;
+ }
+
+ public Object[] getElements(Object inputElement) {
+ if (inputElement instanceof Set) {
+ return ((Set)inputElement).toArray();
+ }
+ return new Object[0];
+ }
+
+ public void dispose() {
+ }
+
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ }
+ };
+
+ LabelProvider lp = new LabelProvider() {
+
+ @Override
+ public String getText(Object element) {
+ if (element instanceof File)
+ return ((File)element).getName();
+ return super.getText(element);
+ }
+ };
+ CheckedTreeSelectionDialog dialog = new CheckedTreeSelectionDialog(getShell(), lp, cp);
+ dialog.setTitle(LaunchUIMessages.getString("SolibSearchPathBlock.7")); //$NON-NLS-1$
+ dialog.setMessage(LaunchUIMessages.getString("SolibSearchPathBlock.8")); //$NON-NLS-1$
+ dialog.setEmptyListMessage(LaunchUIMessages.getString("SolibSearchPathBlock.9")); //$NON-NLS-1$
+ dialog.setSorter(new ViewerSorter());
+ dialog.setInput(libs);
+ dialog.setInitialElementSelections(Arrays.asList(fAutoSolibs));
+ if (dialog.open() == Window.OK) {
+ Object[] result = dialog.getResult();
+ fAutoSolibs = (File[])Arrays.asList(result).toArray(new File[result.length]);
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ private boolean generateLibraryList(final IPath[] paths, final Set libs) {
+ boolean result = true;
+
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+
+ for (int i = 0; i < paths.length; ++i) {
+ File dir = paths[i].toFile();
+ if (dir.exists() && dir.isDirectory()) {
+ File[] all = dir.listFiles();
+ for (int j = 0; j < all.length; ++j) {
+ if (monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+ monitor.subTask(all[j].getPath());
+ String libName = getSharedLibraryName(all[j]);
+ if (libName != null) {
+ libs.add(new File(libName));
+ }
+ }
+ }
+ }
+ }
+ };
+ try {
+ IRunnableContext context = new ProgressMonitorDialog(getShell());
+ context.run(true, true, runnable);
+ }
+ catch(InvocationTargetException e) {
+ }
+ catch(InterruptedException e) {
+ result = false;
+ }
+ return result;
+ }
+
+ protected String getSharedLibraryName(File file) {
+ if (!file.isFile())
+ return null;
+ IProject project = getProject();
+ if (project != null) {
+ IPath fullPath = new Path(file.getPath());
+ try {
+ ICExtensionReference[] binaryParsersExt = CCorePlugin.getDefault().getBinaryParserExtensions(project);
+ for(int i = 0; i < binaryParsersExt.length; i++) {
+ IBinaryParser parser = (IBinaryParser)binaryParsersExt[i].createExtension();
+ try {
+ IBinaryFile bin = parser.getBinary(fullPath);
+ if (bin instanceof IBinaryShared) {
+ String soname = ((IBinaryShared)bin).getSoName();
+ return (soname.length() != 0) ? soname : file.getName();
+ }
+ }
+ catch(IOException e) {
+ }
+ }
+ }
+ catch(CoreException e) {
+ }
+ return null;
+ }
+ // no project: for now
+ IPath path = new Path(file.getPath());
+ String name = path.lastSegment();
+ String extension = path.getFileExtension();
+ if (extension != null && (extension.compareTo("so") == 0 || extension.compareToIgnoreCase("dll") == 0)) //$NON-NLS-1$ //$NON-NLS-2$
+ return name;
+ return (name.indexOf(".so.") >= 0) ? name : null; //$NON-NLS-1$
+ }
+
+ protected boolean isSharedLibrary(File file) {
+ if (!file.isFile())
+ return false;
+ IProject project = getProject();
+ if (project != null) {
+ IPath fullPath = new Path(file.getPath());
+ try {
+ ICExtensionReference[] binaryParsersExt = CCorePlugin.getDefault().getBinaryParserExtensions(project);
+ for(int i = 0; i < binaryParsersExt.length; i++) {
+ IBinaryParser parser = (IBinaryParser)binaryParsersExt[i].createExtension();
+ try {
+ IBinaryFile bin = parser.getBinary(fullPath);
+ return (bin instanceof IBinaryShared);
+ }
+ catch(IOException e) {
+ }
+ }
+ }
+ catch(CoreException e) {
+ }
+ return false;
+ }
+ // no project: for now
+ IPath path = new Path(file.getPath());
+ String extension = path.getFileExtension();
+ if (extension != null && (extension.compareTo("so") == 0 || extension.compareToIgnoreCase("dll") == 0)) //$NON-NLS-1$ //$NON-NLS-2$
+ return true;
+ String name = path.lastSegment();
+ return (name.indexOf(".so.") >= 0); //$NON-NLS-1$
+ }
+
+ public void dialogFieldChanged(DialogField field) {
+ setChanged();
+ notifyObservers();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/TCPSettingsBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/TCPSettingsBlock.java
new file mode 100644
index 00000000000..63271985042
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/TCPSettingsBlock.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.util.Observable;
+
+import org.eclipse.cdt.debug.internal.ui.PixelConverter;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.DialogField;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.IDialogFieldListener;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.LayoutUtil;
+import org.eclipse.cdt.debug.internal.ui.dialogfields.StringDialogField;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.utils.ui.controls.ControlFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+public class TCPSettingsBlock extends Observable {
+
+ private final static String DEFAULT_HOST_NAME = "localhost"; //$NON-NLS-1$
+
+ private final static String DEFAULT_PORT_NUMBER = "10000"; //$NON-NLS-1$
+
+ private Shell fShell;
+
+ private StringDialogField fHostNameField;
+
+ private StringDialogField fPortNumberField;
+
+ private Control fControl;
+
+ private String fErrorMessage = null;
+
+ public TCPSettingsBlock() {
+ super();
+ fHostNameField = createHostNameField();
+ fPortNumberField = createPortNumberField();
+ }
+
+ public void createBlock(Composite parent) {
+ fShell = parent.getShell();
+ Composite comp = ControlFactory.createCompositeEx(parent, 2, GridData.FILL_BOTH);
+ ((GridLayout)comp.getLayout()).makeColumnsEqualWidth = false;
+ ((GridLayout)comp.getLayout()).marginHeight = 0;
+ ((GridLayout)comp.getLayout()).marginWidth = 0;
+ comp.setFont(parent.getFont());
+ PixelConverter converter = new PixelConverter(comp);
+ fHostNameField.doFillIntoGrid(comp, 2);
+ LayoutUtil.setWidthHint(fHostNameField.getTextControl(null), converter.convertWidthInCharsToPixels(20));
+ fPortNumberField.doFillIntoGrid(comp, 2);
+ ((GridData)fPortNumberField.getTextControl(null).getLayoutData()).horizontalAlignment = GridData.BEGINNING;
+ LayoutUtil.setWidthHint(fPortNumberField.getTextControl(null), converter.convertWidthInCharsToPixels(10));
+ setControl(comp);
+ }
+
+ protected Shell getShell() {
+ return fShell;
+ }
+
+ public void dispose() {
+ deleteObservers();
+ }
+
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ initializeHostName(configuration);
+ initializePortNumber(configuration);
+ }
+
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, DEFAULT_HOST_NAME);
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, DEFAULT_PORT_NUMBER);
+ }
+
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ if (fHostNameField != null)
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, fHostNameField.getText().trim());
+ if (fPortNumberField != null)
+ configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, fPortNumberField.getText().trim());
+ }
+
+ private StringDialogField createHostNameField() {
+ StringDialogField field = new StringDialogField();
+ field.setLabelText(LaunchUIMessages.getString("TCPSettingsBlock.0")); //$NON-NLS-1$
+ field.setDialogFieldListener(new IDialogFieldListener() {
+
+ public void dialogFieldChanged(DialogField f) {
+ hostNameFieldChanged();
+ }
+ });
+ return field;
+ }
+
+ private StringDialogField createPortNumberField() {
+ StringDialogField field = new StringDialogField();
+ field.setLabelText(LaunchUIMessages.getString("TCPSettingsBlock.1")); //$NON-NLS-1$
+ field.setDialogFieldListener(new IDialogFieldListener() {
+
+ public void dialogFieldChanged(DialogField f) {
+ portNumberFieldChanged();
+ }
+ });
+ return field;
+ }
+
+ protected void hostNameFieldChanged() {
+ updateErrorMessage();
+ setChanged();
+ notifyObservers();
+ }
+
+ protected void portNumberFieldChanged() {
+ updateErrorMessage();
+ setChanged();
+ notifyObservers();
+ }
+
+ private void initializeHostName(ILaunchConfiguration configuration) {
+ if (fHostNameField != null) {
+ try {
+ fHostNameField.setText(configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_HOST, DEFAULT_HOST_NAME));
+ }
+ catch(CoreException e) {
+ }
+ }
+ }
+
+ private void initializePortNumber(ILaunchConfiguration configuration) {
+ if (fPortNumberField != null) {
+ try {
+ fPortNumberField.setText(configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_PORT, DEFAULT_PORT_NUMBER));
+ }
+ catch(CoreException e) {
+ }
+ }
+ }
+
+ public Control getControl() {
+ return fControl;
+ }
+
+ protected void setControl(Control control) {
+ fControl = control;
+ }
+
+ public boolean isValid(ILaunchConfiguration configuration) {
+ updateErrorMessage();
+ return (getErrorMessage() == null);
+ }
+
+ private void updateErrorMessage() {
+ setErrorMessage(null);
+ if (fHostNameField != null && fPortNumberField != null) {
+ if (fHostNameField.getText().trim().length() == 0)
+ setErrorMessage(LaunchUIMessages.getString("TCPSettingsBlock.2")); //$NON-NLS-1$
+ else if (!hostNameIsValid(fHostNameField.getText().trim()))
+ setErrorMessage(LaunchUIMessages.getString("TCPSettingsBlock.3")); //$NON-NLS-1$
+ else if (fPortNumberField.getText().trim().length() == 0)
+ setErrorMessage(LaunchUIMessages.getString("TCPSettingsBlock.4")); //$NON-NLS-1$
+ else if (!portNumberIsValid(fPortNumberField.getText().trim()))
+ setErrorMessage(LaunchUIMessages.getString("TCPSettingsBlock.5")); //$NON-NLS-1$
+ }
+ }
+
+ public String getErrorMessage() {
+ return fErrorMessage;
+ }
+
+ private void setErrorMessage(String string) {
+ fErrorMessage = string;
+ }
+
+ private boolean hostNameIsValid(String hostName) {
+ return true;
+ }
+
+ private boolean portNumberIsValid(String portNumber) {
+ try {
+ int port = Integer.parseInt(portNumber);
+ return (port > 0 && port <= 0xFFFF);
+ }
+ catch(NumberFormatException e) {
+ return false;
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/WorkingDirectoryBlock.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/WorkingDirectoryBlock.java
new file mode 100644
index 00000000000..36c70746f1b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/WorkingDirectoryBlock.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation 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:
+ * IBM Corporation - initial API and implementation
+ * Ericsson - Updated for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+
+import java.io.File;
+
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.variables.IStringVariableManager;
+import org.eclipse.core.variables.VariablesPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.StringVariableSelectionDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+
+/**
+ * A control for setting the working directory associated with a launch
+ * configuration.
+ */
+public class WorkingDirectoryBlock extends CLaunchConfigurationTab {
+
+ // Local directory
+ protected Text fWorkingDirText;
+ protected Button fWorkspaceButton;
+ protected Button fFileSystemButton;
+ protected Button fVariablesButton;
+
+ // use default button
+ protected Button fUseDefaultWorkingDirButton;
+
+ /**
+ * The last launch config this tab was initialized from
+ */
+ protected ILaunchConfiguration fLaunchConfiguration;
+
+ /**
+ * A listener to update for text changes and widget selection
+ */
+ private class WidgetListener extends SelectionAdapter implements ModifyListener {
+
+ public void modifyText(ModifyEvent e) {
+ updateLaunchConfigurationDialog();
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Object source = e.getSource();
+ if (source == fWorkspaceButton) {
+ handleWorkspaceDirBrowseButtonSelected();
+ } else if (source == fFileSystemButton) {
+ handleWorkingDirBrowseButtonSelected();
+ } else if (source == fUseDefaultWorkingDirButton) {
+ handleUseDefaultWorkingDirButtonSelected();
+ } else if (source == fVariablesButton) {
+ handleWorkingDirVariablesButtonSelected();
+ }
+ }
+ }
+
+ private WidgetListener fListener = new WidgetListener();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ public void createControl(Composite parent) {
+ Font font = parent.getFont();
+
+ Group group = new Group(parent, SWT.NONE);
+ // WorkbenchHelp.setHelp(group,
+ // IJavaDebugHelpContextIds.WORKING_DIRECTORY_BLOCK);
+ GridLayout workingDirLayout = new GridLayout();
+ workingDirLayout.makeColumnsEqualWidth = false;
+ group.setLayout(workingDirLayout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ group.setLayoutData(gd);
+ group.setFont(font);
+ setControl(group);
+
+ group.setText(LaunchUIMessages.getString("WorkingDirectoryBlock.Working_directory")); //$NON-NLS-1$
+
+ fWorkingDirText = new Text(group, SWT.SINGLE | SWT.BORDER);
+ fWorkingDirText.getAccessible().addAccessibleListener(
+ new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = LaunchUIMessages.getString("WorkingDirectoryBlock.Working_directory"); //$NON-NLS-1$
+ }
+ }
+ );
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ fWorkingDirText.setLayoutData(gd);
+ fWorkingDirText.setFont(font);
+ fWorkingDirText.addModifyListener(fListener);
+
+ fUseDefaultWorkingDirButton = new Button(group, SWT.CHECK);
+ fUseDefaultWorkingDirButton.setText(LaunchUIMessages.getString("WorkingDirectoryBlock.Use_default")); //$NON-NLS-1$
+ gd = new GridData(GridData.FILL, GridData.BEGINNING, true, false);
+ fUseDefaultWorkingDirButton.setLayoutData(gd);
+ fUseDefaultWorkingDirButton.setFont(font);
+ fUseDefaultWorkingDirButton.addSelectionListener(fListener);
+
+ Composite buttonComp = new Composite(group, SWT.NONE);
+ GridLayout layout = new GridLayout(3, false);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ buttonComp.setLayout(layout);
+ gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ buttonComp.setLayoutData(gd);
+ buttonComp.setFont(font);
+ fWorkspaceButton = createPushButton(buttonComp, LaunchUIMessages.getString("WorkingDirectoryBlock.0"), null); //$NON-NLS-1$
+ fWorkspaceButton.addSelectionListener(fListener);
+
+ fFileSystemButton = createPushButton(buttonComp, LaunchUIMessages.getString("WorkingDirectoryBlock.1"), null); //$NON-NLS-1$
+ fFileSystemButton.addSelectionListener(fListener);
+
+ fVariablesButton = createPushButton(buttonComp, LaunchUIMessages.getString("WorkingDirectoryBlock.17"), null); //$NON-NLS-1$
+ fVariablesButton.addSelectionListener(fListener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose()
+ */
+ @Override
+ public void dispose() {
+ }
+
+ /**
+ * Show a dialog that lets the user select a working directory
+ */
+ protected void handleWorkingDirBrowseButtonSelected() {
+ DirectoryDialog dialog = new DirectoryDialog(getShell());
+ dialog.setMessage(LaunchUIMessages.getString("WorkingDirectoryBlock.7")); //$NON-NLS-1$
+ String currentWorkingDir = fWorkingDirText.getText();
+ if (!currentWorkingDir.trim().equals("")) { //$NON-NLS-1$
+ File path = new File(currentWorkingDir);
+ if (path.exists()) {
+ dialog.setFilterPath(currentWorkingDir);
+ }
+ }
+
+ String selectedDirectory = dialog.open();
+ if (selectedDirectory != null) {
+ fWorkingDirText.setText(selectedDirectory);
+ }
+ }
+
+ /**
+ * Show a dialog that lets the user select a working directory from the
+ * workspace
+ */
+ protected void handleWorkspaceDirBrowseButtonSelected() {
+ ContainerSelectionDialog dialog = new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace().getRoot(), false,
+ LaunchUIMessages.getString("WorkingDirectoryBlock.4")); //$NON-NLS-1$
+
+ IContainer currentContainer = getContainer();
+ if (currentContainer != null) {
+ IPath path = currentContainer.getFullPath();
+ dialog.setInitialSelections(new Object[] { path});
+ }
+
+ dialog.showClosedProjects(false);
+ dialog.open();
+ Object[] results = dialog.getResult();
+ if ((results != null) && (results.length > 0) && (results[0] instanceof IPath)) {
+ IPath path = (IPath) results[0];
+ String containerName = path.makeRelative().toString();
+ fWorkingDirText.setText("${workspace_loc:" + containerName + "}"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ /**
+ * Returns the selected workspace container,or null
+ */
+ protected IContainer getContainer() {
+ String path = fWorkingDirText.getText().trim();
+ if (path.length() > 0) {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ IResource res = root.findMember(path);
+ if (res instanceof IContainer) {
+ return (IContainer) res;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * The default working dir check box has been toggled.
+ */
+ protected void handleUseDefaultWorkingDirButtonSelected() {
+ boolean def = isDefaultWorkingDirectory();
+ if (def) {
+ setDefaultWorkingDir();
+ }
+ fWorkingDirText.setEnabled(!def);
+ fWorkspaceButton.setEnabled(!def);
+ fVariablesButton.setEnabled(!def);
+ fFileSystemButton.setEnabled(!def);
+ }
+
+ protected void handleWorkingDirVariablesButtonSelected() {
+ String variableText = getVariable();
+ if (variableText != null) {
+ fWorkingDirText.append(variableText);
+ }
+ }
+
+ private String getVariable() {
+ StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell());
+ dialog.open();
+ return dialog.getVariableExpression();
+ }
+
+ /**
+ * Sets the default working directory
+ */
+ protected void setDefaultWorkingDir() {
+ try {
+ ILaunchConfiguration config = getLaunchConfiguration();
+ if (config != null) {
+ ICProject cProject = LaunchUtils.getCProject(config);
+ if (cProject != null) {
+ fWorkingDirText.setText("${workspace_loc:" + cProject.getPath().makeRelative().toOSString() + "}"); //$NON-NLS-1$ //$NON-NLS-2$
+ return;
+ }
+ }
+ } catch (CoreException ce) {
+ }
+ fWorkingDirText.setText(System.getProperty("user.dir")); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+
+ setErrorMessage(null);
+ setMessage(null);
+
+ // if variables are present, we cannot resolve the directory
+ String workingDirPath = fWorkingDirText.getText().trim();
+ if (workingDirPath.indexOf("${") >= 0) { //$NON-NLS-1$
+ IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
+ try {
+ manager.validateStringVariables(workingDirPath);
+ } catch (CoreException e) {
+ setErrorMessage(e.getMessage());
+ return false;
+ }
+ } else if (workingDirPath.length() > 0) {
+ IContainer container = getContainer();
+ if (container == null) {
+ File dir = new File(workingDirPath);
+ if (dir.isDirectory()) {
+ return true;
+ }
+ setErrorMessage(LaunchUIMessages.getString("WorkingDirectoryBlock.10")); //$NON-NLS-1$
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Defaults are empty.
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ // config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY,
+ // (String)null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ setLaunchConfiguration(configuration);
+ try {
+ String wd = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String) null);
+ fWorkingDirText.setText(""); //$NON-NLS-1$
+ if (wd == null) {
+ fUseDefaultWorkingDirButton.setSelection(true);
+ } else {
+ fWorkingDirText.setText(wd);
+ fUseDefaultWorkingDirButton.setSelection(false);
+ }
+ handleUseDefaultWorkingDirButtonSelected();
+ } catch (CoreException e) {
+ setErrorMessage(LaunchUIMessages.getString("WorkingDirectoryBlock.Exception_occurred_reading_configuration___15") + e.getStatus().getMessage()); //$NON-NLS-1$
+ GdbUIPlugin.log(e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ String wd = null;
+ if (!isDefaultWorkingDirectory()) {
+ wd = getAttributeValueFrom(fWorkingDirText);
+ }
+ configuration.setAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, wd);
+ }
+
+ /**
+ * Retuns the string in the text widget, or null
if empty.
+ *
+ * @return text or null
+ */
+ protected String getAttributeValueFrom(Text text) {
+ String content = text.getText().trim();
+ if (content.length() > 0) {
+ return content;
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ public String getName() {
+ return LaunchUIMessages.getString("WorkingDirectoryBlock.Working_Directory_8"); //$NON-NLS-1$
+ }
+
+ /**
+ * Returns whether the default working directory is to be used
+ */
+ protected boolean isDefaultWorkingDirectory() {
+ return fUseDefaultWorkingDirButton.getSelection();
+ }
+
+ /**
+ * Sets the c project currently specified by the given launch config, if
+ * any.
+ */
+ protected void setLaunchConfiguration(ILaunchConfiguration config) {
+ fLaunchConfiguration = config;
+ }
+
+ /**
+ * Returns the current c project context
+ */
+ protected ILaunchConfiguration getLaunchConfiguration() {
+ return fLaunchConfiguration;
+ }
+
+}
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java
new file mode 100644
index 00000000000..5c08a970518
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/GdbViewModelAdapter.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel;
+
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.AbstractDebugVMAdapter;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.ModulesVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMProvider;
+import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch.LaunchVMProvider;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugUIConstants;
+
+/*
+ *
+ */
+@ThreadSafe
+@SuppressWarnings("restriction")
+public class GdbViewModelAdapter extends AbstractDebugVMAdapter
+{
+ public GdbViewModelAdapter(DsfSession session, SteppingController controller) {
+ super(session, controller);
+ getSession().registerModelAdapter(IColumnPresentationFactory.class, this);
+ }
+
+ @Override
+ public void dispose() {
+ getSession().unregisterModelAdapter(IColumnPresentationFactory.class);
+ super.dispose();
+ }
+
+ @Override
+ protected AbstractDMVMProvider createViewModelProvider(IPresentationContext context) {
+ if ( IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId()) ) {
+ return new LaunchVMProvider(this, context, getSession());
+ } else if (IDebugUIConstants.ID_VARIABLE_VIEW.equals(context.getId()) ) {
+ return new VariableVMProvider(this, context, getSession());
+ } else if (IDebugUIConstants.ID_REGISTER_VIEW.equals(context.getId()) ) {
+ return new RegisterVMProvider(this, context, getSession());
+ } else if (IDebugUIConstants.ID_EXPRESSION_VIEW.equals(context.getId()) ) {
+ return new ExpressionVMProvider(this, context, getSession());
+ } else if (IDebugUIConstants.ID_MODULE_VIEW.equals(context.getId()) ) {
+ return new ModulesVMProvider(this, context, getSession());
+ }
+ return null;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java
new file mode 100644
index 00000000000..bff2b7d7dbd
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 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
+ * Wind River Systems - Factored out AbstractContainerVMNode
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch;
+
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractContainerVMNode;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.ui.IMemento;
+
+
+@SuppressWarnings("restriction")
+public class ContainerVMNode extends AbstractContainerVMNode
+ implements IElementMementoProvider
+{
+ public ContainerVMNode(AbstractDMVMProvider provider, DsfSession session) {
+ super(provider, session);
+ }
+
+ @Override
+ public String toString() {
+ return "ContainerVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ IProcesses processService = getServicesTracker().getService(IProcesses.class);
+ ICommandControlService controlService = getServicesTracker().getService(ICommandControlService.class);
+ if (processService == null || controlService == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ processService.getProcessesBeingDebugged(
+ controlService.getContext(),
+ new ViewerDataRequestMonitor(getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ if (getData() != null) fillUpdateWithVMCs(update, getData());
+ update.done();
+ }
+ });
+ }
+
+
+ @Override
+ protected void updateLabelInSessionThread(final ILabelUpdate update) {
+ IProcesses processService = getServicesTracker().getService(IProcesses.class);
+ IRunControl runControl = getServicesTracker().getService(IRunControl.class);
+ if (processService == null || runControl == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class);
+ final IContainerDMContext contDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IContainerDMContext.class);
+
+ String imageKey = null;
+ if (runControl.isSuspended(contDmc)) {
+ imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
+ } else {
+ imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
+ }
+ update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
+
+ processService.getExecutionData(
+ procDmc,
+ new ViewerDataRequestMonitor(getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ update.setLabel("", 0); //$NON-NLS-1$
+ update.done();
+ return;
+ }
+
+ // Create Labels of type Name[PID] if the pid is available
+ final StringBuilder builder = new StringBuilder();
+ builder.append(getData().getName());
+ if (getData().getId() != null && getData().getId().length() > 0) {
+ builder.append("[" + getData().getId()+ "]"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ update.setLabel(builder.toString(), 0);
+ update.done();
+ }
+ });
+ }
+
+ @Override
+ public int getDeltaFlags(Object e) {
+ if (e instanceof ICommandControlShutdownDMEvent) {
+ return IModelDelta.CONTENT;
+ }
+ return super.getDeltaFlags(e);
+ }
+
+ @Override
+ public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
+ if (e instanceof ICommandControlShutdownDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ } else {
+ super.buildDelta(e, parentDelta, nodeOffset, requestMonitor);
+ return;
+ }
+ requestMonitor.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ private final String MEMENTO_NAME = "CONTAINER_MEMENTO_NAME"; //$NON-NLS-1$
+
+ public void compareElements(IElementCompareRequest[] requests) {
+ for (final IElementCompareRequest request : requests) {
+
+ Object element = request.getElement();
+ final IMemento memento = request.getMemento();
+ final String mementoName = memento.getString(MEMENTO_NAME);
+
+ if (mementoName != null) {
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if (dmc instanceof IContainerDMContext)
+ {
+ final IProcessDMContext procDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IProcessDMContext.class);
+
+ if (procDmc != null) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IProcesses processService = getServicesTracker().getService(IProcesses.class);
+ if (processService != null) {
+ processService.getExecutionData(
+ procDmc,
+ new ViewerDataRequestMonitor(processService.getExecutor(), request) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ memento.putString(MEMENTO_NAME, "Container." + getData().getName() + getData().getId()); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ }
+ else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+
+ continue;
+ }
+ }
+ }
+ }
+ request.done();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
+ */
+ public void encodeElements(IElementMementoRequest[] requests) {
+ for (final IElementMementoRequest request : requests) {
+
+ Object element = request.getElement();
+ final IMemento memento = request.getMemento();
+
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if (dmc instanceof IContainerDMContext)
+ {
+ final IProcessDMContext procDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IProcessDMContext.class);
+
+ if (procDmc != null) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IProcesses processService = getServicesTracker().getService(IProcesses.class);
+ if (processService != null) {
+ processService.getExecutionData(
+ procDmc,
+ new ViewerDataRequestMonitor(processService.getExecutor(), request) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ memento.putString(MEMENTO_NAME, "Container." + getData().getName() + getData().getId()); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+
+ continue;
+ }
+ }
+ }
+ request.done();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMModelProxyStrategy.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMModelProxyStrategy.java
new file mode 100644
index 00000000000..d180558738b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMModelProxyStrategy.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.DefaultVMModelProxyStrategy;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ *
+ */
+public class LaunchVMModelProxyStrategy extends DefaultVMModelProxyStrategy {
+
+ final private TreePath fRootPath;
+
+ public LaunchVMModelProxyStrategy(AbstractVMProvider provider, Object rootElement) {
+ super(provider, rootElement);
+ fRootPath = new TreePath( new Object[] { rootElement });
+ }
+
+ @Override
+ public Object getViewerInput() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+
+ @Override
+ public TreePath getRootPath() {
+ return fRootPath;
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java
new file mode 100644
index 00000000000..b8282dd0206
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for new functionality
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlInitializedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractLaunchVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.LaunchRootVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StandardProcessVMNode;
+import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+public class LaunchVMProvider extends AbstractLaunchVMProvider
+ implements IDebugEventSetListener, ILaunchesListener2
+{
+ @ThreadSafe
+ public LaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
+ {
+ super(adapter, presentationContext, session);
+
+ IRootVMNode launchNode = new LaunchRootVMNode(this);
+ setRootNode(launchNode);
+
+ // Container node to contain all processes and threads
+ IVMNode containerNode = new ContainerVMNode(this, getSession());
+ IVMNode processesNode = new StandardProcessVMNode(this);
+ addChildNodes(launchNode, new IVMNode[] { containerNode, processesNode});
+
+ IVMNode threadsNode = new ThreadVMNode(this, getSession());
+ addChildNodes(containerNode, new IVMNode[] { threadsNode });
+
+ IVMNode stackFramesNode = new StackFramesVMNode(this, getSession());
+ addChildNodes(threadsNode, new IVMNode[] { stackFramesNode });
+
+
+ DebugPlugin.getDefault().addDebugEventListener(this);
+ DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
+ }
+
+ @Override
+ public void dispose() {
+ DebugPlugin.getDefault().removeDebugEventListener(this);
+ DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
+ super.dispose();
+ }
+
+ @Override
+ protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
+ // Never skip the process lifecycle events.
+ if (eventToSkip instanceof ICommandControlInitializedDMEvent ||
+ eventToSkip instanceof ICommandControlShutdownDMEvent)
+ {
+ return false;
+ }
+ return super.canSkipHandlingEvent(newEvent, eventToSkip);
+ }
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), getSession().getId());
+ IProcesses processesService = tracker.getService(IProcesses.class);
+ if (processesService instanceof ICachingService) {
+ ((ICachingService)processesService).flushCache(null);
+ }
+ IStack stackService = tracker.getService(IStack.class);
+ if (stackService instanceof ICachingService) {
+ ((ICachingService)stackService).flushCache(null);
+ }
+ IRunControl runControlService = tracker.getService(IRunControl.class);
+ if (runControlService instanceof ICachingService) {
+ ((ICachingService)runControlService).flushCache(null);
+ }
+ tracker.dispose();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore.
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java
new file mode 100644
index 00000000000..1942e2e8a63
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for multi threaded functionality
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch;
+
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractThreadVMNode;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.ui.IMemento;
+
+
+@SuppressWarnings("restriction")
+public class ThreadVMNode extends AbstractThreadVMNode
+ implements IElementLabelProvider, IElementMementoProvider
+{
+ public ThreadVMNode(AbstractDMVMProvider provider, DsfSession session) {
+ super(provider, session);
+ }
+
+ @Override
+ public String toString() {
+ return "ThreadVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
+ for (final ILabelUpdate update : updates) {
+ final IRunControl runControl = getServicesTracker().getService(IRunControl.class);
+ if (runControl == null) {
+ handleFailedUpdate(update);
+ continue;
+ }
+
+ final IMIExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IMIExecutionDMContext.class);
+
+ String imageKey = null;
+ final boolean threadSuspended;
+ if (runControl.isSuspended(execDmc)) {
+ threadSuspended = true;
+ imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED;
+ } else {
+ threadSuspended = false;
+ imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING;
+ }
+ update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
+
+ // Find the Reason for the State
+ runControl.getExecutionData(execDmc,
+ new ViewerDataRequestMonitor(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted(){
+ if (!isSuccess()) {
+ update.setLabel("", 0); //$NON-NLS-1$
+ update.done();
+ return;
+ }
+
+ final IProcesses procService = getServicesTracker().getService(IProcesses.class);
+ if ( procService == null ) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final StateChangeReason reason = getData().getStateChangeReason();
+
+ // Retrieve the rest of the thread information
+ final IThreadDMContext threadDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IThreadDMContext.class);
+
+ procService.getExecutionData(
+ threadDmc,
+ new ViewerDataRequestMonitor(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ // We can still generate a good enough label even if this call fails
+ // so continue and check if we should use getData() or not.
+
+ // Create Labels of type Thread[GDBthreadId]RealThreadID/Name (State: Reason)
+ // Thread[1] 3457 (Suspended:BREAKPOINT)
+ final StringBuilder builder = new StringBuilder("Thread["); //$NON-NLS-1$
+ builder.append(execDmc.getThreadId());
+ builder.append("] "); //$NON-NLS-1$
+ if (isSuccess()) {
+ builder.append(getData().getId());
+ builder.append(getData().getName());
+ }
+ if(threadSuspended)
+ builder.append(" (Suspended"); //$NON-NLS-1$
+ else
+ builder.append(" (Running"); //$NON-NLS-1$
+ // Reason will be null before ContainerSuspendEvent is fired
+ if(reason != null) {
+ builder.append(" : "); //$NON-NLS-1$
+ builder.append(reason);
+ }
+ builder.append(")"); //$NON-NLS-1$
+ update.setLabel(builder.toString(), 0);
+ update.done();
+ }
+ });
+ }
+ });
+
+ }
+ }
+
+ private String produceThreadElementName(String viewName, IMIExecutionDMContext execCtx) {
+ return "Thread." + execCtx.getThreadId(); //$NON-NLS-1$
+ }
+
+ private static final String MEMENTO_NAME = "THREAD_MEMENTO_NAME"; //$NON-NLS-1$
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ public void compareElements(IElementCompareRequest[] requests) {
+
+ for ( IElementCompareRequest request : requests ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+ String mementoName = memento.getString(MEMENTO_NAME);
+
+ if (mementoName != null) {
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IMIExecutionDMContext) {
+
+ String elementName = produceThreadElementName( request.getPresentationContext().getId(), (IMIExecutionDMContext) dmc );
+ request.setEqual( elementName.equals( mementoName ) );
+ }
+ }
+ }
+ request.done();
+ }
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[])
+ */
+ public void encodeElements(IElementMementoRequest[] requests) {
+
+ for ( IElementMementoRequest request : requests ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IMIExecutionDMContext) {
+
+ String elementName = produceThreadElementName( request.getPresentationContext().getId(), (IMIExecutionDMContext) dmc );
+ memento.putString(MEMENTO_NAME, elementName);
+ }
+ }
+ request.done();
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.classpath b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.classpath
new file mode 100644
index 00000000000..304e86186aa
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options
new file mode 100644
index 00000000000..28eeb8b6aa9
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.options
@@ -0,0 +1 @@
+org.eclipse.cdt.dsf.gdb/debug = false
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.project b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.project
new file mode 100644
index 00000000000..01d65c04880
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.project
@@ -0,0 +1,34 @@
+
+
+ org.eclipse.cdt.dsf.gdb
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.pde.ManifestBuilder
+
+
+
+
+ org.eclipse.pde.SchemaBuilder
+
+
+
+
+ org.eclipse.pde.api.tools.apiAnalysisBuilder
+
+
+
+
+
+ org.eclipse.pde.PluginNature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.pde.api.tools.apiAnalysisNature
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
new file mode 100644
index 00000000000..5d4626f8d7e
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/org.eclipse.jdt.core.prefs b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..acad5c5fe98
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,70 @@
+#Tue Jun 24 11:04:03 PDT 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
new file mode 100644
index 00000000000..997fe8ae320
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true
+Bundle-Version: 2.0.0.qualifier
+Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.cdt.dsf,
+ org.eclipse.debug.core,
+ org.eclipse.cdt.core,
+ org.eclipse.cdt.debug.core,
+ org.eclipse.core.variables
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.eclipse.cdt.dsf.gdb,
+ org.eclipse.cdt.dsf.gdb.actions,
+ org.eclipse.cdt.dsf.gdb.breakpoints,
+ org.eclipse.cdt.dsf.gdb.launching,
+ org.eclipse.cdt.dsf.gdb.service,
+ org.eclipse.cdt.dsf.gdb.service.command,
+ org.eclipse.cdt.dsf.mi.service,
+ org.eclipse.cdt.dsf.mi.service.command,
+ org.eclipse.cdt.dsf.mi.service.command.commands,
+ org.eclipse.cdt.dsf.mi.service.command.events,
+ org.eclipse.cdt.dsf.mi.service.command.output
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/about.html b/dsf-gdb/org.eclipse.cdt.dsf.gdb/about.html
new file mode 100644
index 00000000000..cb740ae8bc8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/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/dsf-gdb/org.eclipse.cdt.dsf.gdb/build.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/build.properties
new file mode 100644
index 00000000000..6c286bf62a9
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/build.properties
@@ -0,0 +1,17 @@
+###############################################################################
+# Copyright (c) 2006, 2008 Wind River Systems and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Wind River Systems - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ about.html,\
+ plugin.properties
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties
new file mode 100644
index 00000000000..c3f20315fe2
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties
@@ -0,0 +1,13 @@
+###############################################################################
+# 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
+###############################################################################
+pluginName=GDB DSF Debugger Integration Core
+providerName=Eclipse.org
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.xml
new file mode 100644
index 00000000000..c49c90e1fb3
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java
new file mode 100644
index 00000000000..ad9cbb8ec53
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/IGDBLaunchConfigurationConstants.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb;
+
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+
+
+public class IGDBLaunchConfigurationConstants {
+
+ //
+ // Taken from org.eclipse.cdt.debug.mi.core.IGDBServerMILaunchConfigurationConstants
+ //
+ public static final String ATTR_REMOTE_TCP = GdbPlugin.PLUGIN_ID + ".REMOTE_TCP"; //$NON-NLS-1$
+ public static final String ATTR_HOST = GdbPlugin.PLUGIN_ID + ".HOST"; //$NON-NLS-1$
+ public static final String ATTR_PORT = GdbPlugin.PLUGIN_ID + ".PORT"; //$NON-NLS-1$
+ public static final String ATTR_DEV = GdbPlugin.PLUGIN_ID + ".DEV"; //$NON-NLS-1$
+ public static final String ATTR_DEV_SPEED = GdbPlugin.PLUGIN_ID + ".DEV_SPEED"; //$NON-NLS-1$
+ //
+ //
+
+ //
+ // New to DSF GDB/MI
+ public static final String DEBUGGER_MODE_REMOTE = "remote"; //$NON-NLS-1$
+ public static final String DEBUGGER_MODE_REMOTE_ATTACH = "remote_attach"; //$NON-NLS-1$
+ //
+ //
+
+ //
+ // Taken from org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants
+ //
+ /**
+ * Launch configuration attribute key. The value is the name of
+ * the Debuger associated with a C/C++ launch configuration.
+ */
+ public static final String ATTR_DEBUG_NAME = GdbPlugin.PLUGIN_ID + ".DEBUG_NAME"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. Boolean value to set the gdb command file
+ * Debuger/gdb/MI property.
+ */
+ public static final String ATTR_GDB_INIT = GdbPlugin.PLUGIN_ID + ".GDB_INIT"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. Boolean value to set the non-stop mode
+ * Debuger/gdb/MI property.
+ * @since 1.1
+ */
+ public static final String ATTR_DEBUGGER_NON_STOP = GdbPlugin.PLUGIN_ID + ".NON_STOP"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. Boolean value to set the 'automatically load shared library symbols' flag of the debugger.
+ */
+ public static final String ATTR_DEBUGGER_AUTO_SOLIB = GdbPlugin.PLUGIN_ID + ".AUTO_SOLIB"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. Boolean value to set the 'use shared library symbols for application' flag of the debugger.
+ * @since 1.1
+ */
+ public static final String ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP = GdbPlugin.PLUGIN_ID + ".USE_SOLIB_SYMBOLS_FOR_APP"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. The value is a List (array of String) of directories for the search path of shared libraries.
+ */
+ public static final String ATTR_DEBUGGER_SOLIB_PATH = GdbPlugin.PLUGIN_ID + ".SOLIB_PATH"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. The value is a List (array of String) of shared libraries to load symbols automatically.
+ */
+ public static final String ATTR_DEBUGGER_AUTO_SOLIB_LIST = GdbPlugin.PLUGIN_ID + ".AUTO_SOLIB_LIST"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute key. The value is a boolean specifying the mode of the gdb console.
+ * @since 1.1
+ */
+ public static final String ATTR_DEBUGGER_VERBOSE_MODE = GdbPlugin.PLUGIN_ID + ".verboseMode"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_DEBUG_NAME.
+ */
+ public static final String DEBUGGER_DEBUG_NAME_DEFAULT = "gdb"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_GDB_INIT.
+ */
+ public static final String DEBUGGER_GDB_INIT_DEFAULT = ".gdbinit"; //$NON-NLS-1$
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_DEBUGGER_NON_STOP.
+ * @since 1.1
+ */
+ public static final boolean DEBUGGER_NON_STOP_DEFAULT = false;
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_DEBUGGER_AUTO_SOLIB.
+ */
+ public static final boolean DEBUGGER_AUTO_SOLIB_DEFAULT = true;
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP.
+ * @since 1.1
+ */
+ public static final boolean DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT = false;
+
+ /**
+ * Launch configuration attribute value. The key is ATTR_DEBUGGER_VERBOSE_MODE.
+ * @since 1.1
+ */
+ public static final boolean DEBUGGER_VERBOSE_MODE_DEFAULT = false;
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/actions/IConnect.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/actions/IConnect.java
new file mode 100644
index 00000000000..16fb86f24a0
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/actions/IConnect.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.actions;
+
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+
+/**
+ * @since 1.1
+ */
+public interface IConnect {
+ /**
+ * Returns whether this element can currently attempt to
+ * connect to a new process.
+ */
+ public boolean canConnect();
+
+ /**
+ * Causes this element to attempt to connect to a new process.
+ */
+ public void connect(RequestMonitor rm);
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/breakpoints/CBreakpointGdbThreadsFilterExtension.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/breakpoints/CBreakpointGdbThreadsFilterExtension.java
new file mode 100644
index 00000000000..0d68b3f28f8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/breakpoints/CBreakpointGdbThreadsFilterExtension.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.breakpoints;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.cdt.debug.core.model.ICBreakpoint;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ *
+ */
+public class CBreakpointGdbThreadsFilterExtension implements IDsfBreakpointExtension {
+
+ private Map> fFilteredThreadsByTarget =
+ new HashMap>(1);
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpointExtension#initialize(org.eclipse.cdt.debug.core.model.ICBreakpoint)
+ */
+ public void initialize(ICBreakpoint breakpoint) {
+ // TODO: Initialize fFilteredThreadsByTarget with current IContainerDMContext[]
+ // TODO: IRunControl?
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#getTargetFilters()
+ */
+ public IContainerDMContext[] getTargetFilters() throws CoreException {
+ Set set = fFilteredThreadsByTarget.keySet();
+ return set.toArray( new IContainerDMContext[set.size()] );
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#getThreadFilters(org.eclipse.cdt.debug.core.model.ICDebugTarget)
+ */
+ public IExecutionDMContext[] getThreadFilters( IContainerDMContext target ) throws CoreException {
+ Set set = fFilteredThreadsByTarget.get( target );
+ return ( set != null ) ? set.toArray( new IExecutionDMContext[set.size()] ) : null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#removeTargetFilter(org.eclipse.cdt.debug.core.model.ICDebugTarget)
+ */
+ public void removeTargetFilter( IContainerDMContext target ) throws CoreException {
+ if ( fFilteredThreadsByTarget.containsKey( target ) ) {
+ fFilteredThreadsByTarget.remove( target );
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#removeThreadFilters(org.eclipse.cdt.debug.core.model.ICThread[])
+ */
+ public void removeThreadFilters( IExecutionDMContext[] threads ) throws CoreException {
+ if ( threads != null && threads.length > 0 ) {
+ IContainerDMContext target = DMContexts.getAncestorOfType(threads[0], IContainerDMContext.class);
+ if ( fFilteredThreadsByTarget.containsKey( target ) ) {
+ Set set = fFilteredThreadsByTarget.get( target );
+ if ( set != null ) {
+ set.removeAll( Arrays.asList( threads ) );
+ if ( set.isEmpty() ) {
+ fFilteredThreadsByTarget.remove( target );
+ }
+ }
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#setTargetFilter(org.eclipse.cdt.debug.core.model.ICDebugTarget)
+ */
+ public void setTargetFilter( IContainerDMContext target ) throws CoreException {
+ fFilteredThreadsByTarget.put( target, null );
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.debug.core.model.ICBreakpoint#setThreadFilters(org.eclipse.cdt.debug.core.model.ICThread[])
+ */
+ public void setThreadFilters( IExecutionDMContext[] threads ) throws CoreException {
+ if ( threads != null && threads.length > 0 ) {
+ IContainerDMContext target = DMContexts.getAncestorOfType(threads[0], IContainerDMContext.class);
+ fFilteredThreadsByTarget.put( target, new HashSet( Arrays.asList( threads ) ) );
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java
new file mode 100644
index 00000000000..f2f1a184714
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/internal/GdbPlugin.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.internal;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+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 GdbPlugin extends Plugin {
+
+ // Debugging flag
+ public static boolean DEBUG = false;
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
+
+ // The shared instance
+ private static GdbPlugin plugin;
+
+ private static BundleContext fgBundleContext;
+
+ /**
+ * The constructor
+ */
+ public GdbPlugin() {
+ }
+
+ /*
+ * (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;
+
+ DEBUG = "true".equals(Platform.getDebugOption("org.eclipse.cdt.dsf.gdb/debug")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ /*
+ * (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 GdbPlugin 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$
+ }
+ }
+ }
+ }
+
+ public static void debug(String message) {
+ if (DEBUG) {
+ System.out.print(message);
+ }
+ }
+
+ public static String getDebugTime() {
+ StringBuilder traceBuilder = new StringBuilder();
+
+ // Record the time
+ long time = System.currentTimeMillis();
+ long seconds = (time / 1000) % 1000;
+ if (seconds < 100) traceBuilder.append('0');
+ if (seconds < 10) traceBuilder.append('0');
+ traceBuilder.append(seconds);
+ traceBuilder.append(',');
+ long millis = time % 1000;
+ if (millis < 100) traceBuilder.append('0');
+ if (millis < 10) traceBuilder.append('0');
+ traceBuilder.append(millis);
+ return traceBuilder.toString();
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java
new file mode 100644
index 00000000000..c779e58e4c1
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/FinalLaunchSequence.java
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * 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
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import java.util.List;
+
+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.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+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.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.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
+import org.eclipse.cdt.dsf.mi.service.command.commands.CLISource;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentCD;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIFileExecAndSymbols;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetArgs;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetAutoSolib;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetNonStop;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBSetSolibSearchPath;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MITargetSelect;
+import org.eclipse.cdt.dsf.mi.service.command.commands.RawCommand;
+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.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+public class FinalLaunchSequence extends Sequence {
+
+ Step[] fSteps = new Step[] {
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), fLaunch.getSession().getId());
+ requestMonitor.done();
+ }
+ @Override
+ public void rollBack(RequestMonitor requestMonitor) {
+ if (fTracker != null) fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }},
+
+ /*
+ * Fetch the GDBBackend service for later use
+ */
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fGDBBackend = fTracker.getService(IGDBBackend.class);
+ if (fGDBBackend == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain GDBBackend service", null)); //$NON-NLS-1$
+ }
+
+ requestMonitor.done();
+ }},
+ /*
+ * Fetch the control service for later use
+ */
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fCommandControl = fTracker.getService(IGDBControl.class);
+ if (fCommandControl == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain control service", null)); //$NON-NLS-1$
+ }
+
+ requestMonitor.done();
+ }},
+ /*
+ * Fetch the process service for later use
+ */
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fProcService = fTracker.getService(IMIProcesses.class);
+ if (fProcService == null) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$
+ }
+
+ requestMonitor.done();
+ }},
+ /*
+ * Source the gdbinit file specified in the launch
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ try {
+ final String gdbinitFile = fGDBBackend.getGDBInitFile();
+
+ if (gdbinitFile != null && gdbinitFile.length() > 0) {
+ fCommandControl.queueCommand(
+ new CLISource(fCommandControl.getContext(), gdbinitFile),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleCompleted() {
+ // If the gdbinitFile is the default, then it may not exist and we
+ // should not consider this an error.
+ // If it is not the default, then the user must have specified it and
+ // we want to warn the user if we can't find it.
+ if (!gdbinitFile.equals(IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT )) {
+ requestMonitor.setStatus(getStatus());
+ }
+ requestMonitor.done();
+ }
+ });
+ } else {
+ requestMonitor.done();
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get gdbinit option", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }},
+ /*
+ * Specify the executable file to be debugged and read the symbol table.
+ */
+ new Step() { @Override
+ public void execute(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(
+ new MIFileExecAndSymbols(fCommandControl.getContext(),
+ execPath.toPortableString()),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ } else {
+ requestMonitor.done();
+ }
+ }},
+ /*
+ * Specify the arguments to the executable file
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ try {
+ String args = fGDBBackend.getProgramArguments();
+
+ if (args != null) {
+ fCommandControl.queueCommand(
+ new MIGDBSetArgs(fCommandControl.getContext(), args),
+ new DataRequestMonitor(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();
+ }
+ }},
+ /*
+ * Specify GDB's working directory
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ IPath dir = null;
+ try {
+ dir = fGDBBackend.getGDBWorkingDirectory();
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get working directory", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ if (dir != null) {
+ fCommandControl.queueCommand(
+ new MIEnvironmentCD(fCommandControl.getContext(), dir.toPortableString()),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ } else {
+ requestMonitor.done();
+ }
+ }},
+ /*
+ * Enable non-stop mode if necessary
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ boolean isNonStop = false;
+ try {
+ isNonStop = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
+ } catch (CoreException e) {
+ }
+
+ // 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.
+ // Something to fix later.
+ if (isNonStop) {
+ // The raw commands should not be necessary in the official GDB release
+ fCommandControl.queueCommand(
+ new RawCommand(fCommandControl.getContext(), "set target-async on"), //$NON-NLS-1$
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ fCommandControl.queueCommand(
+ new RawCommand(fCommandControl.getContext(), "set pagination off"), //$NON-NLS-1$
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ fCommandControl.queueCommand(
+ new MIGDBSetNonStop(fCommandControl.getContext(), true),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ }
+ });
+ }
+ });
+ } else {
+ requestMonitor.done();
+ }
+ }},
+ /*
+ * Tell GDB to automatically load or not the shared library symbols
+ */
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ try {
+ boolean autolib = fLaunch.getLaunchConfiguration().getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB,
+ IGDBLaunchConfigurationConstants.DEBUGGER_AUTO_SOLIB_DEFAULT);
+ fCommandControl.queueCommand(
+ new MIGDBSetAutoSolib(fCommandControl.getContext(), autolib),
+ new DataRequestMonitor(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();
+ }
+ }},
+ /*
+ * Set the shared library paths
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ try {
+ List p = fGDBBackend.getSharedLibraryPaths();
+
+ if (p.size() > 0) {
+ String[] paths = p.toArray(new String[p.size()]);
+ fCommandControl.queueCommand(
+ new MIGDBSetSolibSearchPath(fCommandControl.getContext(), paths),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+// Sysroot is not available in GDB6.6 and will make the launch fail in that case.
+// Let's remove it for now
+ requestMonitor.done();
+// // If we are able to set the solib-search-path,
+// // we should disable the sysroot variable, as indicated
+// // in the GDB documentation. This is to avoid the sysroot
+// // variable finding libraries that were not meant to be found.
+// fCommandControl.queueCommand(
+// new MIGDBSetSysroot(fCommandControl.getContext()),
+// new DataRequestMonitor(getExecutor(), requestMonitor));
+ };
+ });
+ } else {
+ requestMonitor.done();
+ }
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set share library paths", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }},
+ /*
+ * Setup the source paths
+ */
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ CSourceLookup sourceLookup = fTracker.getService(CSourceLookup.class);
+ CSourceLookupDirector locator = (CSourceLookupDirector)fLaunch.getSourceLocator();
+ ISourceLookupDMContext sourceLookupDmc = (ISourceLookupDMContext)fCommandControl.getContext();
+
+ sourceLookup.setSourceLookupPath(sourceLookupDmc, locator.getSourceContainers(), requestMonitor);
+ }},
+ /*
+ * If remote debugging, connect to target.
+ */
+ new Step() {
+ 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;
+ }
+
+ @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ if (fSessionType == SessionType.REMOTE) {
+ if (!checkConnectionType(requestMonitor)) return;
+
+ if (fTcpConnection) {
+ if (!getTcpHost(requestMonitor)) return;
+ if (!getTcpPort(requestMonitor)) return;
+
+ fCommandControl.queueCommand(
+ new MITargetSelect(fCommandControl.getContext(),
+ fRemoteTcpHost, fRemoteTcpPort, fAttach),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ } else {
+ if (!getSerialDevice(requestMonitor)) return;
+
+ fCommandControl.queueCommand(
+ new MITargetSelect(fCommandControl.getContext(),
+ fSerialDevice, fAttach),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ }
+ } else {
+ requestMonitor.done();
+ }
+ }
+ },
+ /*
+ * If attach session, perform the attach.
+ */
+ new Step() {
+ @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ if (fAttach) {
+ // 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
+ }
+
+ if (pid != -1) {
+ fProcService.attachDebuggerToProcess(
+ fProcService.createProcessContext(fCommandControl.getContext(), Integer.toString(pid)),
+ new DataRequestMonitor(getExecutor(), requestMonitor));
+ } else {
+ IConnect connectCommand = (IConnect)fLaunch.getSession().getModelAdapter(IConnect.class);
+ if (connectCommand != null) {
+ connectCommand.connect(requestMonitor);
+ } else {
+ requestMonitor.done();
+ }
+ }
+ } else {
+ requestMonitor.done();
+ }
+ }
+ },
+ /*
+ * Start tracking the breakpoints once we know we are connected to the target (necessary for remote debugging)
+ */
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ MIBreakpointsManager bpmService = fTracker.getService(MIBreakpointsManager.class);
+ IBreakpointsTargetDMContext breakpointDmc = (IBreakpointsTargetDMContext)fCommandControl.getContext();
+
+ bpmService.startTrackingBreakpoints(breakpointDmc, requestMonitor);
+ }},
+ /*
+ * Start the program.
+ */
+ new Step() {
+ @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ fCommandControl.start(fLaunch, requestMonitor);
+ }
+ },
+ /*
+ * Cleanup
+ */
+ new Step() {
+ @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ fTracker.dispose();
+ fTracker = null;
+ requestMonitor.done();
+ }
+ },
+ };
+
+ GdbLaunch fLaunch;
+ SessionType fSessionType;
+ boolean fAttach;
+
+ private IGDBControl fCommandControl;
+ private IGDBBackend fGDBBackend;
+ private IMIProcesses fProcService;
+
+ DsfServicesTracker fTracker;
+
+ public FinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach, IProgressMonitor pm) {
+ super(executor, pm, "Configuring GDB", "Aborting configuring GDB");
+ fLaunch = launch;
+ fSessionType = sessionType;
+ fAttach = attach;
+ }
+
+ @Override
+ public Step[] getSteps() {
+ return fSteps;
+ }
+}
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBDebugger.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBDebugger.java
new file mode 100644
index 00000000000..bc4e9ddc460
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBDebugger.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Ericsson - Modified for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+/* This class simply exists because the extension needs it.
+ * However, since we only use the extension to re-use some CDT code,
+ * we don't actually need this class to do anything.
+ */
+public class GDBDebugger {}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBServerDebugger.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBServerDebugger.java
new file mode 100644
index 00000000000..b8f1336b7e2
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GDBServerDebugger.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - Initial API and implementation
+ * Ericsson - Modified for Ericsson
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+/* This class simply exists because the extension needs it.
+ * However, since we only use the extension to re-use some CDT code,
+ * we don't actually need this class to do anything.
+ */
+public class GDBServerDebugger {}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
new file mode 100644
index 00000000000..521426d709f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java
@@ -0,0 +1,298 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+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.concurrent.Sequence;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.model.DsfMemoryBlockRetrieval;
+import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
+import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+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.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.Launch;
+import org.eclipse.debug.core.model.IDisconnect;
+import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
+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, IDisconnect
+{
+ private DefaultDsfExecutor fExecutor;
+ private DsfSession fSession;
+ private DsfServicesTracker fTracker;
+ private boolean fInitialized = false;
+ private boolean fShutDown = false;
+
+ private DsfMemoryBlockRetrieval fMemRetrieval;
+ private IDsfDebugServicesFactory fServiceFactory;
+
+ 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(GdbLaunchDelegate.GDB_DEBUG_MODEL_ID);
+ dsfExecutor.prestartCoreThread();
+ fExecutor = dsfExecutor;
+ fSession = DsfSession.startSession(fExecutor, GdbLaunchDelegate.GDB_DEBUG_MODEL_ID);
+ }
+
+ public DsfExecutor getDsfExecutor() { return fExecutor; }
+ public IDsfDebugServicesFactory getServiceFactory() { return fServiceFactory; }
+
+ public void initialize()
+ {
+ Runnable initRunnable = new DsfRunnable() {
+ public void run() {
+ fTracker = new DsfServicesTracker(GdbPlugin.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, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Error initializing launch", e); //$NON-NLS-1$
+ }
+ }
+
+ public void initializeControl()
+ throws CoreException
+ {
+ // Create a memory retrieval and register it with the session
+ try {
+ fExecutor.submit( new Callable() {
+ public Object call() throws CoreException {
+ ICommandControlService commandControl = fTracker.getService(ICommandControlService.class);
+ IMIProcesses procService = fTracker.getService(IMIProcesses.class);
+ if (commandControl != null && procService != null) {
+ fMemRetrieval = new DsfMemoryBlockRetrieval(
+ GdbLaunchDelegate.GDB_DEBUG_MODEL_ID, getLaunchConfiguration(), fSession);
+ fSession.registerModelAdapter(IMemoryBlockRetrieval.class, fMemRetrieval);
+
+ IProcessDMContext procDmc = procService.createProcessContext(commandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
+ IMemoryDMContext memoryDmc = (IMemoryDMContext)procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
+ fMemRetrieval.initialize(memoryDmc);
+ }
+ return null;
+ }
+ }).get();
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.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, GdbPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+ }
+
+ public DsfSession getSession() { return fSession; }
+
+ @ThreadSafeAndProhibitedFromDsfExecutor("getDsfExecutor()")
+ public void addInferiorProcess(String label) throws CoreException {
+ try {
+ // Add the "inferior" process object to the launch.
+ MIInferiorProcess inferiorProc =
+ getDsfExecutor().submit( new Callable() {
+ public MIInferiorProcess call() throws CoreException {
+ IGDBControl gdb = fTracker.getService(IGDBControl.class);
+ if (gdb != null) {
+ return gdb.getInferiorProcess();
+ }
+ return null;
+ }
+ }).get();
+
+ DebugPlugin.newProcess(this, inferiorProc, label);
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.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, GdbPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+ }
+
+ @ThreadSafeAndProhibitedFromDsfExecutor("getDsfExecutor()")
+ public void addCLIProcess(String label) throws CoreException {
+ try {
+ // Add the CLI process object to the launch.
+ AbstractCLIProcess cliProc =
+ getDsfExecutor().submit( new Callable() {
+ public AbstractCLIProcess call() throws CoreException {
+ IGDBControl gdb = fTracker.getService(IGDBControl.class);
+ if (gdb != null) {
+ return gdb.getCLIProcess();
+ }
+ return null;
+ }
+ }).get();
+
+ DebugPlugin.newProcess(this, cliProc, label);
+ } catch (InterruptedException e) {
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.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, GdbPlugin.PLUGIN_ID, 0, "Debugger shut down before launch was completed.", e)); //$NON-NLS-1$
+ }
+ }
+
+ public void setServiceFactory(IDsfDebugServicesFactory factory) {
+ fServiceFactory = factory;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IServiceEventListener
+ @DsfServiceEventHandler public void eventDispatched(ICommandControlShutdownDMEvent 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
+ ///////////////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IDisconnect
+ @Override
+ public boolean canDisconnect() {
+ return canTerminate();
+ }
+
+ @Override
+ public boolean isDisconnected() {
+ return isTerminated();
+ }
+
+ @Override
+ public void disconnect() throws DebugException {
+ terminate();
+ }
+ // IDisconnect
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * 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 (!isSuccess()) {
+ GdbPlugin.getDefault().getLog().log(new MultiStatus(
+ GdbPlugin.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);
+
+ // DsfMemoryBlockRetrieval.saveMemoryBlocks();
+ fMemRetrieval.saveMemoryBlocks();
+
+ // 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/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java
new file mode 100644
index 00000000000..8a5bdd45f17
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java
@@ -0,0 +1,380 @@
+/*******************************************************************************
+ * Copyright (c) 2008 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
+ * Windriver and Ericsson - Updated for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.cdt.core.model.ICModelMarker;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.service.IDsfDebugServicesFactory;
+import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory;
+import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactoryNS;
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
+
+/**
+ * The shared launch configuration delegate for the DSF/GDB debugger.
+ * This delegate supports all configuration types (local, remote, attach, etc)
+ */
+@ThreadSafe
+public class GdbLaunchDelegate extends LaunchConfigurationDelegate
+ implements ILaunchConfigurationDelegate2
+{
+ public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
+
+ private final static String NON_STOP_FIRST_VERSION = "6.8.50"; //$NON-NLS-1$
+ private boolean isNonStopSession = false;
+
+ public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor == null ) {
+ monitor = new NullProgressMonitor();
+ }
+ 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);
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+
+ try {
+ launchDebugSession( config, launch, monitor );
+ }
+ finally {
+ monitor.done();
+ }
+ }
+
+ private void launchDebugSession( final ILaunchConfiguration config, ILaunch l, IProgressMonitor monitor ) throws CoreException {
+ if ( monitor.isCanceled() ) {
+ return;
+ }
+
+ SessionType sessionType = LaunchUtils.getSessionType(config);
+ boolean attach = LaunchUtils.getIsAttach(config);
+
+ final GdbLaunch launch = (GdbLaunch)l;
+
+ if (sessionType == SessionType.REMOTE) {
+ monitor.subTask( "Debugging remote C/C++ application" );
+ } else {
+ monitor.subTask( "Debugging local C/C++ application" );
+ }
+
+ IPath exePath = new Path(""); //$NON-NLS-1$
+ // An attach session does not need to necessarily have an
+ // executable specified. This is because:
+ // - In remote multi-process attach, there will be more than one executable
+ // In this case executables need to be specified differently.
+ // The current solution is to use the solib-search-path to specify
+ // the path of any executable we can attach to.
+ // - In local single process, GDB has the ability to find the executable
+ // automatically.
+ //
+ // An attach session also does not need to necessarily have a project
+ // specified. This is because we can perform source lookup towards
+ // code that is outside the workspace.
+ // See bug 244567
+ if (!attach) {
+ // First verify we are dealing with a proper project.
+ ICProject project = LaunchUtils.verifyCProject(config);
+ // Now verify we know the program to debug.
+ exePath = LaunchUtils.verifyProgramPath(config, project);
+ // Finally, make sure the program is a proper binary.
+ LaunchUtils.verifyBinary(config, exePath);
+ }
+
+ monitor.worked( 1 );
+
+ String gdbVersion = LaunchUtils.getGDBVersion(config);
+
+ // First make sure non-stop is supported, if the user want to use this mode
+ if (isNonStopSession && !isNonStopSupported(gdbVersion)) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Non-stop mode is only supported starting with GDB " + NON_STOP_FIRST_VERSION, null)); //$NON-NLS-1$
+ }
+
+ launch.setServiceFactory(newServiceFactory(gdbVersion));
+
+ // Create and invoke the launch sequence to create the debug control and services
+ IProgressMonitor subMon1 = new SubProgressMonitor(monitor, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ final ServicesLaunchSequence servicesLaunchSequence =
+ new ServicesLaunchSequence(launch.getSession(), launch, subMon1);
+
+ launch.getSession().getExecutor().execute(servicesLaunchSequence);
+ try {
+ servicesLaunchSequence.get();
+ } catch (InterruptedException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
+ } catch (ExecutionException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in services launch sequence", e1.getCause())); //$NON-NLS-1$
+ }
+
+ if (monitor.isCanceled())
+ return;
+
+ // The initializeControl method should be called after the ICommandControlService
+ // be initialized in the ServicesLaunchSequence above. This is because it is that
+ // service that will trigger the launch cleanup (if we need it during this launch)
+ // through an ICommandControlShutdownDMEvent
+ launch.initializeControl();
+
+ // Add the CLI and "inferior" process objects to the launch.
+ launch.addCLIProcess("gdb"); //$NON-NLS-1$
+ launch.addInferiorProcess(exePath.lastSegment());
+
+ monitor.worked(1);
+
+ // Create and invoke the final launch sequence to setup GDB
+ IProgressMonitor subMon2 = new SubProgressMonitor(monitor, 4, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ final Sequence finalLaunchSequence =
+ getFinalLaunchSequence(launch.getSession().getExecutor(), launch, sessionType, attach, subMon2);
+
+ launch.getSession().getExecutor().execute(finalLaunchSequence);
+ boolean succeed = false;
+ try {
+ finalLaunchSequence.get();
+ succeed = true;
+ } catch (InterruptedException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "Interrupted Exception in dispatch thread", e1)); //$NON-NLS-1$
+ } catch (ExecutionException e1) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in final launch sequence", e1.getCause())); //$NON-NLS-1$
+ } finally {
+ if (!succeed) {
+ // finalLaunchSequence failed. Shutdown the session so that all started
+ // services including any GDB process are shutdown. (bug 251486)
+ //
+ Query launchShutdownQuery = new Query() {
+ @Override
+ protected void execute(DataRequestMonitor rm) {
+ launch.shutdownSession(rm);
+ }
+ };
+
+ launch.getSession().getExecutor().execute(launchShutdownQuery);
+
+ // wait for the shutdown to finish.
+ // The Query.get() method is a synchronous call which blocks until the
+ // query completes.
+ try {
+ launchShutdownQuery.get();
+ } catch (InterruptedException e) {
+ throw new DebugException( new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.INTERNAL_ERROR, "InterruptedException while shutting down debugger launch " + launch, e)); //$NON-NLS-1$
+ } catch (ExecutionException e) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED, "Error in shutting down debugger launch " + launch, e)); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ /*
+ * This method can be overridden by subclasses to allow to change the final launch sequence without
+ * having to change the entire GdbLaunchDelegate
+ */
+ protected Sequence getFinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType type, boolean attach, IProgressMonitor pm) {
+ return new FinalLaunchSequence(executor, launch, type, attach, pm);
+ }
+
+
+ private boolean isNonStopSession(ILaunchConfiguration config) {
+ try {
+ boolean nonStopMode = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
+ IGDBLaunchConfigurationConstants.DEBUGGER_NON_STOP_DEFAULT);
+ return nonStopMode;
+ } catch (CoreException e) {
+ }
+ return false;
+ }
+
+
+ @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) && LaunchUtils.getSessionType(config) == SessionType.CORE) return true;
+
+ return super.preLaunchCheck(config, mode, monitor);
+ }
+
+ @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.
+
+ isNonStopSession = isNonStopSession(configuration);
+
+ GdbLaunch launch = new GdbLaunch(configuration, mode, null);
+ launch.initialize();
+ launch.setSourceLocator(getSourceLocator(configuration, launch.getSession()));
+ return launch;
+ }
+
+ private ISourceLocator getSourceLocator(ILaunchConfiguration configuration, DsfSession session) throws CoreException {
+ DsfSourceLookupDirector locator = new DsfSourceLookupDirector(session);
+ String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
+ if (memento == null) {
+ locator.initializeDefaults(configuration);
+ } else {
+ locator.initializeFromMemento(memento, configuration);
+ }
+ return locator;
+ }
+
+ /**
+ * Recursively creates a set of projects referenced by the current project
+ *
+ * @param proj
+ * The current project
+ * @param referencedProjSet
+ * A set of referenced projects
+ * @throws CoreException
+ * if an error occurs while getting referenced projects from the
+ * current project
+ */
+ private HashSet getReferencedProjectSet(IProject proj, HashSet referencedProjSet) throws CoreException {
+ // The top project is a reference too and it must be added at the top to avoid cycles
+ referencedProjSet.add(proj);
+
+ IProject[] projects = proj.getReferencedProjects();
+ for (IProject refProject : projects) {
+ if (refProject.exists() && !referencedProjSet.contains(refProject)) {
+ getReferencedProjectSet(refProject, referencedProjSet);
+ }
+ }
+ return referencedProjSet;
+ }
+
+ /**
+ * Returns the order list of projects to build before launching.
+ * Used in buildForLaunch()
+ */
+ @Override
+ protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
+ IProject[] orderedProjects = null;
+ ArrayList orderedProjList = null;
+
+ ICProject cProject = LaunchUtils.verifyCProject(configuration);
+ if (cProject != null) {
+ HashSet projectSet = getReferencedProjectSet(cProject.getProject(), new HashSet());
+
+ String[] orderedNames = ResourcesPlugin.getWorkspace().getDescription().getBuildOrder();
+ if (orderedNames != null) {
+ //Projects may not be in the build order but should still be built if selected
+ ArrayList unorderedProjects = new ArrayList(projectSet.size());
+ unorderedProjects.addAll(projectSet);
+ orderedProjList = new ArrayList(projectSet.size());
+
+ for (String projectName : orderedNames) {
+ for (IProject proj : unorderedProjects) {
+ if (proj.getName().equals(projectName)) {
+ orderedProjList.add(proj);
+ unorderedProjects.remove(proj);
+ break;
+ }
+ }
+ }
+
+ // Add any remaining projects to the end of the list
+ orderedProjList.addAll(unorderedProjects);
+
+ orderedProjects = orderedProjList.toArray(new IProject[orderedProjList.size()]);
+ } else {
+ // Try the project prerequisite order then
+ IProject[] projects = projectSet.toArray(new IProject[projectSet.size()]);
+ orderedProjects = ResourcesPlugin.getWorkspace().computeProjectOrder(projects).projects;
+ }
+ }
+ return orderedProjects;
+ }
+
+ /* Used in finalLaunchCheck() */
+ @Override
+ protected IProject[] getProjectsForProblemSearch(ILaunchConfiguration configuration, String mode) throws CoreException {
+ return getBuildOrder(configuration, mode);
+ }
+
+ /**
+ * Searches for compile errors in the specified project
+ * Used in finalLaunchCheck()
+ * @param proj
+ * The project to search
+ * @return true if compile errors exist, otherwise false
+ */
+ @Override
+ protected boolean existsProblems(IProject proj) throws CoreException {
+ IMarker[] markers = proj.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
+ if (markers.length > 0) {
+ for (IMarker marker : markers) {
+ Integer severity = (Integer)marker.getAttribute(IMarker.SEVERITY);
+ if (severity != null) {
+ return severity.intValue() >= IMarker.SEVERITY_ERROR;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean isNonStopSupported(String version) {
+ if (NON_STOP_FIRST_VERSION.compareTo(version) <= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ // A subclass can override this method and provide its own ServiceFactory.
+ protected IDsfDebugServicesFactory newServiceFactory(String version) {
+
+ if (isNonStopSession && isNonStopSupported(version)) {
+ return new GdbDebugServicesFactoryNS(version);
+ }
+
+ if (version.startsWith("6.6") || //$NON-NLS-1$
+ version.startsWith("6.7") || //$NON-NLS-1$
+ version.startsWith("6.8")) { //$NON-NLS-1$
+ return new GdbDebugServicesFactory(version);
+ }
+
+ return new GdbDebugServicesFactory(version);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.java
new file mode 100644
index 00000000000..449e2df8f16
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ * Ericsson - Update for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class LaunchMessages {
+
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.gdb.launching.LaunchMessages";//$NON-NLS-1$
+
+ private static ResourceBundle RESOURCE_BUNDLE = null;
+
+ static {
+ try {
+ RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+ }
+ catch (MissingResourceException x) {
+ }
+ }
+
+ private LaunchMessages() {}
+
+ public static String getFormattedString(String key, String arg) {
+ return MessageFormat.format(getString(key), (Object[])new String[]{arg});
+ }
+
+ public static String getFormattedString(String key, String[] args) {
+ return MessageFormat.format(getString(key), (Object[])args);
+ }
+
+ public static String getString(String key) {
+ if (RESOURCE_BUNDLE == null) return '!' + key + '!';
+ return RESOURCE_BUNDLE.getString(key);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties
new file mode 100644
index 00000000000..7ee2543bc37
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchMessages.properties
@@ -0,0 +1,159 @@
+###############################################################################
+# Copyright (c) 2008 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
+# Monta Vista - Joanne Woo - Bug 87556
+# Nokia - Ken Ryall - Bug 118894
+###############################################################################
+
+AbstractCLaunchDelegate.Debugger_not_installed=CDT Debugger not installed
+AbstractCLaunchDelegate.C_Project_not_specified=C Project not specified
+AbstractCLaunchDelegate.Not_a_C_CPP_project=Project is not a C/C++ project
+AbstractCLaunchDelegate.Program_file_not_specified=Program file not specified
+AbstractCLaunchDelegate.Program_file_does_not_exist=Program file does not exist
+AbstractCLaunchDelegate.PROGRAM_PATH_not_found={0} not found
+AbstractCLaunchDelegate.Working_directory_does_not_exist=Working directory does not exist
+AbstractCLaunchDelegate.WORKINGDIRECTORY_PATH_not_found=The working directory {0} does not exist.
+AbstractCLaunchDelegate.Project_NAME_does_not_exist=Project {0} does not exist
+AbstractCLaunchDelegate.Project_NAME_is_closed=Project {0} is closed
+AbstractCLaunchDelegate.Debugger_Process=Debugger Process
+AbstractCLaunchDelegate.building_projects=Building prerequisite project list
+AbstractCLaunchDelegate.building=Building
+AbstractCLaunchDelegate.searching_for_errors=Searching for compile errors
+AbstractCLaunchDelegate.searching_for_errors_in=Searching for compile errors in
+AbstractCLaunchDelegate.20=Building prerequisite project list
+AbstractCLaunchDelegate.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
+
+LocalRunLaunchDelegate.Launching_Local_C_Application=Launching Local C/C++ Application
+LocalRunLaunchDelegate.Failed_setting_runtime_option_though_debugger=Failed to set program arguments, environment or working directory.
+LocalRunLaunchDelegate.Error_starting_process=Error starting process
+LocalRunLaunchDelegate.Does_not_support_working_dir=Eclipse runtime does not support working directory
+
+LocalAttachLaunchDelegate.Attaching_to_Local_C_Application=Attaching to Local C/C++ Application
+LocalAttachLaunchDelegate.No_Process_ID_selected=No Process ID selected
+LocalAttachLaunchDelegate.Select_Process=Select Process
+LocalAttachLaunchDelegate.Platform_cannot_list_processes=Current platform does not support listing processes
+LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to=Select a Process to attach the debugger to:
+LocalAttachLaunchDelegate.CDT_Launch_Error=CDT Launch Error
+
+CoreFileLaunchDelegate.Launching_postmortem_debugger=Launching postmortem debugger
+CoreFileLaunchDelegate.No_Corefile_selected=No Corefile selected
+CoreFileLaunchDelegate.No_Shell_available_in_Launch=No Shell available in Launch
+CoreFileLaunchDelegate.Select_Corefile=Select Corefile
+CoreFileLaunchDelegate.Corefile_not_accessible=Core file is not accessible.
+CoreFileLaunchDelegate.Corefile_not_readable=Core file does not exist or is not readable.
+CoreFileLaunchDelegate.postmortem_debugging_failed=Post-mortem debugging failed
+
+CApplicationLaunchShortcut.Application_Launcher=Application Launcher
+CApplicationLaunchShortcut.ChooseConfigToDebug=Choose a debug configuration to debug
+CApplicationLaunchShortcut.ChooseConfigToRun=Choose a configuration to run
+CApplicationLaunchShortcut.CLocalApplication=C Local Application
+CApplicationLaunchShortcut.ChooseLocalAppToDebug=Choose a local application to debug
+CApplicationLaunchShortcut.ChooseLocalAppToRun=Choose a local application to run
+CApplicationLaunchShortcut.Launch_failed_no_binaries=Launch failed no binaries
+CApplicationLaunchShortcut.LaunchFailed=Launch failed
+CApplicationLaunchShortcut.LaunchDebugConfigSelection=Launch Debug Configuration Selection
+CApplicationLaunchShortcut.LaunchConfigSelection=Launch Configuration Selection
+CApplicationLaunchShortcut.Invalid_launch_mode_1=Invalid launch mode
+CApplicationLaunchShortcut.Invalid_launch_mode_2=Invalid launch mode.
+CApplicationLaunchShortcut.Invalid_launch_mode_3=Invalid launch mode.
+CApplicationLaunchShortcut.ChooseLaunchConfigToDebug=Choose a launch configuration to debug
+CApplicationLaunchShortcut.ChooseLaunchConfigToRun=Choose a launch configuration to run
+CApplicationLaunchShortcut.Launch_failed_no_project_selected=Launch failed no project selected
+
+AbstractCDebuggerTab.No_debugger_available=No debugger available
+AbstractCDebuggerTab.Debugger=Debugger
+AbstractCDebuggerTab.ErrorLoadingDebuggerPage=Error Loading Debugger UI Component.
+
+LaunchUIPlugin.Error=Error
+
+CMainTab.Project_required=Project required
+CMainTab.Enter_project_before_searching_for_program=Project must first be entered before searching for a program
+CMainTab.Program_Selection=Program Selection
+CMainTab.Enter_project_before_browsing_for_program=Project must first be entered before browsing for a program
+CMainTab.Program_selection=Program selection
+CMainTab.Selection_must_be_file=Selection must be a file
+CMainTab.Selection_must_be_binary_file=Selection must be a binary file
+CMainTab.Project_Selection=Project Selection
+CMainTab.Choose_project_to_constrain_search_for_program=Choose a &project to constrain the search for a program
+CMainTab.Project_not_specified=Project not specified
+CMainTab.Program_not_specified=Program not specified
+CMainTab.Project_must_be_opened=Project must be opened
+CMainTab.Program_does_not_exist=Program does not exist
+CMainTab.Main=Main
+CMainTab.&ProjectColon=&Project:
+CMainTab.C/C++_Application=C/C++ Application:
+CMainTab.Search...=Searc&h Project...
+CMainTab.Choose_program_to_run=Choose a &program to run:
+CMainTab.Choose_program_to_run_from_NAME=Choose a program to run from {0}:
+CMainTab.UseTerminal=Connect process input & output to a terminal.
+CMainTab.Program_is_not_a_recongnized_executable=Program is not a recognized executable.
+
+CDebuggerTab.Advanced_Options_Dialog_Title=Advanced Options
+CDebuggerTab.Stop_at_main_on_startup=Stop on startup at:
+CDebuggerTab.Automatically_track_values_of=Automatically track the values of
+CDebuggerTab.Stop_on_startup_at_can_not_be_empty=The "Stop on startup at" field can not be empty.
+CDebuggerTab.Debugger_Options=Debugger Options
+CDebuggerTab.Mode_not_supported=Mode ''{0}'' is not supported by selected debugger
+CDebuggerTab.Advanced=Advanced...
+CDebuggerTab.Variables=Variables
+CDebuggerTab.Registers=Registers
+CDebuggerTab.No_debugger_available=No debugger available
+CDebuggerTab.CPU_is_not_supported=The CPU is not supported by selected debugger.
+CDebuggerTab.Platform_is_not_supported=The project platform is not supported by the selected debugger.
+
+CoreFileDebuggerTab.No_debugger_available=No debugger available
+CoreFileDebuggerTab.platform_is_not_supported=The project platform is not supported by the selected debugger.
+
+CEnvironmentTab.Edit_Variable=Edit Variable
+CEnvironmentTab.New_Variable=New Variable
+CEnvironmentTab.NameColon=Name:
+CEnvironmentTab.ValueColon=Value:
+CEnvironmentTab.Name=Name
+CEnvironmentTab.Value=Value
+CEnvironmentTab.New...=New...
+CEnvironmentTab.Import...=Import...
+CEnvironmentTab.Edit...=Edit...
+CEnvironmentTab.Remove=Remove
+CEnvironmentTab.Environment=Environment
+CEnvironmentTab.Existing_Environment_Variable=Existing Environment Variable
+CEnvironmentTab.Environment_variable_NAME_exists=Environment variable \" {0} \" exists.\nDo you want to overwrite?
+
+CArgumentsTab.C/C++_Program_Arguments=Program arguments:
+CArgumentsTab.Arguments=Arguments
+CArgumentsTab.Variables=Variables...
+
+WorkingDirectoryBlock.4=Select a &workspace relative working directory:
+WorkingDirectoryBlock.7=Select a working directory for the launch configuration:
+WorkingDirectoryBlock.0=W&orkspace...
+WorkingDirectoryBlock.Working_Directory_8=Working Directory
+WorkingDirectoryBlock.Working_directory=Working directory:
+WorkingDirectoryBlock.10=Working directory does not exist
+WorkingDirectoryBlock.Use_default=Use de&fault
+WorkingDirectoryBlock.17=Variabl&es...
+WorkingDirectoryBlock.1=File S&ystem...
+WorkingDirectoryBlock.Exception_occurred_reading_configuration___15=Exception occurred reading configuration:
+
+Launch.common.Exception_occurred_reading_configuration_EXCEPTION=Exception occurred reading configuration {0}
+Launch.common.DebuggerColon=Debugger:
+Launch.common.BinariesColon=Binaries:
+Launch.common.QualifierColon=Qualifier:
+Launch.common.Browse_1=&Browse...
+Launch.common.Browse_2=B&rowse...
+Launch.common.Project_does_not_exist=Project does not exist
+LocalCDILaunchDelegate.0=Launching Local C/C++ Application
+LocalCDILaunchDelegate.1=Launching debugger session
+LocalCDILaunchDelegate.2=Debugging local C/C++ application
+LocalCDILaunchDelegate.3=Attaching to Local C/C++ Application
+LocalCDILaunchDelegate.4=No Process ID selected.
+LocalCDILaunchDelegate.5=Launching postmortem debugger session
+LocalCDILaunchDelegate.6=No core file selected
+LocalCDILaunchDelegate.7=Core file does not exist or is not readable.
+LocalCDILaunchDelegate.8=Error starting process.
+LocalCDILaunchDelegate.9=Eclipse runtime does not support working directory.
+LocalCDILaunchDelegate.10=Failed to set program arguments, environment or working directory.
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java
new file mode 100644
index 00000000000..6ed13567276
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/LaunchUtils.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.launching;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.ICExtensionReference;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryObject;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+public class LaunchUtils {
+
+ /**
+ * Verify the following things about the project:
+ * - is a valid project name given
+ * - does the project exist
+ * - is the project open
+ * - is the project a C/C++ project
+ */
+ public static ICProject verifyCProject(ILaunchConfiguration configuration) throws CoreException {
+ String name = getProjectName(configuration);
+ if (name == null) {
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.C_Project_not_specified"), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_UNSPECIFIED_PROJECT);
+ return null;
+ }
+ ICProject cproject = getCProject(configuration);
+ if (cproject == null && name.length() > 0) {
+ IProject proj = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
+ if (!proj.exists()) {
+ abort(
+ LaunchMessages.getFormattedString("AbstractCLaunchDelegate.Project_NAME_does_not_exist", name), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT);
+ } else if (!proj.isOpen()) {
+ abort(LaunchMessages.getFormattedString("AbstractCLaunchDelegate.Project_NAME_is_closed", name), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT);
+ }
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.Not_a_C_CPP_project"), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT);
+ }
+ return cproject;
+ }
+
+
+ /**
+ * Verify that program name of the configuration can be found as a file.
+ *
+ * @return Absolute path of the program location
+ */
+ public static IPath verifyProgramPath(ILaunchConfiguration configuration, ICProject cproject) throws CoreException {
+ String programName = configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, (String)null);
+ if (programName == null) {
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.Program_file_not_specified"), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT);
+ }
+
+ IPath programPath = new Path(programName);
+ if (programPath.isEmpty()) {
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.Program_file_does_not_exist"), null, //$NON-NLS-1$
+ ICDTLaunchConfigurationConstants.ERR_NOT_A_C_PROJECT);
+ }
+
+ if (!programPath.isAbsolute() && cproject != null) {
+ // Find the specified program within the specified project
+ IFile wsProgramPath = cproject.getProject().getFile(programPath);
+ programPath = wsProgramPath.getLocation();
+ }
+
+ if (!programPath.toFile().exists()) {
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.Program_file_does_not_exist"), //$NON-NLS-1$
+ new FileNotFoundException(
+ LaunchMessages.getFormattedString("AbstractCLaunchDelegate.PROGRAM_PATH_not_found", //$NON-NLS-1$
+ programPath.toOSString())),
+ ICDTLaunchConfigurationConstants.ERR_PROGRAM_NOT_EXIST);
+ }
+
+ return programPath;
+ }
+
+
+ /**
+ * Verify that the executable path points to a valid binary file.
+ *
+ * @return An object representing the binary file.
+ */
+ public static IBinaryObject verifyBinary(ILaunchConfiguration configuration, IPath exePath) throws CoreException {
+ ICExtensionReference[] parserRefs = CCorePlugin.getDefault().getBinaryParserExtensions(getCProject(configuration).getProject());
+ for (ICExtensionReference parserRef : parserRefs) {
+ try {
+ IBinaryParser parser = (IBinaryParser)parserRef.createExtension();
+ IBinaryObject exe = (IBinaryObject)parser.getBinary(exePath);
+ if (exe != null) {
+ return exe;
+ }
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+ }
+
+ IBinaryParser parser = CCorePlugin.getDefault().getDefaultBinaryParser();
+ try {
+ return (IBinaryObject)parser.getBinary(exePath);
+ } catch (ClassCastException e) {
+ } catch (IOException e) {
+ }
+
+ abort(LaunchMessages.getString("AbstractCLaunchDelegate.Program_is_not_a_recognized_executable"), //$NON-NLS-1$
+ new FileNotFoundException(
+ LaunchMessages.getFormattedString("AbstractCLaunchDelegate.Program_is_not_a_recognized_executable", //$NON-NLS-1$
+ exePath.toOSString())),
+ ICDTLaunchConfigurationConstants.ERR_PROGRAM_NOT_BINARY);
+
+ return null;
+ }
+
+ /**
+ * Throws a core exception with an error status object built from the given
+ * message, lower level exception, and error code.
+ *
+ * @param message
+ * the status message
+ * @param exception
+ * lower level exception associated with the error, or
+ * null
if none
+ * @param code
+ * error code
+ */
+ private static void abort(String message, Throwable exception, int code) throws CoreException {
+ MultiStatus status = new MultiStatus(GdbPlugin.PLUGIN_ID, code, message, exception);
+ status.add(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, code,
+ exception == null ? "" : exception.getLocalizedMessage(), //$NON-NLS-1$
+ exception));
+ throw new CoreException(status);
+ }
+
+ /**
+ * Returns an ICProject based on the project name provided in the configuration.
+ * First look for a project by name, and then confirm it is a C/C++ project.
+ */
+ public static ICProject getCProject(ILaunchConfiguration configuration) throws CoreException {
+ String projectName = getProjectName(configuration);
+ if (projectName != null) {
+ projectName = projectName.trim();
+ if (projectName.length() > 0) {
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ ICProject cProject = CCorePlugin.getDefault().getCoreModel().create(project);
+ if (cProject != null && cProject.exists()) {
+ return cProject;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String getProjectName(ILaunchConfiguration configuration) throws CoreException {
+ return configuration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String)null);
+ }
+
+ public static IPath getGDBPath(ILaunchConfiguration configuration) {
+ IPath retVal = new Path(IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT);
+ try {
+ retVal = new Path(configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUG_NAME,
+ IGDBLaunchConfigurationConstants.DEBUGGER_DEBUG_NAME_DEFAULT));
+ } catch (CoreException e) {
+ }
+ return retVal;
+ }
+
+ public static String getGDBVersion(final ILaunchConfiguration configuration) throws CoreException {
+ String line, version = "";//$NON-NLS-1$
+ Process process = null;
+ String cmd = getGDBPath(configuration).toOSString() + " --version"; //$NON-NLS-1$
+ try {
+ process = ProcessFactory.getFactory().exec(cmd);
+ } catch(IOException e) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
+ "Error while launching command: " + cmd, e.getCause()));//$NON-NLS-1$
+ }
+
+ try {
+ InputStream stream = process.getInputStream();
+ Reader r = new InputStreamReader(stream);
+ BufferedReader reader = new BufferedReader(r);
+
+ // These are the GDB version patterns I have seen up to now
+ // The pattern works for all of them extracting the version of 6.8.50.20080730
+ // GNU gdb 6.8.50.20080730
+ // GNU gdb (GDB) 6.8.50.20080730-cvs
+ // GNU gdb (Ericsson GDB 1.0-10) 6.8.50.20080730-cvs
+ Pattern pattern = Pattern.compile(" gdb( \\(.*\\))? (\\d*(\\.\\d*)*)", Pattern.MULTILINE); //$NON-NLS-1$
+
+ while ((line = reader.readLine()) != null) {
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ version = matcher.group(2);
+ }
+ }
+ } catch (IOException e) {
+ throw new DebugException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
+ "Error reading GDB STDOUT after sending: " + cmd, e.getCause()));//$NON-NLS-1$
+ }
+
+ return version;
+ }
+
+ public static boolean getIsAttach(ILaunchConfiguration config) {
+ try {
+ String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN );
+ if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) {
+ return false;
+ } else if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH)) {
+ return true;
+ } else if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE)) {
+ return false;
+ } else if (debugMode.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)) {
+ return false;
+ } else if (debugMode.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH)) {
+ return true;
+ }
+ } catch (CoreException e) {
+ }
+ return false;
+ }
+
+ public static SessionType getSessionType(ILaunchConfiguration config) {
+ try {
+ String debugMode = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE, ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN );
+ if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_RUN)) {
+ return SessionType.LOCAL;
+ } else if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_ATTACH)) {
+ return SessionType.LOCAL;
+ } else if (debugMode.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE)) {
+ return SessionType.CORE;
+ } else if (debugMode.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)) {
+ return SessionType.REMOTE;
+ } else if (debugMode.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH)) {
+ return SessionType.REMOTE;
+ }
+ } catch (CoreException e) {
+ }
+ return SessionType.LOCAL;
+ }
+
+ public static boolean getConsoleVerboseMode(ILaunchConfiguration config) {
+ boolean verboseMode = IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT;
+ try {
+ verboseMode = config.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_VERBOSE_MODE,
+ IGDBLaunchConfigurationConstants.DEBUGGER_VERBOSE_MODE_DEFAULT);
+ } catch (CoreException e) {
+ }
+ return verboseMode;
+ }
+
+}
+
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java
new file mode 100644
index 00000000000..160fd5150b5
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Nokia - created GDBBackend service. Sep. 2008
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
+import org.eclipse.cdt.dsf.debug.service.IDisassembly;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IMemory;
+import org.eclipse.cdt.dsf.debug.service.IModules;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public class ServicesLaunchSequence extends Sequence {
+
+ Step[] fSteps = new Step[] {
+ new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ // Create the back end GDB service.
+ //
+ fLaunch.getServiceFactory().createService(IMIBackend.class, fSession, fLaunch.getLaunchConfiguration()).initialize(requestMonitor);
+ }
+ },
+ // Create and initialize the Connection service.
+ new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ //
+ // Create the connection.
+ //
+ fCommandControl = fLaunch.getServiceFactory().createService(ICommandControlService.class, fSession, fLaunch.getLaunchConfiguration());
+ fCommandControl.initialize(requestMonitor);
+ }
+ },
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fProcService = (IMIProcesses)fLaunch.getServiceFactory().createService(IProcesses.class, fSession);
+ fProcService.initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IRunControl.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IMemory.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IModules.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IStack.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IExpressions.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fSourceLookup = (CSourceLookup)fLaunch.getServiceFactory().createService(ISourceLookup.class, fSession);
+ fSourceLookup.initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ ISourceLookupDMContext sourceLookupDmc = (ISourceLookupDMContext)fCommandControl.getContext();
+ fSourceLookup.setSourceLookupDirector(sourceLookupDmc, (CSourceLookupDirector)fLaunch.getSourceLocator());
+ requestMonitor.done();
+ }},
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ // Create the low-level breakpoint service
+ fLaunch.getServiceFactory().createService(IBreakpoints.class, fSession).initialize(new RequestMonitor(getExecutor(), requestMonitor));
+ }},
+ new Step() { @Override
+ public void execute(final RequestMonitor requestMonitor) {
+ // Create high-level breakpoint service and install breakpoints
+ // for the GDB debug context.
+ fLaunch.getServiceFactory().createService(MIBreakpointsManager.class, fSession).initialize(new RequestMonitor(getExecutor(), requestMonitor));
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IRegisters.class, fSession).initialize(requestMonitor);
+ }},
+ new Step() { @Override
+ public void execute(RequestMonitor requestMonitor) {
+ fLaunch.getServiceFactory().createService(IDisassembly.class, fSession).initialize(requestMonitor);
+ }},
+ };
+
+ DsfSession fSession;
+ GdbLaunch fLaunch;
+
+ ICommandControlService fCommandControl;
+ IMIProcesses fProcService;
+ CSourceLookup fSourceLookup;
+
+ public ServicesLaunchSequence(DsfSession session, GdbLaunch launch, IProgressMonitor pm) {
+ super(session.getExecutor(), pm, "Initializing debugger services", "Aborting debugger services initialization");
+ fSession = session;
+ fLaunch = launch;
+ }
+
+ @Override
+ public Step[] getSteps() {
+ return fSteps;
+ }
+
+
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java
new file mode 100644
index 00000000000..e89f4607f9a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.launching;
+
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
+import org.eclipse.cdt.dsf.debug.service.IDisassembly;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IMemory;
+import org.eclipse.cdt.dsf.debug.service.IModules;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.IDsfService;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+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 GdbPlugin.getBundleContext() != null;
+ fTracker = new DsfServicesTracker(GdbPlugin.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(IDisassembly.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IRegisters.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(MIBreakpointsManager.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IBreakpoints.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(ISourceLookup.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IExpressions.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IStack.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IModules.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IMemory.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IRunControl.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IProcesses.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(ICommandControl.class, requestMonitor);
+ }
+ }, new Step() {
+ @Override
+ public void execute(RequestMonitor requestMonitor) {
+ shutdownService(IMIBackend.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 = (IDsfService)fTracker.getService(clazz);
+ if (service != null) {
+ service.shutdown(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleCompleted() {
+ if (!isSuccess()) {
+ GdbPlugin.getDefault().getLog().log(getStatus());
+ }
+ requestMonitor.done();
+ }
+ });
+ } else {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
+ "Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$
+ requestMonitor.done();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java
new file mode 100644
index 00000000000..e7c08175ae6
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java
@@ -0,0 +1,568 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems, Nokia 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:
+ * Nokia - initial API and implementation with some code moved from GDBControl.
+ * Wind River System
+ * Ericsson
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
+import org.eclipse.cdt.dsf.gdb.service.command.GDBControl.InitializationShutdownStep;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.spawner.ProcessFactory;
+import org.eclipse.cdt.utils.spawner.Spawner;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.variables.VariablesPlugin;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Implementation of {@link IGDBBackend} for the common case where GDB is launched
+ * in local file system on host PC where Eclipse runs. This also manages some GDB parameters
+ * from a given launch configuration.
+ *
+ * You can subclass for you special needs.
+ *
+ * @since 1.1
+ */
+public class GDBBackend extends AbstractDsfService implements IGDBBackend {
+
+ private ILaunchConfiguration fLaunchConfiguration;
+
+ /*
+ * Parameters for launching GDB.
+ */
+ private IPath fProgramPath;
+ private IPath fGDBWorkingDirectory;
+ private String fGDBInitFile;
+ private List fSharedLibPaths;
+ private String fProgramArguments;
+
+ private SessionType fSessionType;
+ private Boolean fAttach;
+
+ /**
+ * Unique ID of this service instance.
+ */
+ private final String fBackendId;
+ private static int fgInstanceCounter = 0;
+
+ /*
+ * Service state parameters.
+ */
+ private MonitorJob fMonitorJob;
+ private Process fProcess;
+ private int fGDBExitValue;
+ private int fGDBLaunchTimeout = 30;
+
+ public GDBBackend(DsfSession session, ILaunchConfiguration lc) {
+ super(session);
+ fBackendId = "gdb[" +Integer.toString(fgInstanceCounter++) + "]"; //$NON-NLS-1$//$NON-NLS-2$
+ fLaunchConfiguration = lc;
+
+ try {
+ // Don't call verifyCProject, because the JUnit tests are not setting a project
+ ICProject cproject = LaunchUtils.getCProject(lc);
+ fProgramPath = LaunchUtils.verifyProgramPath(lc, cproject);
+ } catch (CoreException e) {
+ fProgramPath = new Path(""); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize( new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ public void doInitialize(final RequestMonitor requestMonitor) {
+
+ final Sequence.Step[] initializeSteps = new Sequence.Step[] {
+ new GDBProcessStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new MonitorJobStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
+ };
+
+ Sequence startupSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return initializeSteps; }
+ };
+ getExecutor().execute(startupSequence);
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
+ new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new MonitorJobStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new GDBProcessStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ };
+ Sequence shutdownSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return shutdownSteps; }
+ };
+ getExecutor().execute(shutdownSequence);
+ }
+
+
+ private IPath getGDBPath() {
+ return LaunchUtils.getGDBPath(fLaunchConfiguration);
+ }
+
+ /*
+ * Options for GDB process.
+ * Allow subclass to override.
+ */
+ protected String getGDBCommandLine() {
+ StringBuffer gdbCommandLine = new StringBuffer(getGDBPath().toOSString());
+
+ // The goal here is to keep options to an absolute minimum.
+ // All configuration should be done in the launch sequence
+ // to allow for more flexibility.
+ gdbCommandLine.append(" --interpreter"); //$NON-NLS-1$
+ // We currently work with MI version 2. Don't use just 'mi' because it
+ // points to the latest MI version, while we want mi2 specifically.
+ gdbCommandLine.append(" mi2"); //$NON-NLS-1$
+ // Don't read the gdbinit file here. It is read explicitly in
+ // the LaunchSequence to make it easier to customize.
+ gdbCommandLine.append(" --nx"); //$NON-NLS-1$
+
+ return gdbCommandLine.toString();
+ }
+
+ public String getGDBInitFile() throws CoreException {
+ if (fGDBInitFile == null) {
+ fGDBInitFile = fLaunchConfiguration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_GDB_INIT,
+ IGDBLaunchConfigurationConstants.DEBUGGER_GDB_INIT_DEFAULT);
+ }
+
+ return fGDBInitFile;
+ }
+
+ public IPath getGDBWorkingDirectory() throws CoreException {
+ if (fGDBWorkingDirectory == null) {
+
+ // First try to use the user-specified working directory for the debugged program.
+ // This is fine only with local debug.
+ // For remote debug, the working dir of the debugged program will be on remote device
+ // and hence not applicable. In such case we may just use debugged program path on host
+ // as the working dir for GDB.
+ // However, we cannot find a standard/common way to distinguish remote debug from local
+ // debug. For instance, a local debug may also use gdbserver+gdb. So it's up to each
+ // debugger implementation to make the distinction.
+ //
+ IPath path = null;
+ String location = fLaunchConfiguration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String)null);
+
+ if (location != null) {
+ String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(location);
+ if (expandedLocation.length() > 0) {
+ path = new Path(expandedLocation);
+ }
+ }
+
+ if (path != null) {
+ // Some validity check. Should have been done by UI code.
+ if (path.isAbsolute()) {
+ File dir = new File(path.toPortableString());
+ if (! dir.isDirectory())
+ path = null;
+ } else {
+ IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
+ if (res instanceof IContainer && res.exists()) {
+ path = res.getLocation();
+ }
+ else
+ // Relative but not found in workspace.
+ path = null;
+ }
+ }
+
+ if (path == null) {
+ // default working dir is the project if this config has a project
+ ICProject cp = LaunchUtils.getCProject(fLaunchConfiguration);
+ if (cp != null) {
+ IProject p = cp.getProject();
+ path = p.getLocation();
+ }
+ else {
+ // no meaningful value found. Just return null.
+ }
+ }
+
+ fGDBWorkingDirectory = path;
+ }
+
+ return fGDBWorkingDirectory;
+ }
+
+ public String getProgramArguments() throws CoreException {
+ if (fProgramArguments == null) {
+ fProgramArguments = fLaunchConfiguration.getAttribute(
+ ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS,
+ (String)null);
+
+ if (fProgramArguments != null) {
+ fProgramArguments = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(fProgramArguments);
+ }
+ }
+
+ return fProgramArguments;
+ }
+
+ public IPath getProgramPath() {
+ return fProgramPath;
+ }
+
+ @SuppressWarnings("unchecked")
+ public List getSharedLibraryPaths() throws CoreException {
+ if (fSharedLibPaths == null) {
+ fSharedLibPaths = fLaunchConfiguration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
+ new ArrayList(0));
+ }
+
+ return fSharedLibPaths;
+ }
+
+ /*
+ * Launch GDB process.
+ * Allow subclass to override.
+ */
+ protected Process launchGDBProcess(String commandLine) throws CoreException {
+ Process proc = null;
+ try {
+ proc = ProcessFactory.getFactory().exec(commandLine);
+ } catch (IOException e) {
+ String message = "Error while launching command " + commandLine; //$NON-NLS-1$
+ throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, message, e));
+ }
+
+ return proc;
+ }
+
+ public Process getProcess() {
+ return fProcess;
+ }
+
+ public OutputStream getMIOutputStream() {
+ return fProcess.getOutputStream();
+ };
+
+ public InputStream getMIInputStream() {
+ return fProcess.getInputStream();
+ };
+
+ public String getId() {
+ return fBackendId;
+ }
+
+ public void interrupt() {
+ if (fProcess instanceof Spawner) {
+ Spawner gdbSpawner = (Spawner) fProcess;
+ gdbSpawner.interrupt();
+ }
+ }
+
+ public void destroy() {
+ // destroy() should be supported even if it's not spawner.
+ if (getState() == State.STARTED) {
+ fProcess.destroy();
+ }
+ }
+
+ public State getState() {
+ if (fMonitorJob == null) {
+ return State.NOT_INITIALIZED;
+ } else if (fMonitorJob.fExited) {
+ return State.TERMINATED;
+ } else {
+ return State.STARTED;
+ }
+ }
+
+ public int getExitCode() {
+ return fGDBExitValue;
+ }
+
+ public SessionType getSessionType() {
+ if (fSessionType == null) {
+ fSessionType = LaunchUtils.getSessionType(fLaunchConfiguration);
+ }
+ return fSessionType;
+ }
+
+ public boolean getIsAttachSession() {
+ if (fAttach == null) {
+ fAttach = LaunchUtils.getIsAttach(fLaunchConfiguration);
+ }
+ return fAttach;
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ protected class GDBProcessStep extends InitializationShutdownStep {
+ GDBProcessStep(Direction direction) { super(direction); }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ class GDBLaunchMonitor {
+ boolean fLaunched = false;
+ boolean fTimedOut = false;
+ }
+ final GDBLaunchMonitor fGDBLaunchMonitor = new GDBLaunchMonitor();
+
+ final RequestMonitor gdbLaunchRequestMonitor = new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleCompleted() {
+ if (!fGDBLaunchMonitor.fTimedOut) {
+ fGDBLaunchMonitor.fLaunched = true;
+ if (!isSuccess()) {
+ requestMonitor.setStatus(getStatus());
+ }
+ requestMonitor.done();
+ }
+ }
+ };
+
+ final Job startGdbJob = new Job("Start GDB Process Job") { //$NON-NLS-1$
+ {
+ setSystem(true);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ if (gdbLaunchRequestMonitor.isCanceled()) {
+ gdbLaunchRequestMonitor.setStatus(new Status(IStatus.CANCEL, GdbPlugin.PLUGIN_ID, -1, "Canceled starting GDB", null)); //$NON-NLS-1$
+ gdbLaunchRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+
+ String commandLine = getGDBCommandLine();
+
+ try {
+ fProcess = launchGDBProcess(commandLine);
+ } catch(CoreException e) {
+ gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, e.getMessage(), e));
+ gdbLaunchRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+
+ try {
+ Reader r = new InputStreamReader(getMIInputStream());
+ BufferedReader reader = new BufferedReader(r);
+ String line;
+ while ((line = reader.readLine()) != null) {
+ line = line.trim();
+ if (line.endsWith("(gdb)")) { //$NON-NLS-1$
+ break;
+ }
+ }
+ } catch (IOException e) {
+ gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Error reading GDB STDOUT", e)); //$NON-NLS-1$
+ gdbLaunchRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+
+ gdbLaunchRequestMonitor.done();
+ return Status.OK_STATUS;
+ }
+ };
+ startGdbJob.schedule();
+
+ getExecutor().schedule(new Runnable() {
+ public void run() {
+ // Only process the event if we have not finished yet (hit the breakpoint).
+ if (!fGDBLaunchMonitor.fLaunched) {
+ fGDBLaunchMonitor.fTimedOut = true;
+ Thread jobThread = startGdbJob.getThread();
+ if (jobThread != null) {
+ jobThread.interrupt();
+ }
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.TARGET_REQUEST_FAILED, "Timed out trying to launch GDB.", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ }
+ }},
+ fGDBLaunchTimeout, TimeUnit.SECONDS);
+ }
+
+ @Override
+ protected void shutdown(final RequestMonitor requestMonitor) {
+ new Job("Terminating GDB process.") { //$NON-NLS-1$
+ {
+ setSystem(true);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ destroy();
+
+ int attempts = 0;
+ while (attempts < 10) {
+ try {
+ // Don't know if we really need the exit value... but what the heck.
+ fGDBExitValue = fProcess.exitValue(); // throws exception if process not exited
+
+ requestMonitor.done();
+ return Status.OK_STATUS;
+ } catch (IllegalThreadStateException ie) {
+ }
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ }
+ attempts++;
+ }
+ requestMonitor.setStatus(new Status(
+ IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Process terminate failed", null)); //$NON-NLS-1$
+ requestMonitor.done();
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+ }
+
+ protected class MonitorJobStep extends InitializationShutdownStep {
+ MonitorJobStep(Direction direction) { super(direction); }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ fMonitorJob = new MonitorJob(
+ fProcess,
+ new DsfRunnable() {
+ public void run() {
+ requestMonitor.done();
+ }
+ });
+ fMonitorJob.schedule();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ if (!fMonitorJob.fExited) {
+ fMonitorJob.kill();
+ }
+ requestMonitor.done();
+ }
+ }
+
+ protected class RegisterStep extends InitializationShutdownStep {
+ RegisterStep(Direction direction) { super(direction); }
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ register(
+ new String[]{ IMIBackend.class.getName(),
+ IGDBBackend.class.getName() },
+ new Hashtable());
+
+ /*
+ * This event is not consumed by any one at present, instead it's
+ * the GDBControlInitializedDMEvent that's used to indicate that GDB
+ * back end is ready for MI commands. But we still fire the event as
+ * it does no harm and may be needed sometime.... 09/29/2008
+ */
+ getSession().dispatchEvent(
+ new BackendStateChangedEvent(getSession().getId(), getId(), IMIBackend.State.STARTED),
+ getProperties());
+
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ requestMonitor.done();
+ }
+ }
+
+ /**
+ * Monitors a system process, waiting for it to terminate, and
+ * then notifies the associated runtime process.
+ */
+ private class MonitorJob extends Job {
+ boolean fExited = false;
+ DsfRunnable fMonitorStarted;
+ Process fMonProcess;
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ synchronized(fMonProcess) {
+ getExecutor().submit(fMonitorStarted);
+ while (!fExited) {
+ try {
+ fMonProcess.waitFor();
+ fGDBExitValue = fMonProcess.exitValue();
+ } catch (InterruptedException ie) {
+ // clear interrupted state
+ Thread.interrupted();
+ } finally {
+ fExited = true;
+ getSession().dispatchEvent(
+ new BackendStateChangedEvent(getSession().getId(), getId(), IMIBackend.State.TERMINATED),
+ getProperties());
+ }
+ }
+ }
+ return Status.OK_STATUS;
+ }
+
+ MonitorJob(Process process, DsfRunnable monitorStarted) {
+ super("GDB process monitor job."); //$NON-NLS-1$
+ fMonProcess = process;
+ fMonitorStarted = monitorStarted;
+ setSystem(true);
+ }
+
+ void kill() {
+ synchronized(fMonProcess) {
+ if (!fExited) {
+ getThread().interrupt();
+ }
+ }
+ }
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java
new file mode 100644
index 00000000000..90ddaddde70
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBMemory_7_0.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.service;
+
+import java.util.Hashtable;
+
+import org.eclipse.cdt.core.IAddress;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IMemory;
+import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.MIMemory;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.model.MemoryByte;
+
+public class GDBMemory_7_0 extends MIMemory {
+
+ public GDBMemory_7_0(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleSuccess() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+ register(new String[] { MIMemory.class.getName(), IMemory.class.getName(), GDBMemory_7_0.class.getName()},
+ new Hashtable());
+
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+
+ @Override
+ protected void readMemoryBlock(IDMContext dmc, IAddress address, long offset,
+ int word_size, int count, DataRequestMonitor drm)
+ {
+ IDMContext threadOrMemoryDmc = dmc;
+
+ IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
+ if(containerCtx != null) {
+ IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class);
+
+ if (procService != null) {
+ IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx);
+ // Return any thread... let's take the first one.
+ if (execCtxs != null && execCtxs.length > 0) {
+ threadOrMemoryDmc = execCtxs[0];
+ }
+ }
+ }
+
+ super.readMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, drm);
+ }
+
+ @Override
+ protected void writeMemoryBlock(IDMContext dmc, IAddress address, long offset,
+ int word_size, int count, byte[] buffer, RequestMonitor rm)
+ {
+ IDMContext threadOrMemoryDmc = dmc;
+
+ IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
+ if(containerCtx != null) {
+ IGDBProcesses procService = getServicesTracker().getService(IGDBProcesses.class);
+
+ if (procService != null) {
+ IMIExecutionDMContext[] execCtxs = procService.getExecutionContexts(containerCtx);
+ // Return any thread... let's take the first one.
+ if (execCtxs != null && execCtxs.length > 0) {
+ threadOrMemoryDmc = execCtxs[0];
+ }
+ }
+ }
+
+ super.writeMemoryBlock(threadOrMemoryDmc, address, offset, word_size, count, buffer, rm);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java
new file mode 100644
index 00000000000..e23b06be894
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.service;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.IProcessInfo;
+import org.eclipse.cdt.core.IProcessList;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
+import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+import org.eclipse.cdt.dsf.mi.service.command.commands.CLIMonitorListProcesses;
+import org.eclipse.cdt.dsf.mi.service.command.output.CLIMonitorListProcessesInfo;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.BundleContext;
+
+
+public class GDBProcesses extends MIProcesses {
+
+ private class GDBContainerDMC extends MIContainerDMC
+ implements IMemoryDMContext
+ {
+ public GDBContainerDMC(String sessionId, IProcessDMContext processDmc, String groupId) {
+ super(sessionId, processDmc, groupId);
+ }
+ }
+
+ private IGDBControl fGdb;
+
+ // A map of pid to names. It is filled when we get all the
+ // processes that are running
+ private Map fProcessNames = new HashMap();
+
+ public GDBProcesses(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ /**
+ * This method initializes this service after our superclass's initialize()
+ * method succeeds.
+ *
+ * @param requestMonitor
+ * The call-back object to notify when this service's
+ * initialization is done.
+ */
+ private void doInitialize(RequestMonitor requestMonitor) {
+
+ fGdb = getServicesTracker().getService(IGDBControl.class);
+
+ // Register this service.
+ register(new String[] { IProcesses.class.getName(),
+ IMIProcesses.class.getName(),
+ MIProcesses.class.getName(),
+ GDBProcesses.class.getName() },
+ new Hashtable());
+
+ ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
+ IProcessDMContext procDmc = createProcessContext(commandControl.getContext(), MIProcesses.UNIQUE_GROUP_ID);
+ IContainerDMContext containerDmc = createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
+ fGdb.getInferiorProcess().setContainerContext(containerDmc);
+
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+
+ /**
+ * @return The bundle context of the plug-in to which this service belongs.
+ */
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ @Override
+ public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
+ String groupId) {
+ return new GDBContainerDMC(getSession().getId(), processDmc, groupId);
+ }
+
+ @Override
+ public void getExecutionData(IThreadDMContext dmc, DataRequestMonitor rm) {
+ if (dmc instanceof IMIProcessDMContext) {
+ String pidStr = ((IMIProcessDMContext)dmc).getProcId();
+ // In our context hierarchy we don't actually use the pid in this version, because in this version,
+ // we only debug a single process. This means we will not have a proper pid in all cases
+ // inside the context, so must find it another way. Note that this method is also called to find the name
+ // of processes to attach to, and in this case, we do have the proper pid.
+ if (pidStr == null || pidStr.length() == 0) {
+ MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
+ if (inferiorProcess != null) {
+ pidStr = inferiorProcess.getPid();
+ }
+ }
+ int pid = -1;
+ try {
+ pid = Integer.parseInt(pidStr);
+ } catch (NumberFormatException e) {
+ }
+
+ String name = fProcessNames.get(pid);
+ // If we still don't find the name in our list, return the default name of our program
+ if (name == null) {
+ IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
+ name = backend.getProgramPath().lastSegment();
+ }
+ rm.setData(new MIThreadDMData(name, pidStr));
+ rm.done();
+ } else {
+ super.getExecutionData(dmc, rm);
+ }
+ }
+
+ @Override
+ public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor rm) {
+ MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
+ if (!fGdb.isConnected() &&
+ inferiorProcess != null &&
+ inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
+
+ rm.setData(true);
+ } else {
+ rm.setData(false);
+ }
+ rm.done();
+ }
+
+ @Override
+ public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor rm) {
+ super.attachDebuggerToProcess(
+ procCtx,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ fGdb.setConnected(true);
+
+ MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
+ if (inferiorProcess != null) {
+ inferiorProcess.setPid(((IMIProcessDMContext)procCtx).getProcId());
+ }
+
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+
+ @Override
+ public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor rm) {
+ rm.setData(false); // don't turn on yet, as we need to generate events to use this properly
+ rm.done();
+ }
+
+ @Override
+ public void detachDebuggerFromProcess(IDMContext dmc, final RequestMonitor rm) {
+ super.detachDebuggerFromProcess(
+ dmc,
+ new RequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ fGdb.setConnected(false);
+
+ MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
+ if (inferiorProcess != null) {
+ inferiorProcess.setPid(null);
+ }
+
+ rm.done();
+ }
+ });
+ }
+
+ @Override
+ public void getProcessesBeingDebugged(IDMContext dmc, DataRequestMonitor rm) {
+ MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
+ if (fGdb.isConnected() &&
+ inferiorProcess != null &&
+ inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
+
+ final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
+ if (containerDmc == null) {
+ // This service version only handles a single process to debug, therefore, we can simply
+ // create the context describing this process ourselves.
+ ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+ String groupId = MIProcesses.UNIQUE_GROUP_ID;
+ IProcessDMContext procDmc = createProcessContext(controlDmc, groupId);
+ IMIContainerDMContext newContainerDmc = createContainerContext(procDmc, groupId);
+ rm.setData(new IContainerDMContext[] {newContainerDmc});
+ rm.done();
+ } else {
+ // List of threads
+ super.getProcessesBeingDebugged(dmc, rm);
+ }
+ } else {
+ rm.setData(new IDMContext[0]);
+ rm.done();
+ }
+ }
+
+ @Override
+ public void getRunningProcesses(IDMContext dmc, final DataRequestMonitor rm) {
+ final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+ IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
+ if (backend.getSessionType() == SessionType.LOCAL) {
+ IProcessList list = null;
+ try {
+ list = CCorePlugin.getDefault().getProcessList();
+ } catch (CoreException e) {
+ }
+
+ if (list == null) {
+ // If the list is null, the prompter will deal with it
+ fProcessNames.clear();
+ rm.setData(null);
+ } else {
+ fProcessNames.clear();
+ for (IProcessInfo procInfo : list.getProcessList()) {
+ fProcessNames.put(procInfo.getPid(), procInfo.getName());
+ }
+ rm.setData(makeProcessDMCs(controlDmc, list.getProcessList()));
+ }
+ rm.done();
+ } else {
+ // monitor list processes is only for remote session
+ fGdb.queueCommand(
+ new CLIMonitorListProcesses(dmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ for (IProcessInfo procInfo : getData().getProcessList()) {
+ fProcessNames.put(procInfo.getPid(), procInfo.getName());
+ }
+ rm.setData(makeProcessDMCs(controlDmc, getData().getProcessList()));
+ } else {
+ // The monitor list command is not supported.
+ // Just return an empty list and let the caller deal with it.
+ fProcessNames.clear();
+ rm.setData(new IProcessDMContext[0]);
+ }
+ rm.done();
+ }
+
+ });
+ }
+ }
+
+ private IProcessDMContext[] makeProcessDMCs(ICommandControlDMContext controlDmc, IProcessInfo[] processes) {
+ IProcessDMContext[] procDmcs = new IMIProcessDMContext[processes.length];
+ for (int i=0; i
+ *
+ * @param sessionId Session that this context belongs to.
+ * @param containerDmc The container that this context belongs to.
+ * @param threadDmc The thread context parents of this context.
+ * @param threadId GDB/MI thread identifier.
+ */
+ protected MIExecutionDMC(String sessionId, IContainerDMContext containerDmc, IThreadDMContext threadDmc, String threadId) {
+ super(sessionId,
+ containerDmc == null && threadDmc == null ? new IDMContext[0] :
+ containerDmc == null ? new IDMContext[] { threadDmc } :
+ threadDmc == null ? new IDMContext[] { containerDmc } :
+ new IDMContext[] { containerDmc, threadDmc });
+ fThreadId = threadId;
+ }
+
+ /**
+ * Returns the GDB/MI thread identifier of this context.
+ * @return
+ */
+ public int getThreadId(){
+ try {
+ return Integer.parseInt(fThreadId);
+ } catch (NumberFormatException e) {
+ }
+
+ return 0;
+ }
+
+ public String getId(){
+ return fThreadId;
+ }
+
+ @Override
+ public String toString() { return baseToString() + ".thread[" + fThreadId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId.equals(fThreadId);
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ fThreadId.hashCode(); }
+ }
+
+ /**
+ * Context representing a thread group of GDB/MI.
+ */
+ @Immutable
+ private static class MIContainerDMC extends AbstractDMContext
+ implements IMIContainerDMContext
+ {
+ /**
+ * String ID that is used to identify the thread group in the GDB/MI protocol.
+ */
+ private final String fId;
+
+ /**
+ * Constructor for the context. It should not be called directly by clients.
+ * Instead clients should call {@link IMIProcesses#createContainerContext
+ * to create instances of this context based on the group name.
+ *
+ * @param sessionId Session that this context belongs to.
+ * @param processDmc The process context that is the parent of this context.
+ * @param groupId GDB/MI thread group identifier.
+ */
+ public MIContainerDMC(String sessionId, IProcessDMContext processDmc, String groupId) {
+ super(sessionId, processDmc == null ? new IDMContext[0] : new IDMContext[] { processDmc });
+ fId = groupId;
+ }
+
+ /**
+ * Returns the GDB/MI thread group identifier of this context.
+ */
+ public String getGroupId(){ return fId; }
+
+ @Override
+ public String toString() { return baseToString() + ".threadGroup[" + fId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.baseEquals(obj) &&
+ (((MIContainerDMC)obj).fId == null ? fId == null : ((MIContainerDMC)obj).fId.equals(fId));
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); }
+ }
+
+ private class GDBContainerDMC extends MIContainerDMC
+ implements IMemoryDMContext
+ {
+ public GDBContainerDMC(String sessionId, IProcessDMContext processDmc, String groupId) {
+ super(sessionId, processDmc, groupId);
+ }
+ }
+
+ /**
+ * Context representing a thread.
+ */
+ @Immutable
+ private static class MIThreadDMC extends AbstractDMContext
+ implements IThreadDMContext
+ {
+ /**
+ * ID used by GDB to refer to threads.
+ */
+ private final String fId;
+
+ /**
+ * Constructor for the context. It should not be called directly by clients.
+ * Instead clients should call {@link IMIProcesses#createThreadContext}
+ * to create instances of this context based on the thread ID.
+ *
+ *
+ * @param sessionId Session that this context belongs to.
+ * @param processDmc The process that this thread belongs to.
+ * @param id thread identifier.
+ */
+ public MIThreadDMC(String sessionId, IProcessDMContext processDmc, String id) {
+ super(sessionId, processDmc == null ? new IDMContext[0] : new IDMContext[] { processDmc });
+ fId = id;
+ }
+
+ /**
+ * Returns the thread identifier of this context.
+ * @return
+ */
+ public String getId(){ return fId; }
+
+ @Override
+ public String toString() { return baseToString() + ".OSthread[" + fId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.baseEquals(obj) &&
+ (((MIThreadDMC)obj).fId == null ? fId == null : ((MIThreadDMC)obj).fId.equals(fId));
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); }
+ }
+
+ @Immutable
+ private static class MIProcessDMC extends AbstractDMContext
+ implements IMIProcessDMContext
+ {
+ /**
+ * ID given by the OS.
+ */
+ private final String fId;
+
+ /**
+ * Constructor for the context. It should not be called directly by clients.
+ * Instead clients should call {@link IMIProcesses#createProcessContext}
+ * to create instances of this context based on the PID.
+ *
+ *
+ * @param sessionId Session that this context belongs to.
+ * @param controlDmc The control context parent of this process.
+ * @param id process identifier.
+ */
+ public MIProcessDMC(String sessionId, ICommandControlDMContext controlDmc, String id) {
+ super(sessionId, controlDmc == null ? new IDMContext[0] : new IDMContext[] { controlDmc });
+ fId = id;
+ }
+
+ public String getProcId() { return fId; }
+
+ @Override
+ public String toString() { return baseToString() + ".proc[" + fId + "]"; } //$NON-NLS-1$ //$NON-NLS-2$
+
+ @Override
+ public boolean equals(Object obj) {
+ return super.baseEquals(obj) &&
+ (((MIProcessDMC)obj).fId == null ? fId == null : ((MIProcessDMC)obj).fId.equals(fId));
+ }
+
+ @Override
+ public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); }
+ }
+
+ /**
+ * The data of a corresponding thread or process.
+ */
+ @Immutable
+ protected static class MIThreadDMData implements IThreadDMData {
+ final String fName;
+ final String fId;
+
+ public MIThreadDMData(String name, String id) {
+ fName = name;
+ fId = id;
+ }
+
+ public String getId() { return fId; }
+ public String getName() { return fName; }
+ public boolean isDebuggerAttached() {
+ return true;
+ }
+ }
+
+ /**
+ * Event indicating that an container (debugged process) has started. This event
+ * implements the {@link IStartedMDEvent} from the IRunControl service.
+ */
+ public static class ContainerStartedDMEvent extends AbstractDMEvent
+ implements IStartedDMEvent
+ {
+ public ContainerStartedDMEvent(IContainerDMContext context) {
+ super(context);
+ }
+ }
+
+ /**
+ * Event indicating that an container is no longer being debugged. This event
+ * implements the {@link IExitedMDEvent} from the IRunControl service.
+ */
+ public static class ContainerExitedDMEvent extends AbstractDMEvent
+ implements IExitedDMEvent
+ {
+ public ContainerExitedDMEvent(IContainerDMContext context) {
+ super(context);
+ }
+ }
+
+ /**
+ * A map of thread id to thread group id. We use this to find out to which threadGroup a thread belongs.
+ */
+ private Map fThreadToGroupMap = new HashMap();
+
+ private IGDBControl fCommandControl;
+
+ // A cache for commands about the threadGroups
+ private CommandCache fContainerCommandCache;
+
+ //A cache for commands about the threads
+ private CommandCache fThreadCommandCache;
+
+ // A map of process id to process names. It is filled when we get all the processes that are running
+ private Map fProcessNames = new HashMap();
+
+ private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$
+
+ public GDBProcesses_7_0(DsfSession session) {
+ super(session);
+ }
+
+ /**
+ * This method initializes this service.
+ *
+ * @param requestMonitor
+ * The request monitor indicating the operation is finished
+ */
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ /**
+ * This method initializes this service after our superclass's initialize()
+ * method succeeds.
+ *
+ * @param requestMonitor
+ * The call-back object to notify when this service's
+ * initialization is done.
+ */
+ private void doInitialize(RequestMonitor requestMonitor) {
+
+ fCommandControl = getServicesTracker().getService(IGDBControl.class);
+ fContainerCommandCache = new CommandCache(getSession(), fCommandControl);
+ fContainerCommandCache.setContextAvailable(fCommandControl.getContext(), true);
+ fThreadCommandCache = new CommandCache(getSession(), fCommandControl);
+ fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
+
+ getSession().addServiceEventListener(this, null);
+ fCommandControl.addEventListener(this);
+
+ // Register this service.
+ register(new String[] { IProcesses.class.getName(),
+ IMIProcesses.class.getName(),
+ IGDBProcesses.class.getName(),
+ GDBProcesses_7_0.class.getName() },
+ new Hashtable());
+
+ requestMonitor.done();
+ }
+
+
+ /**
+ * This method shuts down this service. It unregisters the service, stops
+ * receiving service events, and calls the superclass shutdown() method to
+ * finish the shutdown process.
+ *
+ * @return void
+ */
+ @Override
+ public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ getSession().removeServiceEventListener(this);
+ fCommandControl.removeEventListener(this);
+ super.shutdown(requestMonitor);
+ }
+
+ /**
+ * @return The bundle context of the plug-in to which this service belongs.
+ */
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ public IThreadDMContext createThreadContext(IProcessDMContext processDmc, String threadId) {
+ return new MIThreadDMC(getSession().getId(), processDmc, threadId);
+ }
+
+ public IProcessDMContext createProcessContext(ICommandControlDMContext controlDmc, String pid) {
+ return new MIProcessDMC(getSession().getId(), controlDmc, pid);
+ }
+
+ public IMIExecutionDMContext createExecutionContext(IContainerDMContext containerDmc,
+ IThreadDMContext threadDmc,
+ String threadId) {
+ return new MIExecutionDMC(getSession().getId(), containerDmc, threadDmc, threadId);
+ }
+
+ public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
+ String groupId) {
+ return new GDBContainerDMC(getSession().getId(), processDmc, groupId);
+ }
+
+ public IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId) {
+ String groupId = fThreadToGroupMap.get(threadId);
+ IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
+ return createContainerContext(processDmc, groupId);
+ }
+
+ public IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc) {
+ String groupId = containerDmc.getGroupId();
+ List execDmcList = new ArrayList();
+ Iterator> iterator = fThreadToGroupMap.entrySet().iterator();
+ while (iterator.hasNext()){
+ Map.Entry entry = iterator.next();
+ if (entry.getValue().equals(groupId)) {
+ String threadId = entry.getKey();
+ IProcessDMContext procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
+ IMIExecutionDMContext execDmc = createExecutionContext(containerDmc,
+ createThreadContext(procDmc, threadId),
+ threadId);
+ execDmcList.add(execDmc);
+ }
+ }
+ return execDmcList.toArray(new IMIExecutionDMContext[0]);
+ }
+
+ /**
+ * This method obtains the model data for a given IThreadDMContext object
+ * which can represent a thread or a process.
+ *
+ * @param dmc
+ * The context for which we are requesting the data
+ * @param rm
+ * The request monitor that will contain the requested data
+ */
+ @SuppressWarnings("unchecked")
+ public void getModelData(IDMContext dmc, DataRequestMonitor> rm) {
+ if (dmc instanceof IThreadDMContext) {
+ getExecutionData((IThreadDMContext) dmc,
+ (DataRequestMonitor) rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor rm) {
+ if (dmc instanceof IMIProcessDMContext) {
+ String id = ((IMIProcessDMContext)dmc).getProcId();
+ String name = fProcessNames.get(id);
+ if (name == null) name = "Unknown name"; //$NON-NLS-1$
+ rm.setData(new MIThreadDMData(name, id));
+ rm.done();
+ } else if (dmc instanceof MIThreadDMC) {
+ final MIThreadDMC threadDmc = (MIThreadDMC)dmc;
+
+ ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+ fThreadCommandCache.execute(new MIThreadInfo(controlDmc, threadDmc.getId()),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ IThreadDMData threadData = null;
+ if (getData().getThreadList().length != 0) {
+ MIThread thread = getData().getThreadList()[0];
+ if (thread.getThreadId().equals(threadDmc.getId())) {
+ threadData = new MIThreadDMData("", thread.getOsId()); //$NON-NLS-1$
+ }
+ }
+
+ if (threadData != null) {
+ rm.setData(threadData);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Could not get thread info", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void getDebuggingContext(IThreadDMContext dmc, DataRequestMonitor rm) {
+ if (dmc instanceof MIProcessDMC) {
+ MIProcessDMC procDmc = (MIProcessDMC)dmc;
+ rm.setData(createContainerContext(procDmc, procDmc.getProcId()));
+ } else if (dmc instanceof MIThreadDMC) {
+ MIThreadDMC threadDmc = (MIThreadDMC)dmc;
+ IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class);
+ IMIContainerDMContext containerDmc = createContainerContext(procDmc, procDmc.getProcId());
+ rm.setData(createExecutionContext(containerDmc, threadDmc, threadDmc.getId()));
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid thread context.", null)); //$NON-NLS-1$
+ }
+
+ rm.done();
+ }
+
+ public void isDebuggerAttachSupported(IDMContext dmc, DataRequestMonitor rm) {
+ IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
+ rm.setData(backend.getIsAttachSession());
+ rm.done();
+ }
+
+ public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor rm) {
+ if (procCtx instanceof IMIProcessDMContext) {
+ ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
+ fCommandControl.queueCommand(
+ new MITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ fCommandControl.setConnected(true);
+
+ IMIContainerDMContext containerDmc = createContainerContext(procCtx,
+ ((IMIProcessDMContext)procCtx).getProcId());
+ rm.setData(containerDmc);
+ rm.done();
+ }
+ });
+
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void canDetachDebuggerFromProcess(IDMContext dmc, DataRequestMonitor rm) {
+ IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
+ rm.setData(backend.getIsAttachSession() && fCommandControl.isConnected());
+ rm.done();
+ }
+
+ public void detachDebuggerFromProcess(final IDMContext dmc, final RequestMonitor rm) {
+ ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+ IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc, IMIProcessDMContext.class);
+
+ if (controlDmc != null && procDmc != null) {
+ fCommandControl.queueCommand(
+ new MITargetDetach(controlDmc, procDmc.getProcId()),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // only if it is the last detach
+ fCommandControl.setConnected(false);
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ public void canTerminate(IThreadDMContext thread, DataRequestMonitor rm) {
+ rm.setData(true);
+ rm.done();
+ }
+
+ public void isDebugNewProcessSupported(IDMContext dmc, DataRequestMonitor rm) {
+ rm.setData(false);
+ rm.done();
+ }
+
+ public void debugNewProcess(IDMContext dmc, String file,
+ Map attributes, DataRequestMonitor rm) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
+ NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor rm) {
+// MIInferiorProcess inferiorProcess = fCommandControl.getInferiorProcess();
+// if (fCommandControl.isConnected() &&
+// inferiorProcess != null &&
+// inferiorProcess.getState() != MIInferiorProcess.State.TERMINATED) {
+
+ final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+ final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
+ if (containerDmc != null) {
+ fThreadCommandCache.execute(
+ new MIListThreadGroups(controlDmc, containerDmc.getGroupId()),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(makeExecutionDMCs(containerDmc, getData().getThreadInfo().getThreadList()));
+ rm.done();
+ }
+ });
+ } else {
+ fContainerCommandCache.execute(
+ new MIListThreadGroups(controlDmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(makeContainerDMCs(controlDmc, getData().getGroupList()));
+ rm.done();
+ }
+ });
+ }
+// } else {
+// rm.setData(new IDMContext[0]);
+// rm.done();
+// }
+ }
+
+ private IExecutionDMContext[] makeExecutionDMCs(IContainerDMContext containerDmc, MIThread[] threadInfos) {
+ final IProcessDMContext procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
+
+ if (threadInfos.length == 0) {
+ // Main thread always exist even if it is not reported by GDB.
+ // So create thread-id = 0 when no thread is reported.
+ // This hack is necessary to prevent AbstractMIControl from issuing a thread-select
+ // because it doesn't work if the application was not compiled with pthread.
+ return new IMIExecutionDMContext[]{createExecutionContext(containerDmc,
+ createThreadContext(procDmc, FAKE_THREAD_ID),
+ FAKE_THREAD_ID)};
+ } else {
+ IExecutionDMContext[] executionDmcs = new IMIExecutionDMContext[threadInfos.length];
+ for (int i = 0; i < threadInfos.length; i++) {
+ String threadId = threadInfos[i].getThreadId();
+ executionDmcs[i] = createExecutionContext(containerDmc,
+ createThreadContext(procDmc, threadId),
+ threadId);
+ }
+ return executionDmcs;
+ }
+ }
+
+ private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) {
+ IProcessDMContext[] procDmcs = makeProcessDMCs(controlDmc, groups);
+
+ IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length];
+ for (int i = 0; i < procDmcs.length; i++) {
+ String groupId = groups[i].getGroupId();
+ IProcessDMContext procDmc = createProcessContext(controlDmc, groupId);
+ containerDmcs[i] = createContainerContext(procDmc, groupId);
+ }
+ return containerDmcs;
+ }
+
+ public void getRunningProcesses(IDMContext dmc, final DataRequestMonitor rm) {
+ final ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
+
+ if (controlDmc != null) {
+ // Don't cache this command since the list can change at any time.
+ fCommandControl.queueCommand(
+ new MIListThreadGroups(controlDmc, true),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ for (IThreadGroupInfo groupInfo : getData().getGroupList()) {
+ fProcessNames.put(groupInfo.getPid(), groupInfo.getName());
+ }
+ rm.setData(makeProcessDMCs(controlDmc, getData().getGroupList()));
+ } else {
+ rm.setData(new IProcessDMContext[0]);
+ }
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ }
+
+ private IProcessDMContext[] makeProcessDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] processes) {
+ IProcessDMContext[] procDmcs = new IMIProcessDMContext[processes.length];
+ for (int i=0; i rm) {
+ rm.setData(false);
+ rm.done();
+ }
+
+ public void runNewProcess(IDMContext dmc, String file,
+ Map attributes, DataRequestMonitor rm) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
+ NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ public void terminate(IThreadDMContext thread, RequestMonitor rm) {
+ if (thread instanceof IMIProcessDMContext) {
+ fCommandControl.terminate(rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIThreadGroupCreatedEvent e) {
+ IProcessDMContext procDmc = e.getDMContext();
+ IMIContainerDMContext containerDmc = e.getGroupId() != null ? createContainerContext(procDmc, e.getGroupId()) : null;
+ getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIThreadGroupExitedEvent e) {
+ IProcessDMContext procDmc = e.getDMContext();
+ IMIContainerDMContext containerDmc = e.getGroupId() != null ? createContainerContext(procDmc, e.getGroupId()) : null;
+ getSession().dispatchEvent(new ContainerExitedDMEvent(containerDmc), getProperties());
+
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IResumedDMEvent e) {
+ if (e instanceof IContainerResumedDMEvent) {
+ // This will happen in all-stop mode
+ fContainerCommandCache.setContextAvailable(e.getDMContext(), false);
+ fThreadCommandCache.setContextAvailable(e.getDMContext(), false);
+ } else {
+ // This will happen in non-stop mode
+ // Keep target available for Container commands
+ }
+ }
+
+
+ @DsfServiceEventHandler
+ public void eventDispatched(ISuspendedDMEvent e) {
+ if (e instanceof IContainerSuspendedDMEvent) {
+ // This will happen in all-stop mode
+ fContainerCommandCache.setContextAvailable(e.getDMContext(), true);
+ fThreadCommandCache.setContextAvailable(e.getDMContext(), true);
+ } else {
+ // This will happen in non-stop mode
+ }
+ }
+
+ // Event handler when a thread or threadGroup starts
+ @DsfServiceEventHandler
+ public void eventDispatched(IStartedDMEvent e) {
+ if (e instanceof ContainerStartedDMEvent) {
+ fContainerCommandCache.reset();
+ } else {
+ fThreadCommandCache.reset();
+ }
+ }
+
+ // Event handler when a thread or a threadGroup exits
+ @DsfServiceEventHandler
+ public void eventDispatched(IExitedDMEvent e) {
+ if (e instanceof ContainerExitedDMEvent) {
+ fContainerCommandCache.reset();
+ } else {
+ fThreadCommandCache.reset();
+ }
+ }
+
+ public void flushCache(IDMContext context) {
+ fContainerCommandCache.reset(context);
+ fThreadCommandCache.reset(context);
+ }
+
+ /*
+ * Catch =thread-created/exited and =thread-group-exited events to update our
+ * groupId to threadId map.
+ */
+ public void eventReceived(Object output) {
+ for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
+ if (oobr instanceof MINotifyAsyncOutput) {
+ MINotifyAsyncOutput exec = (MINotifyAsyncOutput) oobr;
+ String miEvent = exec.getAsyncClass();
+ if ("thread-created".equals(miEvent) || "thread-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
+ String threadId = null;
+ String groupId = null;
+
+ MIResult[] results = exec.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ MIValue val = results[i].getMIValue();
+ if (var.equals("group-id")) { //$NON-NLS-1$
+ if (val instanceof MIConst) {
+ groupId = ((MIConst) val).getString();
+ }
+ } else if (var.equals("id")) { //$NON-NLS-1$
+ if (val instanceof MIConst) {
+ threadId = ((MIConst) val).getString();
+ }
+ }
+ }
+
+ // Until GDB is officially supporting multi-process, we may not get
+ // a groupId. In this case, we are running single process and we'll
+ // need its groupId
+ if (groupId == null) {
+ groupId = MIProcesses.UNIQUE_GROUP_ID;
+ }
+
+ if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
+ // Update the thread to groupId map with the new groupId
+ fThreadToGroupMap.put(threadId, groupId);
+ } else {
+ fThreadToGroupMap.remove(threadId);
+ }
+ } else if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
+
+ String groupId = null;
+
+ MIResult[] results = exec.getMIResults();
+ for (int i = 0; i < results.length; i++) {
+ String var = results[i].getVariable();
+ MIValue val = results[i].getMIValue();
+ if (var.equals("id")) { //$NON-NLS-1$
+ if (val instanceof MIConst) {
+ groupId = ((MIConst) val).getString().trim();
+ }
+ }
+ }
+
+ if (groupId != null) {
+ if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$
+ // Remove any entries for that group from our thread to group map
+ // When detaching from a group, we won't have received any thread-exited event
+ // but we don't want to keep those entries.
+ if (fThreadToGroupMap.containsValue(groupId)) {
+ Iterator> iterator = fThreadToGroupMap.entrySet().iterator();
+ while (iterator.hasNext()){
+ if (iterator.next().getValue().equals(groupId)) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java
new file mode 100644
index 00000000000..609940e1207
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson AB - Modified for additional functionality
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.service;
+
+
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIRunControl;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+public class GDBRunControl extends MIRunControl {
+ private IGDBBackend fGdb;
+ private IMIProcesses fProcService;
+
+ // Record list of execution contexts
+ private IExecutionDMContext[] fOldExecutionCtxts;
+
+
+ public GDBRunControl(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleSuccess() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+
+ fGdb = getServicesTracker().getService(IGDBBackend.class);
+ fProcService = getServicesTracker().getService(IMIProcesses.class);
+
+ register(new String[]{IRunControl.class.getName(),
+ MIRunControl.class.getName(),
+ GDBRunControl.class.getName()}, new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+
+ @Override
+ public IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, int threadId) {
+ IProcessDMContext procDmc = DMContexts.getAncestorOfType(container, IProcessDMContext.class);
+
+ IThreadDMContext threadDmc = null;
+ if (procDmc != null) {
+ // For now, reuse the threadId as the OSThreadId
+ threadDmc = fProcService.createThreadContext(procDmc, Integer.toString(threadId));
+ }
+
+ return fProcService.createExecutionContext(container, threadDmc, Integer.toString(threadId));
+ }
+
+ @Override
+ public void suspend(IExecutionDMContext context, final RequestMonitor rm){
+ canSuspend(
+ context,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (getData()) {
+ fGdb.interrupt();
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+
+
+ /*
+ * This is a HACK. Remove this method when GDB starts to account exited threads id in -thread-list-id command.
+ * Exited threads are reported in -thread-list-id command even after an exit event is raised by GDB
+ * Hence, this method needs a special handling in case of GDB.
+ * Raises ExitEvent when a thread really exits from the system. This is done by comparing the execution contexts list
+ * See bug 200615 for details.
+ */
+ @Override
+ public void getExecutionContexts(IContainerDMContext containerDmc, final DataRequestMonitor rm) {
+ fProcService.getProcessesBeingDebugged(
+ containerDmc,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (getData() instanceof IExecutionDMContext[]) {
+ IExecutionDMContext[] execDmcs = (IExecutionDMContext[])getData();
+ raiseExitEvents(execDmcs);
+ fOldExecutionCtxts = execDmcs;
+ rm.setData(fOldExecutionCtxts);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid contexts", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+
+ private void raiseExitEvents(IExecutionDMContext[] ctxts){
+ if(ctxts == null || fOldExecutionCtxts == null)
+ return;
+ List list = Arrays.asList(ctxts);
+ List oldThreadList = Arrays.asList(fOldExecutionCtxts);
+ Iterator iterator = oldThreadList.iterator();
+ while(iterator.hasNext()){
+ IExecutionDMContext ctxt = iterator.next();
+ if(! list.contains(ctxt)){
+ IContainerDMContext containerDmc = DMContexts.getAncestorOfType(ctxt, IContainerDMContext.class);
+ MIEvent> e = new MIThreadExitEvent(containerDmc, Integer.toString(((IMIExecutionDMContext)ctxt).getThreadId()));
+ // Dispatch DsfMIThreadExitEvent
+ getSession().dispatchEvent(e, getProperties());
+ }
+ }
+ }
+
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java
new file mode 100644
index 00000000000..ee33e80b63b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for additional functionality
+ * Ericsson - Version 7.0
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.service;
+
+
+import java.util.Hashtable;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIRunControl;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+public class GDBRunControl_7_0 extends MIRunControl {
+ private IGDBBackend fGdb;
+ private IMIProcesses fProcService;
+
+ public GDBRunControl_7_0(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ public void handleSuccess() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+
+ fGdb = getServicesTracker().getService(IGDBBackend.class);
+ fProcService = getServicesTracker().getService(IMIProcesses.class);
+
+ register(new String[]{IRunControl.class.getName(), MIRunControl.class.getName()},
+ new Hashtable());
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+
+ @Override
+ public IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, int threadId) {
+ IProcessDMContext procDmc = DMContexts.getAncestorOfType(container, IProcessDMContext.class);
+
+ IThreadDMContext threadDmc = null;
+ if (procDmc != null) {
+ // For now, reuse the threadId as the OSThreadId
+ threadDmc = fProcService.createThreadContext(procDmc, Integer.toString(threadId));
+ }
+
+ return fProcService.createExecutionContext(container, threadDmc, Integer.toString(threadId));
+ }
+
+ @Override
+ public void suspend(IExecutionDMContext context, final RequestMonitor rm){
+ canSuspend(
+ context,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (getData()) {
+ fGdb.interrupt();
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Context cannot be suspended.", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+
+ @Override
+ public void getExecutionContexts(IContainerDMContext containerDmc, final DataRequestMonitor rm) {
+ fProcService.getProcessesBeingDebugged(
+ containerDmc,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (getData() instanceof IExecutionDMContext[]) {
+ IExecutionDMContext[] execDmcs = (IExecutionDMContext[])getData();
+ rm.setData(execDmcs);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid contexts", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java
new file mode 100644
index 00000000000..8e728b2de03
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java
@@ -0,0 +1,781 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson AB - Modified for handling of multiple threads
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.gdb.service;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.datamodel.IDMEvent;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIRunControl;
+import org.eclipse.cdt.dsf.mi.service.MIStack;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecFinish;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecInterrupt;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNext;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecNextInstruction;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStep;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecStepInstruction;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecUntil;
+import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIErrorEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIRunningEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MISharedLibEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MISignalEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MISteppingRangeEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIStoppedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadCreatedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadExitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+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.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Implementation note: This class implements event handlers for the events that
+ * are generated by this service itself. When the event is dispatched, these
+ * handlers will be called first, before any of the clients. These handlers
+ * update the service's internal state information to make them consistent with
+ * the events being issued. Doing this in the handlers as opposed to when the
+ * events are generated, guarantees that the state of the service will always be
+ * consistent with the events. The purpose of this pattern is to allow clients
+ * that listen to service events and track service state, to be perfectly in
+ * sync with the service state.
+ * @since 1.1
+ */
+public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunControl, ICachingService
+{
+ @Immutable
+ private static class ExecutionData implements IExecutionDMData {
+ private final StateChangeReason fReason;
+ ExecutionData(StateChangeReason reason) {
+ fReason = reason;
+ }
+ public StateChangeReason getStateChangeReason() { return fReason; }
+ }
+
+ /**
+ * Base class for events generated by the MI Run Control service. Most events
+ * generated by the MI Run Control service are directly caused by some MI event.
+ * Other services may need access to the extended MI data carried in the event.
+ *
+ * @param DMC that this event refers to
+ * @param MIInfo object that is the direct cause of this event
+ * @see MIRunControl
+ */
+ @Immutable
+ private static class RunControlEvent> extends AbstractDMEvent
+ implements IDMEvent, IMIDMEvent
+ {
+ final private T fMIInfo;
+ public RunControlEvent(V dmc, T miInfo) {
+ super(dmc);
+ fMIInfo = miInfo;
+ }
+
+ public T getMIEvent() { return fMIInfo; }
+ }
+
+ /**
+ * Indicates that the given thread has been suspended.
+ */
+ @Immutable
+ private static class SuspendedEvent extends RunControlEvent
+ implements ISuspendedDMEvent
+ {
+ SuspendedEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo) {
+ super(ctx, miInfo);
+ }
+
+ public StateChangeReason getReason() {
+ if (getMIEvent() instanceof MIBreakpointHitEvent) {
+ return StateChangeReason.BREAKPOINT;
+ } else if (getMIEvent() instanceof MISteppingRangeEvent) {
+ return StateChangeReason.STEP;
+ } else if (getMIEvent() instanceof MISharedLibEvent) {
+ return StateChangeReason.SHAREDLIB;
+ }else if (getMIEvent() instanceof MISignalEvent) {
+ return StateChangeReason.SIGNAL;
+ }else if (getMIEvent() instanceof MIWatchpointTriggerEvent) {
+ return StateChangeReason.WATCHPOINT;
+ }else if (getMIEvent() instanceof MIErrorEvent) {
+ return StateChangeReason.ERROR;
+ }else {
+ return StateChangeReason.USER_REQUEST;
+ }
+ }
+ }
+
+ @Immutable
+ private static class ResumedEvent extends RunControlEvent
+ implements IResumedDMEvent
+ {
+ ResumedEvent(IExecutionDMContext ctx, MIRunningEvent miInfo) {
+ super(ctx, miInfo);
+ }
+
+ public StateChangeReason getReason() {
+ switch(getMIEvent().getType()) {
+ case MIRunningEvent.CONTINUE:
+ return StateChangeReason.USER_REQUEST;
+ case MIRunningEvent.NEXT:
+ case MIRunningEvent.NEXTI:
+ return StateChangeReason.STEP;
+ case MIRunningEvent.STEP:
+ case MIRunningEvent.STEPI:
+ return StateChangeReason.STEP;
+ case MIRunningEvent.FINISH:
+ return StateChangeReason.STEP;
+ case MIRunningEvent.UNTIL:
+ case MIRunningEvent.RETURN:
+ break;
+ }
+ return StateChangeReason.UNKNOWN;
+ }
+ }
+
+ @Immutable
+ private static class StartedDMEvent extends RunControlEvent
+ implements IStartedDMEvent
+ {
+ StartedDMEvent(IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) {
+ super(executionDmc, miInfo);
+ }
+ }
+
+ @Immutable
+ private static class ExitedDMEvent extends RunControlEvent
+ implements IExitedDMEvent
+ {
+ ExitedDMEvent(IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) {
+ super(executionDmc, miInfo);
+ }
+ }
+
+ protected class MIThreadRunState {
+ // State flags
+ boolean fSuspended = false;
+ boolean fResumePending = false;
+ boolean fStepping = false;
+ StateChangeReason fStateChangeReason;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // MIRunControlNS
+ ///////////////////////////////////////////////////////////////////////////
+
+ private ICommandControlService fConnection;
+
+ private boolean fTerminated = false;
+
+ // ThreadStates indexed by the execution context
+ protected Map fThreadRunStates = new HashMap();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Initialization and shutdown
+ ///////////////////////////////////////////////////////////////////////////
+
+ public GDBRunControl_7_0_NS(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ public void initialize(final RequestMonitor rm) {
+ super.initialize(new RequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(rm);
+ }
+ });
+ }
+
+ private void doInitialize(final RequestMonitor rm) {
+ register(new String[]{IRunControl.class.getName()}, new Hashtable());
+ fConnection = getServicesTracker().getService(ICommandControlService.class);
+ getSession().addServiceEventListener(this, null);
+ rm.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor rm) {
+ unregister();
+ getSession().removeServiceEventListener(this);
+ super.shutdown(rm);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // AbstractDsfService
+ ///////////////////////////////////////////////////////////////////////////
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IDMService
+ ///////////////////////////////////////////////////////////////////////////
+
+ @SuppressWarnings("unchecked")
+ public void getModelData(IDMContext dmc, DataRequestMonitor> rm) {
+ if (dmc instanceof IExecutionDMContext) {
+ getExecutionData((IExecutionDMContext) dmc, (DataRequestMonitor) rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IRunControl
+ ///////////////////////////////////////////////////////////////////////////
+
+ // ------------------------------------------------------------------------
+ // Suspend
+ // ------------------------------------------------------------------------
+
+ public boolean isSuspended(IExecutionDMContext context) {
+
+ // Thread case
+ if (context instanceof IMIExecutionDMContext) {
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ return (threadState == null) ? false : !fTerminated && threadState.fSuspended;
+ }
+
+ // Container case
+ if (context instanceof IContainerDMContext) {
+ boolean isSuspended = false;
+ for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
+ if (DMContexts.isAncestorOf(threadContext, context)) {
+ isSuspended |= isSuspended(threadContext);
+ }
+ }
+ return isSuspended;
+ }
+
+ // Default case
+ return false;
+ }
+
+ public void canSuspend(IExecutionDMContext context, DataRequestMonitor rm) {
+
+ // Thread case
+ if (context instanceof IMIExecutionDMContext) {
+ rm.setData(doCanSuspend(context));
+ rm.done();
+ return;
+ }
+
+ // Container case
+ if (context instanceof IContainerDMContext) {
+ boolean canSuspend = false;
+ for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
+ if (DMContexts.isAncestorOf(threadContext, context)) {
+ canSuspend |= doCanSuspend(threadContext);
+ }
+ }
+ rm.setData(canSuspend);
+ rm.done();
+ return;
+ }
+
+ // Default case
+ rm.setData(false);
+ rm.done();
+ }
+
+ private boolean doCanSuspend(IExecutionDMContext context) {
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ return (threadState == null) ? false : !fTerminated && !threadState.fSuspended;
+ }
+
+ public void suspend(IExecutionDMContext context, final RequestMonitor rm) {
+
+ assert context != null;
+
+ // Thread case
+ IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
+ if (thread != null) {
+ doSuspendThread(thread, rm);
+ return;
+ }
+
+ // Container case
+ IContainerDMContext container = DMContexts.getAncestorOfType(context, IContainerDMContext.class);
+ if (container != null) {
+ doSuspendContainer(container, rm);
+ return;
+ }
+
+ // Default case
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ private void doSuspendThread(IMIExecutionDMContext context, final RequestMonitor rm) {
+
+ if (!doCanSuspend(context)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ "Given context: " + context + ", is already suspended.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ MIExecInterrupt cmd = new MIExecInterrupt(context);
+ fConnection.queueCommand(cmd, new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ private void doSuspendContainer(IContainerDMContext context, final RequestMonitor rm) {
+ MIExecInterrupt cmd = new MIExecInterrupt(context, true);
+ fConnection.queueCommand(cmd, new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ // ------------------------------------------------------------------------
+ // Resume
+ // ------------------------------------------------------------------------
+
+ public void canResume(IExecutionDMContext context, DataRequestMonitor rm) {
+
+ // Thread case
+ if (context instanceof IMIExecutionDMContext) {
+ rm.setData(doCanResume(context));
+ rm.done();
+ return;
+ }
+
+ // Container case
+ if (context instanceof IContainerDMContext) {
+ boolean canSuspend = false;
+ for (IMIExecutionDMContext threadContext : fThreadRunStates.keySet()) {
+ if (DMContexts.isAncestorOf(threadContext, context)) {
+ canSuspend |= doCanResume(threadContext);
+ }
+ }
+ rm.setData(canSuspend);
+ rm.done();
+ return;
+ }
+
+ // Default case
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ private boolean doCanResume(IExecutionDMContext context) {
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ return (threadState == null) ? false : !fTerminated && threadState.fSuspended && !threadState.fResumePending;
+ }
+
+ public void resume(IExecutionDMContext context, final RequestMonitor rm) {
+
+ assert context != null;
+
+ // Thread case
+ IMIExecutionDMContext thread = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
+ if (thread != null) {
+ doResumeThread(thread, rm);
+ return;
+ }
+
+ // Container case
+ IContainerDMContext container = DMContexts.getAncestorOfType(context, IContainerDMContext.class);
+ if (container != null) {
+ doResumeContainer(container, rm);
+ return;
+ }
+
+ // Default case
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Invalid context type.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ private void doResumeThread(IMIExecutionDMContext context, final RequestMonitor rm) {
+
+ if (!doCanResume(context)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Given context: " + context + ", is already running.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ if (threadState == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+ threadState.fResumePending = true;
+
+ MIExecContinue cmd = new MIExecContinue(context);
+ fConnection.queueCommand(cmd, new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ private void doResumeContainer(IContainerDMContext context, final RequestMonitor rm) {
+ MIExecContinue cmd = new MIExecContinue(context, true);
+ fConnection.queueCommand(cmd, new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ // ------------------------------------------------------------------------
+ // Step
+ // ------------------------------------------------------------------------
+
+ public boolean isStepping(IExecutionDMContext context) {
+
+ // If it's a thread, just look it up
+ if (context instanceof IMIExecutionDMContext) {
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ return (threadState == null) ? false : !fTerminated && threadState.fStepping;
+ }
+
+ // Default case
+ return false;
+ }
+
+ public void canStep(IExecutionDMContext context, StepType stepType, DataRequestMonitor rm) {
+
+ // If it's a thread, just look it up
+ if (context instanceof IMIExecutionDMContext) {
+ canResume(context, rm);
+ return;
+ }
+
+ // If it's a container, then we don't want to step it
+ rm.setData(false);
+ rm.done();
+ }
+
+ public void step(IExecutionDMContext context, StepType stepType, final RequestMonitor rm) {
+
+ assert context != null;
+
+ IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ if (!doCanResume(context)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Cannot resume context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ if (threadState == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Given context: " + context + " can't be found.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ threadState.fResumePending = true;
+ threadState.fStepping = true;
+
+ switch (stepType) {
+ case STEP_INTO:
+ fConnection.queueCommand(new MIExecStep(dmc),
+ new DataRequestMonitor(getExecutor(), rm));
+ break;
+ case STEP_OVER:
+ fConnection.queueCommand(new MIExecNext(dmc),
+ new DataRequestMonitor(getExecutor(), rm));
+ break;
+ case STEP_RETURN:
+ // The -exec-finish command operates on the selected stack frame, but here we always
+ // want it to operate on the stop stack frame. So we manually create a top-frame
+ // context to use with the MI command.
+ // We get a local instance of the stack service because the stack service can be shut
+ // down before the run control service is shut down. So it is possible for the
+ // getService() request below to return null.
+ MIStack stackService = getServicesTracker().getService(MIStack.class);
+ if (stackService != null) {
+ IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
+ fConnection.queueCommand(new MIExecFinish(topFrameDmc),
+ new DataRequestMonitor(getExecutor(), rm));
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ "Cannot create context for command, stack service not available.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ break;
+ case INSTRUCTION_STEP_INTO:
+ fConnection.queueCommand(new MIExecStepInstruction(dmc),
+ new DataRequestMonitor(getExecutor(), rm));
+ break;
+ case INSTRUCTION_STEP_OVER:
+ fConnection.queueCommand(new MIExecNextInstruction(dmc),
+ new DataRequestMonitor(getExecutor(), rm));
+ break;
+ default:
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
+ INTERNAL_ERROR, "Given step type not supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Run to line
+ // ------------------------------------------------------------------------
+
+ // Later add support for Address and function.
+ // skipBreakpoints is not used at the moment. Implement later
+ public void runToLine(IExecutionDMContext context, String fileName, String lineNo, boolean skipBreakpoints, final DataRequestMonitor rm) {
+
+ assert context != null;
+
+ IMIExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IMIExecutionDMContext.class);
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
+ "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ if (!doCanResume(context)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Cannot resume context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ if (threadState == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
+ "Given context: " + context + " is not an MI execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ threadState.fResumePending = true;
+ fConnection.queueCommand(new MIExecUntil(dmc, fileName + ":" + lineNo), //$NON-NLS-1$
+ new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ // ------------------------------------------------------------------------
+ // Support functions
+ // ------------------------------------------------------------------------
+
+ public void getExecutionContexts(final IContainerDMContext containerDmc, final DataRequestMonitor rm) {
+ IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
+ procService.getProcessesBeingDebugged(
+ containerDmc,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ if (getData() instanceof IExecutionDMContext[]) {
+ rm.setData((IExecutionDMContext[])getData());
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid contexts", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+
+ public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor rm) {
+ MIThreadRunState threadState = fThreadRunStates.get(dmc);
+ if (threadState == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,INVALID_HANDLE,
+ "Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ rm.done();
+ return;
+ }
+
+ if (dmc instanceof IMIExecutionDMContext) {
+ rm.setData(new ExecutionData(threadState.fSuspended ? threadState.fStateChangeReason : null));
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Given context: " + dmc + " is not a recognized execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ rm.done();
+ }
+
+
+ private IMIExecutionDMContext createMIExecutionContext(IContainerDMContext container, String threadId) {
+ IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
+
+ IProcessDMContext procDmc = DMContexts.getAncestorOfType(container, IProcessDMContext.class);
+
+ IThreadDMContext threadDmc = null;
+ if (procDmc != null) {
+ // For now, reuse the threadId as the OSThreadId
+ threadDmc = procService.createThreadContext(procDmc, threadId);
+ }
+
+ return procService.createExecutionContext(container, threadDmc, threadId);
+ }
+
+ private void updateThreadState(IMIExecutionDMContext context, ResumedEvent event) {
+ StateChangeReason reason = event.getReason();
+ boolean isStepping = reason.equals(StateChangeReason.STEP);
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ if (threadState == null) {
+ threadState = new MIThreadRunState();
+ fThreadRunStates.put(context, threadState);
+ }
+ threadState.fSuspended = false;
+ threadState.fResumePending = false;
+ threadState.fStateChangeReason = reason;
+ threadState.fStepping = isStepping;
+ }
+
+ private void updateThreadState(IMIExecutionDMContext context, SuspendedEvent event) {
+ StateChangeReason reason = event.getReason();
+ MIThreadRunState threadState = fThreadRunStates.get(context);
+ if (threadState == null) {
+ threadState = new MIThreadRunState();
+ fThreadRunStates.put(context, threadState);
+ }
+ threadState.fSuspended = true;
+ threadState.fResumePending = false;
+ threadState.fStepping = false;
+ threadState.fStateChangeReason = reason;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Event handlers
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIRunningEvent e) {
+ getSession().dispatchEvent(new ResumedEvent(e.getDMContext(), e), getProperties());
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIStoppedEvent e) {
+ getSession().dispatchEvent(new SuspendedEvent(e.getDMContext(), e), getProperties());
+ }
+
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIThreadCreatedEvent e) {
+ IContainerDMContext containerDmc = e.getDMContext();
+ IMIExecutionDMContext executionCtx = null;
+ if (e.getStrId() != null) {
+ executionCtx = createMIExecutionContext(containerDmc, e.getStrId());
+ }
+ getSession().dispatchEvent(new StartedDMEvent(executionCtx, e), getProperties());
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(final MIThreadExitEvent e) {
+ IContainerDMContext containerDmc = e.getDMContext();
+ IMIExecutionDMContext executionCtx = null;
+ if (e.getStrId() != null) {
+ executionCtx = createMIExecutionContext(containerDmc, e.getStrId());
+ }
+ getSession().dispatchEvent(new ExitedDMEvent(executionCtx, e), getProperties());
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(ResumedEvent e) {
+ IExecutionDMContext ctx = e.getDMContext();
+ if (ctx instanceof IMIExecutionDMContext) {
+ updateThreadState((IMIExecutionDMContext)ctx, e);
+ }
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(SuspendedEvent e) {
+ IExecutionDMContext ctx = e.getDMContext();
+ if (ctx instanceof IMIExecutionDMContext) {
+ updateThreadState((IMIExecutionDMContext)ctx, e);
+ }
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(StartedDMEvent e) {
+ IExecutionDMContext executionCtx = e.getDMContext();
+ if (executionCtx instanceof IMIExecutionDMContext) {
+ if (fThreadRunStates.get(executionCtx) == null) {
+ fThreadRunStates.put((IMIExecutionDMContext)executionCtx, new MIThreadRunState());
+ }
+ }
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(ExitedDMEvent e) {
+ fThreadRunStates.remove(e.getDMContext());
+ }
+
+ /**
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(ICommandControlShutdownDMEvent e) {
+ fTerminated = true;
+ }
+
+ public void flushCache(IDMContext context) {
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
new file mode 100644
index 00000000000..5a7a31c0e7f
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * 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
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.dsf.debug.service.AbstractDsfDebugServicesFactory;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
+import org.eclipse.cdt.dsf.debug.service.IDisassembly;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IMemory;
+import org.eclipse.cdt.dsf.debug.service.IModules;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.gdb.service.command.GDBControl;
+import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0;
+import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
+import org.eclipse.cdt.dsf.mi.service.ExpressionService;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
+import org.eclipse.cdt.dsf.mi.service.MIDisassembly;
+import org.eclipse.cdt.dsf.mi.service.MIMemory;
+import org.eclipse.cdt.dsf.mi.service.MIModules;
+import org.eclipse.cdt.dsf.mi.service.MIRegisters;
+import org.eclipse.cdt.dsf.mi.service.MIStack;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.ILaunchConfiguration;
+
+public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory {
+
+ private final String fVersion;
+
+ public GdbDebugServicesFactory(String version) {
+ fVersion = version;
+ }
+
+ public String getVersion() { return fVersion; }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V createService(Class clazz, DsfSession session, Object ... optionalArguments) {
+ if (MIBreakpointsManager.class.isAssignableFrom(clazz)) {
+ return (V)createBreakpointManagerService(session);
+ }
+ else if (ICommandControl.class.isAssignableFrom(clazz)) {
+ for (Object arg : optionalArguments) {
+ if (arg instanceof ILaunchConfiguration) {
+ return (V)createCommandControl(session, (ILaunchConfiguration)arg);
+ }
+ }
+ }
+ else if (IMIBackend.class.isAssignableFrom(clazz)) {
+ for (Object arg : optionalArguments) {
+ if (arg instanceof ILaunchConfiguration) {
+ return (V)createBackendGDBService(session, (ILaunchConfiguration)arg);
+ }
+ }
+ }
+
+
+ return super.createService(clazz, session);
+ }
+
+ protected MIBreakpointsManager createBreakpointManagerService(DsfSession session) {
+ return new MIBreakpointsManager(session, CDebugCorePlugin.PLUGIN_ID);
+ }
+
+ @Override
+ protected IBreakpoints createBreakpointService(DsfSession session) {
+ return new MIBreakpoints(session);
+ }
+
+ protected ICommandControl createCommandControl(DsfSession session, ILaunchConfiguration config) {
+ if ("6.8".compareTo(fVersion) < 0) { //$NON-NLS-1$
+ return new GDBControl_7_0(session, config);
+ }
+ return new GDBControl(session, config);
+ }
+
+ protected IMIBackend createBackendGDBService(DsfSession session, ILaunchConfiguration lc) {
+ return new GDBBackend(session, lc);
+ }
+
+ @Override
+ protected IDisassembly createDisassemblyService(DsfSession session) {
+ return new MIDisassembly(session);
+ }
+
+ @Override
+ protected IExpressions createExpressionService(DsfSession session) {
+ return new ExpressionService(session);
+ }
+
+ @Override
+ protected IMemory createMemoryService(DsfSession session) {
+ if ("6.8".compareTo(fVersion) < 0) { //$NON-NLS-1$
+ return new GDBMemory_7_0(session);
+ }
+
+ return new MIMemory(session);
+ }
+
+ @Override
+ protected IModules createModulesService(DsfSession session) {
+ return new MIModules(session);
+ }
+
+ @Override
+ protected IProcesses createProcessesService(DsfSession session) {
+ if (fVersion.startsWith("6.8.50.20081118")) { //$NON-NLS-1$
+ return new GDBProcesses_7_0(session);
+ }
+ return new GDBProcesses(session);
+ }
+
+ @Override
+ protected IRegisters createRegistersService(DsfSession session) {
+ return new MIRegisters(session);
+ }
+
+ @Override
+ protected IRunControl createRunControlService(DsfSession session) {
+ if ("6.8".compareTo(fVersion) < 0) { //$NON-NLS-1$
+ return new GDBRunControl_7_0(session);
+ }
+ return new GDBRunControl(session);
+ }
+
+ @Override
+ protected ISourceLookup createSourceLookupService(DsfSession session) {
+ return new CSourceLookup(session);
+ }
+
+ @Override
+ protected IStack createStackService(DsfSession session) {
+ return new MIStack(session);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactoryNS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactoryNS.java
new file mode 100644
index 00000000000..093e00e56a8
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactoryNS.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.service;
+
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.service.DsfSession;
+
+public class GdbDebugServicesFactoryNS extends GdbDebugServicesFactory {
+
+ public GdbDebugServicesFactoryNS(String version) {
+ super(version);
+ }
+
+ @Override
+ protected IRunControl createRunControlService(DsfSession session) {
+ return new GDBRunControl_7_0_NS(session);
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java
new file mode 100644
index 00000000000..e7eb6061495
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBBackend.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Nokia Corporation.
+ * 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:
+ * Nokia - initial version
+ * Ericsson - Minor cleanup
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service;
+
+import java.util.List;
+
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+
+/**
+ * Service that manages back end GDB process, such as launching and monitoring
+ * GDB process, managing certain GDB parameters/options. This service makes it
+ * easy for debugger implementations to customize the way to start GDB process
+ * and convert some parameters if needed. See bug 240092 for more.
+ *
+ * A base implementation {@link GDBBackend} is provided that should be
+ * sufficient for most cases. But if you have special needs, it's recommended to
+ * subclass the base implementation.
+ *
+ * Here are some special cases:
+ * Example #1: GDB is usually launched on the host machine where Eclipse is
+ * running, but it can also be launched on a remote machine through, say, SSH.
+ * Example #2: GDB is usually launched in the host file system, but it can also
+ * be launched in a chroot'ed file system such as Scratchbox (see
+ * http://www.scratchbox.org)
+ *
+ * @since 1.1
+ */
+public interface IGDBBackend extends IMIBackend {
+
+ /**
+ * Get path of the debugged program on host.
+ *
+ * @return IPath
+ */
+ public IPath getProgramPath();
+
+ /**
+ * Get init file for GDB.
+ *
+ * @return file name, may have relative or absolute path, or empty string ("")
+ * indicating an init file is not specified.
+ * @throws CoreException
+ * - error in getting the option.
+ */
+ public String getGDBInitFile() throws CoreException;
+
+ /**
+ * get arguments for the debugged program.
+ *
+ * @return String
+ * @throws CoreException
+ * - error in getting the option.
+ */
+ public String getProgramArguments() throws CoreException;
+
+ /**
+ * Get working directory for GDB.
+ *
+ * @return IPath - null if no meaningful value found.
+ * @throws CoreException
+ * - if any error occurs.
+ */
+ public IPath getGDBWorkingDirectory() throws CoreException;
+
+ /**
+ * @throws CoreException
+ * - error in getting the option.
+ */
+ public List getSharedLibraryPaths() throws CoreException;
+
+
+ /**
+ * Sends an interrupt signal to the GDB process.
+ */
+ public void interrupt();
+
+ /**
+ * @return The type of the session currently ongoing with the backend
+ */
+ public SessionType getSessionType();
+
+ /**
+ * @return true if the ongoing session is attaching to a remote target.
+ */
+ public boolean getIsAttachSession();
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java
new file mode 100644
index 00000000000..1661011a278
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBProcesses.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.service;
+
+import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+
+public interface IGDBProcesses extends IMIProcesses {
+ /**
+ * Get a list of all execution contexts belonging to a container. This call is synchronous,
+ * unlike the call to getProcessesBeingDebugged(). However, some services may not be able
+ * to fulfill this request synchronously and will have to rely on getProcessesBeingDebugged().
+ *
+ * @param containerDmc The container for which we want to get the execution contexts
+ */
+ IMIExecutionDMContext[] getExecutionContexts(IMIContainerDMContext containerDmc);
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/SessionType.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/SessionType.java
new file mode 100644
index 00000000000..779892a4fac
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/SessionType.java
@@ -0,0 +1,13 @@
+/*******************************************************************************
+ * 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.cdt.dsf.gdb.service;
+
+public enum SessionType { LOCAL, REMOTE, CORE }
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java
new file mode 100644
index 00000000000..f861504b82b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl.java
@@ -0,0 +1,504 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for additional features in DSF Reference implementation
+ * Nokia - create and use backend service.
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses.ContainerStartedDMEvent;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
+import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor;
+import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecRun;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBExit;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.osgi.framework.BundleContext;
+
+/**
+ * GDB Debugger control implementation. This implementation extends the
+ * base MI control implementation to provide the GDB-specific debugger
+ * features. This includes:
+ * - CLI console support,
+ * - inferior process status tracking.
+ */
+public class GDBControl extends AbstractMIControl implements IGDBControl {
+
+ /**
+ * Event indicating that the back end process has started.
+ */
+ private static class GDBControlInitializedDMEvent extends AbstractDMEvent
+ implements ICommandControlInitializedDMEvent
+ {
+ public GDBControlInitializedDMEvent(ICommandControlDMContext context) {
+ super(context);
+ }
+ }
+
+ /**
+ * Event indicating that the CommandControl (back end process) has terminated.
+ */
+ private static class GDBControlShutdownDMEvent extends AbstractDMEvent
+ implements ICommandControlShutdownDMEvent
+ {
+ public GDBControlShutdownDMEvent(ICommandControlDMContext context) {
+ super(context);
+ }
+ }
+
+ private GDBControlDMContext fControlDmc;
+
+ private IGDBBackend fMIBackend;
+
+ private boolean fConnected = true;
+
+ private MIRunControlEventProcessor fMIEventProcessor;
+ private CLIEventProcessor fCLICommandProcessor;
+ private AbstractCLIProcess fCLIProcess;
+ private MIInferiorProcess fInferiorProcess = null;
+
+ private PTY fPty;
+
+ public GDBControl(DsfSession session, ILaunchConfiguration config) {
+ super(session, false);
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize( new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ public void doInitialize(final RequestMonitor requestMonitor) {
+
+ fMIBackend = getServicesTracker().getService(IGDBBackend.class);
+
+ // getId uses the MIBackend service, which is why we must wait until we
+ // have it, before we can create this context.
+ fControlDmc = new GDBControlDMContext(getSession().getId(), getId());
+
+ final Sequence.Step[] initializeSteps = new Sequence.Step[] {
+ new CommandMonitoringStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new InferiorInputOutputInitStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new CommandProcessorsStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
+ };
+
+ Sequence startupSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return initializeSteps; }
+ };
+ getExecutor().execute(startupSequence);
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
+ new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new CommandProcessorsStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new InferiorInputOutputInitStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new CommandMonitoringStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ };
+ Sequence shutdownSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return shutdownSteps; }
+ };
+ getExecutor().execute(shutdownSequence);
+
+ }
+
+ public String getId() {
+ return fMIBackend.getId();
+ }
+
+ @Override
+ public MIControlDMContext getControlDMContext() {
+ return fControlDmc;
+ }
+
+ public ICommandControlDMContext getContext() {
+ return fControlDmc;
+ }
+
+ public void terminate(final RequestMonitor rm) {
+ // Schedule a runnable to be executed 2 seconds from now.
+ // If we don't get a response to the quit command, this
+ // runnable will kill the task.
+ final Future> quitTimeoutFuture = getExecutor().schedule(
+ new DsfRunnable() {
+ public void run() {
+ fMIBackend.destroy();
+ rm.done();
+ }
+
+ @Override
+ protected boolean isExecutionRequired() {
+ return false;
+ }
+ },
+ 2, TimeUnit.SECONDS);
+
+ queueCommand(
+ new MIGDBExit(fControlDmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ // Cancel the time out runnable (if it hasn't run yet).
+ if (quitTimeoutFuture.cancel(false)) {
+ if (!isSuccess()) {
+ fMIBackend.destroy();
+ }
+ rm.done();
+ }
+ }
+ }
+ );
+ }
+
+ /*
+ * This method does the necessary work to setup the input/output streams for the
+ * inferior process, by either preparing the PTY to be used, to simply leaving
+ * the PTY null, which indicates that the input/output streams of the CLI should
+ * be used instead; this decision is based on the type of session.
+ */
+ public void initInferiorInputOutput(final RequestMonitor requestMonitor) {
+ if (fMIBackend.getSessionType() == SessionType.REMOTE || fMIBackend.getIsAttachSession()) {
+ // These types do not use a PTY
+ fPty = null;
+ requestMonitor.done();
+ } else {
+ // These types always use a PTY
+ try {
+ fPty = new PTY();
+
+ // Tell GDB to use this PTY
+ queueCommand(
+ new MIInferiorTTYSet((ICommandControlDMContext)fControlDmc, fPty.getSlaveName()),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleFailure() {
+ // We were not able to tell GDB to use the PTY
+ // so we won't use it at all.
+ fPty = null;
+ requestMonitor.done();
+ }
+ });
+ } catch (IOException e) {
+ fPty = null;
+ requestMonitor.done();
+ }
+ }
+ }
+
+
+ public boolean canRestart() {
+ if (fMIBackend.getIsAttachSession()) return false;
+
+ // Before GDB6.8, the Linux gdbserver would restart a new
+ // process when getting a -exec-run but the communication
+ // with GDB had a bug and everything hung.
+ // with GDB6.8 the program restarts properly one time,
+ // but on a second attempt, gdbserver crashes.
+ // So, lets just turn off the Restart for Remote debugging
+ if (fMIBackend.getSessionType() == SessionType.REMOTE) return false;
+
+ return true;
+ }
+
+ /*
+ * Start the program.
+ */
+ public void start(GdbLaunch launch, final RequestMonitor requestMonitor) {
+ startOrRestart(launch, false, requestMonitor);
+ }
+
+ /*
+ * Before restarting the inferior, we must re-initialize its input/output streams
+ * and create a new inferior process object. Then we can restart the inferior.
+ */
+ public void restart(final GdbLaunch launch, final RequestMonitor requestMonitor) {
+ startOrRestart(launch, true, requestMonitor);
+ }
+
+ /*
+ * Insert breakpoint at entry if set, and start or restart the program.
+ */
+ protected void startOrRestart(final GdbLaunch launch, boolean restart, final RequestMonitor requestMonitor) {
+ if (fMIBackend.getIsAttachSession()) {
+ // When attaching to a running process, we do not need to set a breakpoint or
+ // start the program; it is left up to the user.
+ requestMonitor.done();
+ return;
+ }
+
+ DsfServicesTracker servicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId());
+ IMIProcesses procService = servicesTracker.getService(IMIProcesses.class);
+ servicesTracker.dispose();
+ IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
+ final IContainerDMContext containerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
+
+ final MICommand execCommand;
+ if (fMIBackend.getSessionType() == SessionType.REMOTE) {
+ // When doing remote debugging, we use -exec-continue instead of -exec-run
+ execCommand = new MIExecContinue(containerDmc);
+ } else {
+ execCommand = new MIExecRun(containerDmc, new String[0]);
+ }
+
+ boolean stopInMain = false;
+ try {
+ stopInMain = launch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ final DataRequestMonitor execMonitor = new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ getSession().dispatchEvent(new ContainerStartedDMEvent(containerDmc), getProperties());
+ super.handleSuccess();
+ }
+ };
+
+ if (!stopInMain) {
+ // Just start the program.
+ queueCommand(execCommand, execMonitor);
+ } else {
+ String stopSymbol = null;
+ try {
+ stopSymbol = launch.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, GdbPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ // Insert a breakpoint at the requested stop symbol.
+ queueCommand(
+ new MIBreakInsert(fControlDmc, true, false, null, 0, stopSymbol, 0),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ // After the break-insert is done, execute the -exec-run or -exec-continue command.
+ queueCommand(execCommand, execMonitor);
+ }
+ });
+ }
+ }
+
+ /*
+ * This method creates a new inferior process object based on the current Pty or output stream.
+ */
+ public void createInferiorProcess() {
+ if (fPty == null) {
+ fInferiorProcess = new GDBInferiorProcess(GDBControl.this, fMIBackend, fMIBackend.getMIOutputStream());
+ } else {
+ fInferiorProcess = new GDBInferiorProcess(GDBControl.this, fMIBackend, fPty);
+ }
+ }
+
+ public boolean isConnected() {
+ return fInferiorProcess.getState() != MIInferiorProcess.State.TERMINATED && fConnected;
+ }
+
+ public void setConnected(boolean connected) {
+ fConnected = connected;
+ }
+
+ public AbstractCLIProcess getCLIProcess() {
+ return fCLIProcess;
+ }
+
+ public MIInferiorProcess getInferiorProcess() {
+ return fInferiorProcess;
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(ICommandControlShutdownDMEvent e) {
+ // Handle our "GDB Exited" event and stop processing commands.
+ stopCommandProcessing();
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BackendStateChangedEvent e) {
+ if (e.getState() == IMIBackend.State.TERMINATED && e.getBackendId().equals(fMIBackend.getId())) {
+ // Handle "GDB Exited" event, just relay to following event.
+ getSession().dispatchEvent(new GDBControlShutdownDMEvent(fControlDmc), getProperties());
+ }
+ }
+
+ public static class InitializationShutdownStep extends Sequence.Step {
+ public enum Direction { INITIALIZING, SHUTTING_DOWN }
+
+ private Direction fDirection;
+ public InitializationShutdownStep(Direction direction) { fDirection = direction; }
+
+ @Override
+ final public void execute(RequestMonitor requestMonitor) {
+ if (fDirection == Direction.INITIALIZING) {
+ initialize(requestMonitor);
+ } else {
+ shutdown(requestMonitor);
+ }
+ }
+
+ @Override
+ final public void rollBack(RequestMonitor requestMonitor) {
+ if (fDirection == Direction.INITIALIZING) {
+ shutdown(requestMonitor);
+ } else {
+ super.rollBack(requestMonitor);
+ }
+ }
+
+ protected void initialize(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ protected void shutdown(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ }
+
+ protected class CommandMonitoringStep extends InitializationShutdownStep {
+ CommandMonitoringStep(Direction direction) { super(direction); }
+
+ @Override
+ protected void initialize(final RequestMonitor requestMonitor) {
+ startCommandProcessing(fMIBackend.getMIInputStream(), fMIBackend.getMIOutputStream());
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ stopCommandProcessing();
+ requestMonitor.done();
+ }
+ }
+
+ protected class InferiorInputOutputInitStep extends InitializationShutdownStep {
+ InferiorInputOutputInitStep(Direction direction) { super(direction); }
+
+ @Override
+ protected void initialize(final RequestMonitor requestMonitor) {
+ initInferiorInputOutput(requestMonitor);
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ }
+
+ protected class CommandProcessorsStep extends InitializationShutdownStep {
+ CommandProcessorsStep(Direction direction) { super(direction); }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ try {
+ fCLIProcess = new MIBackendCLIProcess(GDBControl.this, fMIBackend);
+ }
+ catch(IOException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Failed to create CLI Process", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ createInferiorProcess();
+
+ fCLICommandProcessor = new CLIEventProcessor(GDBControl.this, fControlDmc);
+ fMIEventProcessor = new MIRunControlEventProcessor(GDBControl.this, fControlDmc);
+
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ fCLICommandProcessor.dispose();
+ fMIEventProcessor.dispose();
+ fCLIProcess.dispose();
+ fInferiorProcess.dispose();
+
+ requestMonitor.done();
+ }
+ }
+
+ protected class RegisterStep extends InitializationShutdownStep {
+ RegisterStep(Direction direction) { super(direction); }
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ getSession().addServiceEventListener(GDBControl.this, null);
+ register(
+ new String[]{ ICommandControl.class.getName(),
+ ICommandControlService.class.getName(),
+ AbstractMIControl.class.getName(),
+ IGDBControl.class.getName() },
+ new Hashtable());
+ getSession().dispatchEvent(new GDBControlInitializedDMEvent(fControlDmc), getProperties());
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ getSession().removeServiceEventListener(GDBControl.this);
+ requestMonitor.done();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java
new file mode 100644
index 00000000000..19657a111e6
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext;
+import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext;
+import org.eclipse.cdt.dsf.debug.service.ISignals.ISignalsDMContext;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
+import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
+
+/**
+ *
+ */
+public class GDBControlDMContext extends MIControlDMContext
+ implements ISymbolDMContext, IBreakpointsTargetDMContext, ISourceLookupDMContext,
+ ISignalsDMContext, IDisassemblyDMContext
+{
+
+ public GDBControlDMContext(String sessionId, String commandControlId) {
+ super(sessionId, commandControlId);
+ }
+
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java
new file mode 100644
index 00000000000..53e651b07ea
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControl_7_0.java
@@ -0,0 +1,496 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for additional features in DSF Reference implementation
+ * Ericsson - New version for 7_0
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.Sequence;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.gdb.service.SessionType;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend;
+import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
+import org.eclipse.cdt.dsf.mi.service.MIProcesses;
+import org.eclipse.cdt.dsf.mi.service.IMIBackend.BackendStateChangedEvent;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractMIControl;
+import org.eclipse.cdt.dsf.mi.service.command.CLIEventProcessor_7_0;
+import org.eclipse.cdt.dsf.mi.service.command.MIBackendCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIRunControlEventProcessor_7_0;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecContinue;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIExecRun;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIGDBExit;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIInferiorTTYSet;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.pty.PTY;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.osgi.framework.BundleContext;
+
+/**
+ * GDB Debugger control implementation. This implementation extends the
+ * base MI control implementation to provide the GDB-specific debugger
+ * features. This includes:
+ * - CLI console support,
+ * - inferior process status tracking.
+ */
+public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
+
+ /**
+ * Event indicating that the back end process has started.
+ */
+ private static class GDBControlInitializedDMEvent extends AbstractDMEvent
+ implements ICommandControlInitializedDMEvent
+ {
+ public GDBControlInitializedDMEvent(ICommandControlDMContext context) {
+ super(context);
+ }
+ }
+
+ /**
+ * Event indicating that the CommandControl (back end process) has terminated.
+ */
+ private static class GDBControlShutdownDMEvent extends AbstractDMEvent
+ implements ICommandControlShutdownDMEvent
+ {
+ public GDBControlShutdownDMEvent(ICommandControlDMContext context) {
+ super(context);
+ }
+ }
+
+ private GDBControlDMContext fControlDmc;
+
+ private IGDBBackend fMIBackend;
+
+ private boolean fConnected = true;
+
+ private MIRunControlEventProcessor_7_0 fMIEventProcessor;
+ private CLIEventProcessor_7_0 fCLICommandProcessor;
+ private AbstractCLIProcess fCLIProcess;
+ private MIInferiorProcess fInferiorProcess = null;
+
+ private PTY fPty;
+
+ public GDBControl_7_0(DsfSession session, ILaunchConfiguration config) {
+ super(session, true);
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize( new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ public void doInitialize(final RequestMonitor requestMonitor) {
+ fMIBackend = getServicesTracker().getService(IGDBBackend.class);
+
+ // getId uses the MIBackend service, which is why we must wait until we
+ // have it, before we can create this context.
+ fControlDmc = new GDBControlDMContext(getSession().getId(), getId());
+
+ final Sequence.Step[] initializeSteps = new Sequence.Step[] {
+ new CommandMonitoringStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new InferiorInputOutputInitStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new CommandProcessorsStep(InitializationShutdownStep.Direction.INITIALIZING),
+ new RegisterStep(InitializationShutdownStep.Direction.INITIALIZING),
+ };
+
+ Sequence startupSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return initializeSteps; }
+ };
+ getExecutor().execute(startupSequence);
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ final Sequence.Step[] shutdownSteps = new Sequence.Step[] {
+ new RegisterStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new CommandProcessorsStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new InferiorInputOutputInitStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ new CommandMonitoringStep(InitializationShutdownStep.Direction.SHUTTING_DOWN),
+ };
+ Sequence shutdownSequence = new Sequence(getExecutor(), requestMonitor) {
+ @Override public Step[] getSteps() { return shutdownSteps; }
+ };
+ getExecutor().execute(shutdownSequence);
+
+ }
+
+ public String getId() {
+ return fMIBackend.getId();
+ }
+
+ @Override
+ public MIControlDMContext getControlDMContext() {
+ return fControlDmc;
+ }
+
+ public ICommandControlDMContext getContext() {
+ return fControlDmc;
+ }
+
+ public void terminate(final RequestMonitor rm) {
+ // Schedule a runnable to be executed 2 seconds from now.
+ // If we don't get a response to the quit command, this
+ // runnable will kill the task.
+ final Future> quitTimeoutFuture = getExecutor().schedule(
+ new DsfRunnable() {
+ public void run() {
+ fMIBackend.destroy();
+ rm.done();
+ }
+
+ @Override
+ protected boolean isExecutionRequired() {
+ return false;
+ }
+ },
+ 2, TimeUnit.SECONDS);
+
+ queueCommand(
+ new MIGDBExit(fControlDmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ // Cancel the time out runnable (if it hasn't run yet).
+ if (quitTimeoutFuture.cancel(false)) {
+ if (!isSuccess()) {
+ fMIBackend.destroy();
+ }
+ rm.done();
+ }
+ }
+ }
+ );
+ }
+
+ /*
+ * This method does the necessary work to setup the input/output streams for the
+ * inferior process, by either preparing the PTY to be used, to simply leaving
+ * the PTY null, which indicates that the input/output streams of the CLI should
+ * be used instead; this decision is based on the type of session.
+ */
+ public void initInferiorInputOutput(final RequestMonitor requestMonitor) {
+ if (fMIBackend.getSessionType() == SessionType.REMOTE || fMIBackend.getIsAttachSession()) {
+ // These types do not use a PTY
+ fPty = null;
+ requestMonitor.done();
+ } else {
+ // These types always use a PTY
+ try {
+ fPty = new PTY();
+
+ // Tell GDB to use this PTY
+ queueCommand(
+ new MIInferiorTTYSet((ICommandControlDMContext)fControlDmc, fPty.getSlaveName()),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleFailure() {
+ // We were not able to tell GDB to use the PTY
+ // so we won't use it at all.
+ fPty = null;
+ requestMonitor.done();
+ }
+ });
+ } catch (IOException e) {
+ fPty = null;
+ requestMonitor.done();
+ }
+ }
+ }
+
+
+ public boolean canRestart() {
+ if (fMIBackend.getIsAttachSession()) return false;
+
+ // Before GDB6.8, the Linux gdbserver would restart a new
+ // process when getting a -exec-run but the communication
+ // with GDB had a bug and everything hung.
+ // with GDB6.8 the program restarts properly one time,
+ // but on a second attempt, gdbserver crashes.
+ // So, lets just turn off the Restart for Remote debugging
+ if (fMIBackend.getSessionType() == SessionType.REMOTE) return false;
+
+ return true;
+ }
+
+ /*
+ * Start the program.
+ */
+ public void start(GdbLaunch launch, final RequestMonitor requestMonitor) {
+ startOrRestart(launch, false, requestMonitor);
+ }
+
+ /*
+ * Before restarting the inferior, we must re-initialize its input/output streams
+ * and create a new inferior process object. Then we can restart the inferior.
+ */
+ public void restart(final GdbLaunch launch, final RequestMonitor requestMonitor) {
+ startOrRestart(launch, true, requestMonitor);
+ }
+
+ /*
+ * Insert breakpoint at entry if set, and start or restart the program.
+ */
+ protected void startOrRestart(final GdbLaunch launch, boolean restart, final RequestMonitor requestMonitor) {
+ if (fMIBackend.getIsAttachSession()) {
+ // When attaching to a running process, we do not need to set a breakpoint or
+ // start the program; it is left up to the user.
+ requestMonitor.done();
+ return;
+ }
+
+ DsfServicesTracker servicesTracker = new DsfServicesTracker(GdbPlugin.getBundleContext(), getSession().getId());
+ IMIProcesses procService = servicesTracker.getService(IMIProcesses.class);
+ servicesTracker.dispose();
+ IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, MIProcesses.UNIQUE_GROUP_ID);
+ final IContainerDMContext containerDmc = procService.createContainerContext(procDmc, MIProcesses.UNIQUE_GROUP_ID);
+
+ final MICommand execCommand;
+ if (fMIBackend.getSessionType() == SessionType.REMOTE) {
+ // When doing remote debugging, we use -exec-continue instead of -exec-run
+ execCommand = new MIExecContinue(containerDmc);
+ } else {
+ execCommand = new MIExecRun(containerDmc, new String[0]);
+ }
+
+ boolean stopInMain = false;
+ try {
+ stopInMain = launch.getLaunchConfiguration().getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false );
+ } catch (CoreException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot retrieve stop at entry point boolean", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ final DataRequestMonitor execMonitor = new DataRequestMonitor(getExecutor(), requestMonitor);
+
+ if (!stopInMain) {
+ // Just start the program.
+ queueCommand(execCommand, execMonitor);
+ } else {
+ String stopSymbol = null;
+ try {
+ stopSymbol = launch.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, GdbPlugin.PLUGIN_ID, DebugException.CONFIGURATION_INVALID, "Cannot retrieve the entry point symbol", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ // Insert a breakpoint at the requested stop symbol.
+ queueCommand(
+ new MIBreakInsert(fControlDmc, true, false, null, 0, stopSymbol, 0),
+ new DataRequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ // After the break-insert is done, execute the -exec-run or -exec-continue command.
+ queueCommand(execCommand, execMonitor);
+ }
+ });
+ }
+ }
+
+ /*
+ * This method creates a new inferior process object based on the current Pty or output stream.
+ */
+ public void createInferiorProcess() {
+ if (fPty == null) {
+ fInferiorProcess = new GDBInferiorProcess(GDBControl_7_0.this, fMIBackend, fMIBackend.getMIOutputStream());
+ } else {
+ fInferiorProcess = new GDBInferiorProcess(GDBControl_7_0.this, fMIBackend, fPty);
+ }
+ }
+
+ public boolean isConnected() {
+ return fInferiorProcess.getState() != MIInferiorProcess.State.TERMINATED && fConnected;
+ }
+
+ public void setConnected(boolean connected) {
+ fConnected = connected;
+ }
+
+ public AbstractCLIProcess getCLIProcess() {
+ return fCLIProcess;
+ }
+
+ public MIInferiorProcess getInferiorProcess() {
+ return fInferiorProcess;
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(ICommandControlShutdownDMEvent e) {
+ // Handle our "GDB Exited" event and stop processing commands.
+ stopCommandProcessing();
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BackendStateChangedEvent e) {
+ if (e.getState() == IMIBackend.State.TERMINATED && e.getBackendId().equals(fMIBackend.getId())) {
+ // Handle "GDB Exited" event, just relay to following event.
+ getSession().dispatchEvent(new GDBControlShutdownDMEvent(fControlDmc), getProperties());
+ }
+ }
+
+ public static class InitializationShutdownStep extends Sequence.Step {
+ public enum Direction { INITIALIZING, SHUTTING_DOWN }
+
+ private Direction fDirection;
+ public InitializationShutdownStep(Direction direction) { fDirection = direction; }
+
+ @Override
+ final public void execute(RequestMonitor requestMonitor) {
+ if (fDirection == Direction.INITIALIZING) {
+ initialize(requestMonitor);
+ } else {
+ shutdown(requestMonitor);
+ }
+ }
+
+ @Override
+ final public void rollBack(RequestMonitor requestMonitor) {
+ if (fDirection == Direction.INITIALIZING) {
+ shutdown(requestMonitor);
+ } else {
+ super.rollBack(requestMonitor);
+ }
+ }
+
+ protected void initialize(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ protected void shutdown(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ }
+
+ protected class CommandMonitoringStep extends InitializationShutdownStep {
+ CommandMonitoringStep(Direction direction) { super(direction); }
+
+ @Override
+ protected void initialize(final RequestMonitor requestMonitor) {
+ startCommandProcessing(fMIBackend.getMIInputStream(), fMIBackend.getMIOutputStream());
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ stopCommandProcessing();
+ requestMonitor.done();
+ }
+ }
+
+ protected class InferiorInputOutputInitStep extends InitializationShutdownStep {
+ InferiorInputOutputInitStep(Direction direction) { super(direction); }
+
+ @Override
+ protected void initialize(final RequestMonitor requestMonitor) {
+ initInferiorInputOutput(requestMonitor);
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ requestMonitor.done();
+ }
+ }
+
+ protected class CommandProcessorsStep extends InitializationShutdownStep {
+ CommandProcessorsStep(Direction direction) { super(direction); }
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ try {
+ fCLIProcess = new MIBackendCLIProcess(GDBControl_7_0.this, fMIBackend);
+ }
+ catch(IOException e) {
+ requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Failed to create CLI Process", e)); //$NON-NLS-1$
+ requestMonitor.done();
+ return;
+ }
+
+ createInferiorProcess();
+
+ fCLICommandProcessor = new CLIEventProcessor_7_0(GDBControl_7_0.this, fControlDmc);
+ fMIEventProcessor = new MIRunControlEventProcessor_7_0(GDBControl_7_0.this, fControlDmc);
+
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ fCLICommandProcessor.dispose();
+ fMIEventProcessor.dispose();
+ fCLIProcess.dispose();
+ fInferiorProcess.dispose();
+
+ requestMonitor.done();
+ }
+ }
+
+ protected class RegisterStep extends InitializationShutdownStep {
+ RegisterStep(Direction direction) { super(direction); }
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ getSession().addServiceEventListener(GDBControl_7_0.this, null);
+ register(
+ new String[]{ ICommandControl.class.getName(),
+ ICommandControlService.class.getName(),
+ AbstractMIControl.class.getName(),
+ IGDBControl.class.getName() },
+ new Hashtable());
+ getSession().dispatchEvent(new GDBControlInitializedDMEvent(fControlDmc), getProperties());
+ requestMonitor.done();
+ }
+
+ @Override
+ protected void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ getSession().removeServiceEventListener(GDBControl_7_0.this);
+ requestMonitor.done();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java
new file mode 100644
index 00000000000..51c3114646a
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBInferiorProcess.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.gdb.service.command;
+
+import java.io.OutputStream;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+import org.eclipse.cdt.utils.pty.PTY;
+
+/**
+ *
+ */
+class GDBInferiorProcess extends MIInferiorProcess {
+
+ private IGDBBackend fBackend;
+
+ public GDBInferiorProcess(ICommandControlService commandControl, IGDBBackend backend, PTY p) {
+ super(commandControl, p);
+ fBackend = backend;
+ }
+
+ public GDBInferiorProcess(ICommandControlService commandControl, IGDBBackend backend, OutputStream gdbOutputStream) {
+ super(commandControl, gdbOutputStream);
+ fBackend = backend;
+ }
+
+ @Override
+ @ThreadSafeAndProhibitedFromDsfExecutor("getSession#getExecutor")
+ public void destroy() {
+ try {
+ getSession().getExecutor().submit(new DsfRunnable() {
+ public void run() {
+ if (isDisposed() || !getSession().isActive()) return;
+
+ // An inferior will be destroy():interrupt and kill if
+ // - For attach session:
+ // never (we don't kill an independent process.)
+ // - For Program session:
+ // if the inferior is still running.
+ // - For PostMortem(Core): send event
+ // else noop
+ if (fBackend.getIsAttachSession() == false) {
+ // Try to interrupt the inferior, first.
+ if (getState() == State.RUNNING) {
+ fBackend.interrupt();
+ }
+ }
+ }
+ }).get();
+ } catch (RejectedExecutionException e) {
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ } finally {
+ super.destroy();
+ }
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java
new file mode 100644
index 00000000000..3027a783581
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/IGDBControl.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Ericsson and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse 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.command;
+
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
+import org.eclipse.cdt.dsf.mi.service.command.AbstractCLIProcess;
+import org.eclipse.cdt.dsf.mi.service.command.MIInferiorProcess;
+
+public interface IGDBControl extends ICommandControlService {
+
+ void terminate(final RequestMonitor rm);
+ void initInferiorInputOutput(final RequestMonitor requestMonitor);
+
+ boolean canRestart();
+ void start(GdbLaunch launch, final RequestMonitor requestMonitor);
+ void restart(final GdbLaunch launch, final RequestMonitor requestMonitor);
+ void createInferiorProcess();
+
+ boolean isConnected();
+
+ void setConnected(boolean connected);
+
+ AbstractCLIProcess getCLIProcess();
+
+ MIInferiorProcess getInferiorProcess();
+}
\ No newline at end of file
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/CSourceLookup.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/CSourceLookup.java
new file mode 100644
index 00000000000..66f6298071b
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/CSourceLookup.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIEnvironmentDirectory;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+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.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.sourcelookup.ISourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
+import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
+import org.osgi.framework.BundleContext;
+
+/**
+ * ISourceLookup service implementation based on the CDT CSourceLookupDirector.
+ */
+public class CSourceLookup extends AbstractDsfService implements ISourceLookup {
+
+ private Map fDirectors = new HashMap();
+
+ ICommandControl fConnection;
+
+ public CSourceLookup(DsfSession session) {
+ super(session);
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+
+ public void setSourceLookupDirector(ISourceLookupDMContext ctx, CSourceLookupDirector director) {
+ fDirectors.put(ctx, director);
+ }
+
+ public void setSourceLookupPath(ISourceLookupDMContext ctx, ISourceContainer[] containers, RequestMonitor rm) {
+ List pathList = getSourceLookupPath(containers);
+ String[] paths = pathList.toArray(new String[pathList.size()]);
+
+ fConnection.queueCommand(
+ new MIEnvironmentDirectory(ctx, paths, false),
+ new DataRequestMonitor(getExecutor(), rm));
+ }
+
+ private List getSourceLookupPath(ISourceContainer[] containers) {
+ ArrayList list = new ArrayList(containers.length);
+
+ for (int i = 0; i < containers.length; ++i) {
+ if (containers[i] instanceof ProjectSourceContainer) {
+ IProject project = ((ProjectSourceContainer)containers[i]).getProject();
+ if (project != null && project.exists())
+ list.add(project.getLocation().toPortableString());
+ }
+ if (containers[i] instanceof FolderSourceContainer) {
+ IContainer container = ((FolderSourceContainer)containers[i]).getContainer();
+ if (container != null && container.exists())
+ list.add(container.getLocation().toPortableString());
+ }
+ if (containers[i] instanceof DirectorySourceContainer) {
+ File dir = ((DirectorySourceContainer)containers[i]).getDirectory();
+ if (dir != null && dir.exists()) {
+ IPath path = new Path( dir.getAbsolutePath());
+ list.add(path.toPortableString());
+ }
+ }
+ if (containers[i].isComposite()) {
+ try {
+ list.addAll(getSourceLookupPath(containers[i].getSourceContainers()));
+ } catch (CoreException e) {
+ }
+ }
+ }
+
+ return list;
+ }
+
+
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }});
+ }
+
+ private void doInitialize(final RequestMonitor requestMonitor) {
+ fConnection = getServicesTracker().getService(ICommandControl.class);
+
+ // Register this service
+ register(new String[] { CSourceLookup.class.getName(), ISourceLookup.class.getName() }, new Hashtable());
+
+ requestMonitor.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor requestMonitor) {
+ unregister();
+ super.shutdown(requestMonitor);
+ }
+
+ public void getDebuggerPath(ISourceLookupDMContext sourceLookupCtx, Object source, final DataRequestMonitor rm)
+ {
+ if (! (source instanceof String)) {
+ // In future if needed other elements such as URIs could be supported.
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Only string source element is supported", null)); //$NON-NLS-1$);
+ rm.done();
+ return;
+ }
+ final String sourceString = (String) source;
+
+ if (!fDirectors.containsKey(sourceLookupCtx) ){
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "No source director configured for given context", null)); //$NON-NLS-1$);
+ rm.done();
+ return;
+ }
+ final CSourceLookupDirector director = fDirectors.get(sourceLookupCtx);
+
+ new Job("Lookup Debugger Path") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IPath debuggerPath = director.getCompilationPath(sourceString);
+ if (debuggerPath != null) {
+ rm.setData(debuggerPath.toString());
+ } else {
+ rm.setData(sourceString);
+ }
+ rm.done();
+
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+
+ }
+
+ public void getSource(ISourceLookupDMContext sourceLookupCtx, final String debuggerPath, final DataRequestMonitor rm)
+ {
+ if (!fDirectors.containsKey(sourceLookupCtx) ){
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "No source director configured for given context", null)); //$NON-NLS-1$);
+ rm.done();
+ return;
+ }
+ final CSourceLookupDirector director = fDirectors.get(sourceLookupCtx);
+
+ new Job("Lookup Source") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ Object[] sources;
+ try {
+ sources = director.findSourceElements(debuggerPath);
+ if (sources == null || sources.length == 0) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "No sources found", null)); //$NON-NLS-1$);
+ } else {
+ rm.setData(sources[0]);
+ }
+ } catch (CoreException e) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Source lookup failed", e)); //$NON-NLS-1$);
+ } finally {
+ rm.done();
+ }
+
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+}
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/ExpressionService.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/ExpressionService.java
new file mode 100644
index 00000000000..e4b53393621
--- /dev/null
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/ExpressionService.java
@@ -0,0 +1,927 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Ericsson - Modified for handling of multiple execution contexts
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.mi.service;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.cdt.core.IAddress;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMContext;
+import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
+import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
+import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildCount;
+import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildren;
+import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetValue;
+import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetVar;
+import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataEvaluateExpression;
+import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetAttributesInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetChildCountInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetChildrenInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetValueInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetVarInfo;
+import org.eclipse.cdt.dsf.mi.service.command.output.MIDataEvaluateExpressionInfo;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.utils.Addr32;
+import org.eclipse.cdt.utils.Addr64;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.BundleContext;
+
+/**
+ * This class implements a debugger expression evaluator as a DSF service. The
+ * primary interface that clients of this class should use is IExpressions.
+ */
+public class ExpressionService extends AbstractDsfService implements IExpressions, ICachingService {
+
+ /**
+ * This class represents the two expressions that characterize an Expression Context.
+ */
+ public static class ExpressionInfo {
+ private final String fullExpression;
+ private final String relativeExpression;
+
+ public ExpressionInfo(String full, String relative) {
+ fullExpression = full;
+ relativeExpression = relative;
+ }
+
+ public String getFullExpr() { return fullExpression; }
+ public String getRelExpr() { return relativeExpression; }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ExpressionInfo) {
+ if (fullExpression == null ? ((ExpressionInfo) other).fullExpression == null :
+ fullExpression.equals(((ExpressionInfo) other).fullExpression)) {
+ if (relativeExpression == null ? ((ExpressionInfo) other).relativeExpression == null :
+ relativeExpression.equals(((ExpressionInfo) other).relativeExpression)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (fullExpression == null ? 0 : fullExpression.hashCode()) ^
+ (relativeExpression == null ? 0 : relativeExpression.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ return "[" + fullExpression +", " + relativeExpression + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ }
+ }
+ /**
+ * This class represents an expression.
+ */
+ protected static class MIExpressionDMC extends AbstractDMContext implements IExpressionDMContext {
+ /**
+ * This field holds an expression to be evaluated.
+ */
+ private ExpressionInfo exprInfo;
+
+ /**
+ * ExpressionDMC Constructor for expression to be evaluated in context of
+ * a stack frame.
+ *
+ * @param sessionId
+ * The session ID in which this context is created.
+ * @param expression
+ * The expression to be described by this ExpressionDMC
+ * @param relExpr
+ * The relative expression if this expression was created as a child
+ * @param frameCtx
+ * The parent stack frame context for this ExpressionDMC.
+ */
+ public MIExpressionDMC(String sessionId, String expression, String relExpr, IFrameDMContext frameCtx) {
+ this(sessionId, expression, relExpr, (IDMContext)frameCtx);
+ }
+
+ /**
+ * ExpressionDMC Constructor for expression to be evaluated in context of
+ * an thread.
+ *
+ * @param sessionId
+ * The session ID in which this context is created.
+ * @param expression
+ * The expression to be described by this ExpressionDMC
+ * @param relExpr
+ * The relative expression if this expression was created as a child
+ * @param execCtx
+ * The parent thread context for this ExpressionDMC.
+ */
+ public MIExpressionDMC(String sessionId, String expression, String relExpr, IMIExecutionDMContext execCtx) {
+ this(sessionId, expression, relExpr, (IDMContext)execCtx);
+ }
+
+ /**
+ * ExpressionDMC Constructor for expression to be evaluated in context of
+ * a memory space.
+ *
+ * @param sessionId
+ * The session ID in which this context is created.
+ * @param expression
+ * The expression to be described by this ExpressionDMC
+ * @param relExpr
+ * The relative expression if this expression was created as a child
+ * @param memoryCtx
+ * The parent memory space context for this ExpressionDMC.
+ */
+ public MIExpressionDMC(String sessionId, String expression, String relExpr, IMemoryDMContext memoryCtx) {
+ this(sessionId, expression, relExpr, (IDMContext)memoryCtx);
+ }
+
+ private MIExpressionDMC(String sessionId, String expr, String relExpr, IDMContext parent) {
+ super(sessionId, new IDMContext[] { parent });
+ exprInfo = new ExpressionInfo(expr, relExpr);
+ }
+
+ /**
+ * @return True if the two objects are equal, false otherwise.
+ */
+ @Override
+ public boolean equals(Object other) {
+ return super.baseEquals(other) && exprInfo.equals(((MIExpressionDMC)other).exprInfo);
+ }
+
+ /**
+ *
+ * @return The hash code of this ExpressionDMC object.
+ */
+ @Override
+ public int hashCode() {
+ return super.baseHashCode() + exprInfo.hashCode();
+ }
+
+ /**
+ *
+ * @return A string representation of this ExpressionDMC (including the
+ * expression to which it is bound).
+ */
+ @Override
+ public String toString() {
+ return baseToString() + ".expr" + exprInfo.toString(); //$NON-NLS-1$
+ }
+
+ /**
+ * @return The full expression string represented by this ExpressionDMC
+ */
+ public String getExpression() {
+ return exprInfo.getFullExpr();
+ }
+
+ /**
+ * @return The relative expression string represented by this ExpressionDMC
+ */
+ public String getRelativeExpression() {
+ return exprInfo.getRelExpr();
+ }
+ }
+
+ protected static class InvalidContextExpressionDMC extends AbstractDMContext
+ implements IExpressionDMContext
+ {
+ private final String expression;
+
+ public InvalidContextExpressionDMC(String sessionId, String expr, IDMContext parent) {
+ super(sessionId, new IDMContext[] { parent });
+ expression = expr;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return super.baseEquals(other) &&
+ expression == null ? ((InvalidContextExpressionDMC) other).getExpression() == null : expression.equals(((InvalidContextExpressionDMC) other).getExpression());
+ }
+
+ @Override
+ public int hashCode() {
+ return expression == null ? super.baseHashCode() : super.baseHashCode() ^ expression.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return baseToString() + ".invalid_expr[" + expression + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public String getExpression() {
+ return expression;
+ }
+ }
+
+
+ /**
+ * Contains the address of an expression as well as the size of its type.
+ */
+ protected static class ExpressionDMAddress implements IExpressionDMAddress {
+ IAddress fAddr;
+ int fSize;
+
+ public ExpressionDMAddress(IAddress addr, int size) {
+ fAddr = addr;
+ fSize = size;
+ }
+
+ public ExpressionDMAddress(String addrStr, int size) {
+ fSize = size;
+ // We must count the "0x" and that
+ // is why we compare with 10 characters
+ // instead of 8
+ if (addrStr.length() <= 10) {
+ fAddr = new Addr32(addrStr);
+ } else {
+ fAddr = new Addr64(addrStr);
+ }
+ }
+
+ public IAddress getAddress() { return fAddr; }
+ public int getSize() { return fSize; }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ExpressionDMAddress) {
+ ExpressionDMAddress otherAddr = (ExpressionDMAddress) other;
+ return (fSize == otherAddr.getSize()) &&
+ (fAddr == null ? otherAddr.getAddress() == null : fAddr.equals(otherAddr.getAddress()));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (fAddr == null ? 0 :fAddr.hashCode()) + fSize;
+ }
+
+ @Override
+ public String toString() {
+ return (fAddr == null ? "null" : "(0x" + fAddr.toString()) + ", " + fSize + ")"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+ }
+ }
+
+ /**
+ * This class represents the static data referenced by an instance of ExpressionDMC,
+ * such as its type and number of children; it does not contain the value or format
+ * of the expression.
+ */
+ protected static class ExpressionDMData implements IExpressionDMData {
+ // This is the relative expression, such as the name of a field within a structure,
+ // in contrast to the fully-qualified expression contained in the ExpressionDMC,
+ // which refers to the full name, including parent structure.
+ private final String relativeExpression;
+ private final String exprType;
+ private final int numChildren;
+ private final boolean editable;
+
+ /**
+ * ExpressionDMData constructor.
+ */
+ public ExpressionDMData(String expr, String type, int num, boolean edit) {
+ relativeExpression = expr;
+ exprType = type;
+ numChildren = num;
+ editable = edit;
+ }
+
+ public BasicType getBasicType() {
+ return null;
+ }
+
+ public String getEncoding() {
+ return null;
+ }
+
+ public Map getEnumerations() {
+ return new HashMap();
+ }
+
+ public String getName() {
+ return relativeExpression;
+ }
+
+ public IRegisterDMContext getRegister() {
+ return null;
+ }
+
+ // See class VariableVMNode for an example of usage of this method
+ public String getStringValue() {
+ return null;
+ }
+
+ public String getTypeId() {
+ return null;
+ }
+
+ public String getTypeName() {
+ return exprType;
+ }
+
+ public int getNumChildren() {
+ return numChildren;
+ }
+
+ public boolean isEditable() {
+ return editable;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ExpressionDMData) {
+ ExpressionDMData otherData = (ExpressionDMData) other;
+ return (getNumChildren() == otherData.getNumChildren()) &&
+ (getTypeName() == null ? otherData.getTypeName() == null : getTypeName().equals(otherData.getTypeName())) &&
+ (getName() == null ? otherData.getName() == null : getName().equals(otherData.getName()));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return relativeExpression == null ? 0 : relativeExpression.hashCode() +
+ exprType == null ? 0 : exprType.hashCode() + numChildren;
+ }
+
+ @Override
+ public String toString() {
+ return "relExpr=" + relativeExpression + ", type=" + exprType + ", numchildren=" + numChildren; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
+ }
+ }
+
+ /**
+ * Event generated every time an expression is changed by the ExpressionService.
+ *
+ * A client wishing to receive such events has to register as a service
+ * event listener and implement the corresponding eventDispatched method.
+ *
+ * E.g.:
+ *
+ * getSession().addServiceEventListener(listenerObject, null);
+ *
+ * @DsfServiceEventHandler
+ * public void eventDispatched(ExpressionChangedEvent e) {
+ * IExpressionDMContext context = e.getDMContext();
+ * // do something...
+ * }
+ */
+ protected static class ExpressionChangedEvent extends AbstractDMEvent
+ implements IExpressionChangedDMEvent {
+
+ public ExpressionChangedEvent(IExpressionDMContext context) {
+ super(context);
+ }
+ }
+
+ private CommandCache fExpressionCache;
+ private MIVariableManager varManager;
+
+
+ public ExpressionService(DsfSession session) {
+ super(session);
+ }
+
+ /**
+ * This method initializes this service.
+ *
+ * @param requestMonitor
+ * The request monitor indicating the operation is finished
+ */
+ @Override
+ public void initialize(final RequestMonitor requestMonitor) {
+ super.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(requestMonitor);
+ }
+ });
+ }
+
+ /**
+ * This method initializes this service after our superclass's initialize()
+ * method succeeds.
+ *
+ * @param requestMonitor
+ * The call-back object to notify when this service's
+ * initialization is done.
+ */
+ private void doInitialize(RequestMonitor requestMonitor) {
+
+ // Register to receive service events for this session.
+ getSession().addServiceEventListener(this, null);
+
+ // Register this service.
+ register(new String[] { IExpressions.class.getName(),
+ ExpressionService.class.getName() },
+ new Hashtable());
+
+ // Create the expressionService-specific CommandControl which is our
+ // variable object manager.
+ // It will deal with the meta-commands, before sending real MI commands
+ // to the back-end, through the MICommandControl service
+ // It must be created after the ExpressionService is registered
+ // since it will need to find it.
+ varManager = new MIVariableManager(getSession(), getServicesTracker());
+
+ // Create the meta command cache which will use the variable manager
+ // to actually send MI commands to the back-end
+ fExpressionCache = new CommandCache(getSession(), varManager);
+ ICommandControlService commandControl = getServicesTracker().getService(ICommandControlService.class);
+ fExpressionCache.setContextAvailable(commandControl.getContext(), true);
+
+ requestMonitor.done();
+ }
+
+ /**
+ * This method shuts down this service. It unregisters the service, stops
+ * receiving service events, and calls the superclass shutdown() method to
+ * finish the shutdown process.
+ *
+ * @return void
+ */
+ @Override
+ public void shutdown(RequestMonitor requestMonitor) {
+ unregister();
+ varManager.dispose();
+ getSession().removeServiceEventListener(this);
+ super.shutdown(requestMonitor);
+ }
+
+ /**
+ * @return The bundle context of the plug-in to which this service belongs.
+ */
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ /**
+ * Create an expression context with the same full and relative expression
+ */
+ public IExpressionDMContext createExpression(IDMContext ctx, String expression) {
+ return createExpression(ctx, expression, expression);
+ }
+
+ /**
+ * Create an expression context.
+ */
+ public IExpressionDMContext createExpression(IDMContext ctx, String expression, String relExpr) {
+ IFrameDMContext frameDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
+ if (frameDmc != null) {
+ return new MIExpressionDMC(getSession().getId(), expression, relExpr, frameDmc);
+ }
+
+ IMIExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
+ if (execCtx != null) {
+ // If we have a thread context but not a frame context, we give the user
+ // the expression as per the top-most frame of the specified thread.
+ // To do this, we create our own frame context.
+ MIStack stackService = getServicesTracker().getService(MIStack.class);
+ if (stackService != null) {
+ frameDmc = stackService.createFrameDMContext(execCtx, 0);
+ return new MIExpressionDMC(getSession().getId(), expression, relExpr, frameDmc);
+ }
+
+ return new InvalidContextExpressionDMC(getSession().getId(), expression, execCtx);
+ }
+
+ IMemoryDMContext memoryCtx = DMContexts.getAncestorOfType(ctx, IMemoryDMContext.class);
+ if (memoryCtx != null) {
+ return new MIExpressionDMC(getSession().getId(), expression, relExpr, memoryCtx);
+ }
+
+ // Don't care about the relative expression at this point
+ return new InvalidContextExpressionDMC(getSession().getId(), expression, ctx);
+ }
+
+ /**
+ * @see IFormattedValues.getFormattedValueContext(IFormattedDataDMContext, String)
+ *
+ * @param dmc
+ * The context describing the data for which we want to create
+ * a Formatted context.
+ * @param formatId
+ * The format that will be used to create the Formatted context
+ *
+ * @return A FormattedValueDMContext that can be used to obtain the value
+ * of an expression in a specific format.
+ */
+
+ public FormattedValueDMContext getFormattedValueContext(
+ IFormattedDataDMContext dmc, String formatId) {
+ return new FormattedValueDMContext(this, dmc, formatId);
+ }
+
+ /**
+ * @see IFormattedValues.getAvailableFormats(IFormattedDataDMContext, DataRequestMonitor)
+ *
+ * @param dmc
+ * The context describing the data for which we want to know
+ * which formats are available.
+ * @param rm
+ * The data request monitor for this asynchronous operation.
+ *
+ */
+
+ public void getAvailableFormats(IFormattedDataDMContext dmc,
+ final DataRequestMonitor rm) {
+ rm.setData(new String[] { IFormattedValues.BINARY_FORMAT,
+ IFormattedValues.NATURAL_FORMAT, IFormattedValues.HEX_FORMAT,
+ IFormattedValues.OCTAL_FORMAT, IFormattedValues.DECIMAL_FORMAT });
+ rm.done();
+ }
+
+ /**
+ * This method obtains the model data for a given ExpressionDMC object or
+ * for a FormattedValueDMC, or for this DSF service.
+ *
+ * @param dmc
+ * The context for which we are requesting the data
+ * @param rm
+ * The request monitor that will contain the requested data
+ */
+ @SuppressWarnings("unchecked")
+ public void getModelData(IDMContext dmc, DataRequestMonitor> rm) {
+ if (dmc instanceof MIExpressionDMC) {
+ getExpressionData((MIExpressionDMC) dmc,
+ (DataRequestMonitor) rm);
+ } else if (dmc instanceof FormattedValueDMContext) {
+ getFormattedExpressionValue((FormattedValueDMContext) dmc,
+ (DataRequestMonitor) rm);
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /**
+ * Obtains the static data of an expression represented
+ * by an ExpressionDMC object (dmc ).
+ *
+ * @param dmc
+ * The ExpressionDMC for the expression to be evaluated.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getExpressionData(
+ final IExpressionDMContext dmc,
+ final DataRequestMonitor rm)
+ {
+ if (dmc instanceof MIExpressionDMC) {
+ fExpressionCache.execute(
+ new ExprMetaGetVar(dmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(new ExpressionDMData(getData().getExpr(),
+ getData().getType(), getData().getNumChildren(), getData().getEditable()));
+ rm.done();
+ }
+ });
+ } else if (dmc instanceof InvalidContextExpressionDMC) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
+ rm.done();
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid expression context.", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /**
+ * Obtains the address of an expression and the size of its type.
+ *
+ * @param dmc
+ * The ExpressionDMC for the expression.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getExpressionAddressData(
+ IExpressionDMContext dmc,
+ final DataRequestMonitor rm) {
+
+ // First create an address expression and a size expression
+ // to be used in back-end calls
+ final IExpressionDMContext addressDmc =
+ createExpression( dmc, "&(" + dmc.getExpression() + ")" );//$NON-NLS-1$//$NON-NLS-2$
+ final IExpressionDMContext sizeDmc =
+ createExpression( dmc, "sizeof(" + dmc.getExpression() + ")" ); //$NON-NLS-1$//$NON-NLS-2$
+
+ if (addressDmc instanceof InvalidContextExpressionDMC || sizeDmc instanceof InvalidContextExpressionDMC) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
+ rm.done();
+ } else {
+ fExpressionCache.execute(
+ new MIDataEvaluateExpression(addressDmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ String tmpAddrStr = getData().getValue();
+
+ // Deal with adresses of contents of a char* which is in
+ // the form of "0x12345678 \"This is a string\""
+ int split = tmpAddrStr.indexOf(' ');
+ if (split != -1) tmpAddrStr = tmpAddrStr.substring(0, split);
+ final String addrStr = tmpAddrStr;
+
+ fExpressionCache.execute(
+ new MIDataEvaluateExpression(sizeDmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ try {
+ int size = Integer.parseInt(getData().getValue());
+ rm.setData(new ExpressionDMAddress(addrStr, size));
+ } catch (NumberFormatException e) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
+ "Unexpected size format from backend: " + getData().getValue(), null)); //$NON-NLS-1$
+ }
+ rm.done();
+ }
+ });
+ }
+ });
+ }
+ }
+
+ /**
+ * Obtains the value of an expression in a specific format.
+ *
+ * @param dmc
+ * The context for the format of the value requested and
+ * for the expression to be evaluated. The expression context
+ * should be a parent of the FormattedValueDMContext.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getFormattedExpressionValue(
+ final FormattedValueDMContext dmc,
+ final DataRequestMonitor rm)
+ {
+ // We need to make sure the FormattedValueDMContext also holds an ExpressionContext,
+ // or else this method cannot do its work.
+ // Note that we look for MIExpressionDMC and not IExpressionDMC, because getting
+ // looking for IExpressionDMC could yield InvalidContextExpressionDMC which is still
+ // not what we need to have.
+ if (DMContexts.getAncestorOfType(dmc, MIExpressionDMC.class) == null ) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context for evaluating expressions.", null)); //$NON-NLS-1$
+ rm.done();
+ } else {
+ fExpressionCache.execute(
+ new ExprMetaGetValue(dmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData(new FormattedValueDMData(getData().getValue()));
+ rm.done();
+ }
+ });
+ }
+ }
+
+ /* Not implemented
+ *
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.service.IExpressions#getBaseExpressions(org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ public void getBaseExpressions(IExpressionDMContext exprContext,
+ DataRequestMonitor rm) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
+ NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
+ rm.done();
+ }
+
+ /**
+ * Retrieves the children expressions of the specified expression
+ *
+ * @param exprCtx
+ * The context for the expression for which the children
+ * should be retrieved.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getSubExpressions(final IExpressionDMContext dmc,
+ final DataRequestMonitor rm)
+ {
+ if (dmc instanceof MIExpressionDMC) {
+ fExpressionCache.execute(
+ new ExprMetaGetChildren(dmc),
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ ExpressionInfo[] childrenExpr = getData().getChildrenExpressions();
+ IExpressionDMContext[] childArray = new IExpressionDMContext[childrenExpr.length];
+ for (int i=0; i rm) {
+ getSubExpressions(
+ exprCtx,
+ new DataRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData((IExpressionDMContext[])Arrays.asList(getData()).subList(startIndex, startIndex + length).toArray());
+ rm.done();
+ }
+ });
+ }
+
+ /**
+ * Retrieves the count of children expressions of the specified expression
+ *
+ * @param exprCtx
+ * The context for the expression for which the children count
+ * should be retrieved.
+ * @param rm
+ * The data request monitor that will contain the requested data
+ */
+ public void getSubExpressionCount(IExpressionDMContext dmc,
+ final DataRequestMonitor