1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-06 17:26:01 +02:00

Migrated DSF and DSF-GDB to the CDT project.

This commit is contained in:
Pawel Piech 2009-01-08 21:08:05 +00:00
commit 5b47187366
876 changed files with 120844 additions and 0 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.cdt.dsf.gdb.ui</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<component id="org.eclipse.cdt.dsf.gdb.ui" version="2">
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GdbLocalRunLaunchConfigurationTabGroup.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbLocalRunLaunchConfigurationTabGroup">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbLocalRunLaunchConfigurationTabGroup"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="META-INF/MANIFEST.MF">
<filter id="923795461">
<message_arguments>
<message_argument value="1.1.0.qualifier"/>
<message_argument value="1.0.0.v20080609"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GDBSolibBlock.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GDBSolibBlock">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GDBSolibBlock"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GdbAttachLaunchConfigurationTabGroup.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbAttachLaunchConfigurationTabGroup">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbAttachLaunchConfigurationTabGroup"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/IMILaunchConfigurationComponent.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.IMILaunchConfigurationComponent">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.IMILaunchConfigurationComponent"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/CMainTab.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CMainTab">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CMainTab"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/TCPSettingsBlock.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.TCPSettingsBlock">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.TCPSettingsBlock"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GdbServerDebuggerPage.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbServerDebuggerPage">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbServerDebuggerPage"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/SolibSearchPathBlock.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.SolibSearchPathBlock">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.SolibSearchPathBlock"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/LaunchUIMessages.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchUIMessages"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GdbRemoteRunLaunchConfigurationTabGroup.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbRemoteRunLaunchConfigurationTabGroup">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbRemoteRunLaunchConfigurationTabGroup"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/CLaunchConfigurationTab.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CLaunchConfigurationTab">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CLaunchConfigurationTab"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/SerialPortSettingsBlock.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.SerialPortSettingsBlock">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.SerialPortSettingsBlock"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/AbstractCDebuggerTab.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.AbstractCDebuggerTab">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.AbstractCDebuggerTab"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/GdbDebuggerPage.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbDebuggerPage">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbDebuggerPage"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/CDebuggerTab.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CDebuggerTab">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.CDebuggerTab"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/LaunchImages.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchImages">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.LaunchImages"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/ProcessPrompter.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/ui/launching/ICDTLaunchHelpContextIds.java" type="org.eclipse.cdt.dsf.gdb.internal.ui.launching.ICDTLaunchHelpContextIds">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.internal.ui.launching.ICDTLaunchHelpContextIds"/>
<message_argument value="org.eclipse.cdt.dsf.gdb.ui_1.1.0"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head><body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2007</p>
<h3>License</h3>
<p>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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, "Program" will mean the Content.</p>
<p>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 <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body></html>

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

View file

@ -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

View file

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension
point="org.eclipse.debug.ui.launchConfigurationTabGroups">
<launchConfigurationTabGroup
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbLocalRunLaunchConfigurationTabGroup"
id="org.eclipse.cdt.dsf.gdb.launch.localRunLaunchTabGroup"
type="org.eclipse.cdt.dsf.gdb.launch.localCLaunch">
</launchConfigurationTabGroup>
<launchConfigurationTabGroup
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbRemoteRunLaunchConfigurationTabGroup"
id="org.eclipse.cdt.dsf.gdb.launch.remoteRunLaunchTabGroup"
type="org.eclipse.cdt.dsf.gdb.launch.remoteCLaunch">
</launchConfigurationTabGroup>
<launchConfigurationTabGroup
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbAttachLaunchConfigurationTabGroup"
id="org.eclipse.cdt.dsf.gdb.launch.localAttachLaunchTabGroup"
type="org.eclipse.cdt.dsf.gdb.launch.attachCLaunch">
</launchConfigurationTabGroup>
</extension>
<extension
point="org.eclipse.debug.ui.launchConfigurationTypeImages">
<launchConfigurationTypeImage
configTypeID="org.eclipse.cdt.dsf.gdb.launch.localCLaunch"
icon="icons/full/obj16/c_app.gif"
id="org.eclipse.cdt.dsf.gdb.launch.localRunLaunchImage">
</launchConfigurationTypeImage>
<launchConfigurationTypeImage
configTypeID="org.eclipse.cdt.dsf.gdb.launch.remoteCLaunch"
icon="icons/full/obj16/c_app.gif"
id="org.eclipse.cdt.dsf.gdb.launch.remoteRunLaunchImage">
</launchConfigurationTypeImage>
<launchConfigurationTypeImage
configTypeID="org.eclipse.cdt.dsf.gdb.launch.attachCLaunch"
icon="icons/full/obj16/c_app.gif"
id="org.eclipse.cdt.dsf.gdb.launch.attachRunLaunchImage">
</launchConfigurationTypeImage>
</extension>
<extension point="org.eclipse.core.runtime.adapters">
<factory
class="org.eclipse.cdt.dsf.gdb.internal.ui.GdbAdapterFactory"
adaptableType="org.eclipse.cdt.dsf.gdb.launching.GdbLaunch">
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider"/>
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory"/>
<adapter type="org.eclipse.debug.ui.contexts.ISuspendTrigger"/>
<adapter type="org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory"/>
</factory>
</extension>
<extension point="org.eclipse.debug.ui.memoryRenderings">
<renderingBindings
defaultIds="org.eclipse.debug.ui.rendering.raw_memory"
primaryId="org.eclipse.debug.ui.rendering.raw_memory"
renderingIds="org.eclipse.debug.ui.rendering.raw_memory,org.eclipse.debug.ui.rendering.ascii,org.eclipse.debug.ui.rendering.signedint,org.eclipse.debug.ui.rendering.unsignedint">
<enablement>
<instanceof value="org.eclipse.cdt.dsf.debug.model.DsfMemoryBlock"/>
</enablement>
</renderingBindings>
</extension>
<extension point="org.eclipse.ui.propertyPages">
<page class="org.eclipse.cdt.dsf.gdb.internal.ui.breakpoints.CBreakpointGdbThreadFilterPage"
id="org.eclipse.cdt.dsf.gdb.breakpoint.filtering"
name="Filter">
<filter name="debugModelId" value="org.eclipse.cdt.dsf.gdb"/>
<enabledWhen>
<adapt type="org.eclipse.cdt.debug.core.model.ICBreakpoint"/>
</enabledWhen>
</page>
</extension>
<extension
point="org.eclipse.debug.core.statusHandlers">
<statusHandler
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter"
code="100"
id="org.eclipse.cdt.dsf.gdb.ui.processPrompter"
plugin="org.eclipse.cdt.dsf.gdb.ui">
</statusHandler>
</extension>
<extension
point="org.eclipse.cdt.debug.ui.CDebuggerPage">
<debuggerPage
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbDebuggerPage"
debuggerID="org.eclipse.cdt.dsf.gdb.GdbDebugger"
id="org.eclipse.cdt.dsf.gdb.ui.GdbDebuggerPage">
</debuggerPage>
<debuggerPage
class="org.eclipse.cdt.dsf.gdb.internal.ui.launching.GdbServerDebuggerPage"
debuggerID="org.eclipse.cdt.dsf.gdb.GdbServerDebugger"
id="org.eclipse.cdt.dsf.gdb.ui.GdbServerDebuggerPage">
</debuggerPage>
</extension>
<extension
point="org.eclipse.ui.popupMenus">
<viewerContribution
id="org.eclipse.cdt.dsf.gdb.ui.debugview.context"
targetID="org.eclipse.debug.ui.DebugView">
<action
class="org.eclipse.cdt.dsf.gdb.internal.ui.actions.ConnectActionDelegate"
icon="icons/full/obj16/connect.gif"
id="org.eclipse.cdt.dsf.gdb.ui.connect"
label="%action.connect.label"
menubarPath="threadGroup"
tooltip="%action.connect.tooltip">
<enablement>
<pluginState
id="org.eclipse.cdt.dsf.gdb.ui"
value="activated">
</pluginState>
</enablement>
</action>
<visibility>
<pluginState
id="org.eclipse.cdt.dsf.gdb.ui"
value="activated">
</pluginState>
</visibility>
</viewerContribution>
</extension>
<extension
point="org.eclipse.ui.viewActions">
<viewContribution
id="org.eclipse.cdt.dsf.gdb.ui.debugview.toolbar"
targetID="org.eclipse.debug.ui.DebugView">
<action
class="org.eclipse.cdt.dsf.gdb.internal.ui.actions.ConnectActionDelegate"
icon="icons/full/obj16/connect.gif"
id="org.eclipse.cdt.dsf.gdb.ui.connect"
label="%action.connect.label"
toolbarPath="threadGroup"
tooltip="%action.connect.tooltip">
<enablement>
<pluginState
id="org.eclipse.cdt.dsf.gdb.ui"
value="activated">
</pluginState>
</enablement>
</action>
</viewContribution>
</extension>
</plugin>

View file

@ -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<GdbLaunch, SessionAdapterSet> fgLaunchAdapterSets =
Collections.synchronizedMap(new HashMap<GdbLaunch, SessionAdapterSet>());
/**
* 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.
* <p>
* Access to this map is synchronized using the fgLaunchAdapterSets
* instance.
* </p>
*/
private static Map<ILaunch, SessionAdapterSet> fgDisposedLaunchAdapterSets =
new WeakHashMap<ILaunch, SessionAdapterSet>();
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) {
}
}

View file

@ -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 <code>null</code> if none
*
* @return the active workbench shell or <code>null</code> 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$
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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<Boolean> canConnectQuery = new Query<Boolean>() {
@Override
public void execute(DataRequestMonitor<Boolean> 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<Integer> fRequestMonitor;
public PromptForPidJob(String name, IProcessInfo[] procs, DataRequestMonitor<Integer> 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<IProcessDMContext[]>(fExecutor, rm) {
@Override
protected void handleSuccess() {
final List<IProcessInfo> procInfoList = new ArrayList<IProcessInfo>();
// 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<Integer>(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<IDMContext>(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<IThreadDMData> (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();
}
}
});
}
}

View file

@ -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<Boolean>(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;
}
}

View file

@ -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<Boolean> canRestart = new Query<Boolean>() {
@Override
protected void execute(DataRequestMonitor<Boolean> 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<IPath> execPathRef = new AtomicReference<IPath>();
Query<Object> restartQuery = new Query<Object>() {
@Override
protected void execute(final DataRequestMonitor<Object> 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());
}
}
}

View file

@ -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<ProcessInfo> {
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;
}
}

View file

@ -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();
}
}

View file

@ -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<Object> children = new ArrayList<Object>();
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<Object> targets = new ArrayList<Object>();
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<Object> list = new ArrayList<Object>(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<IContainerDMContext> {
@Override
protected void execute(DataRequestMonitor<IContainerDMContext> 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<IExecutionDMContext[]> {
@Override
protected void execute(DataRequestMonitor<IExecutionDMContext[]> 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<String> {
@Override
protected void execute(DataRequestMonitor<String> 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<String> {
@Override
protected void execute(final DataRequestMonitor<String> 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<IThreadDMData>(
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);
}
}

View file

@ -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 <code>ICDebuggerPage</code>
* 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));
}
}

View file

@ -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.
* <p>
* This class may be instantiated. This class is not intended to be subclassed.
* </p>
*/
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 <code>null</code> if empty.
*
* @return text or <code>null</code>
*/
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();
}
}

View file

@ -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<ICDebugConfiguration>() {
public int compare(ICDebugConfiguration c1, ICDebugConfiguration c2) {
return Collator.getInstance().compare(c1.getName(), c2.getName());
}
});
List<ICDebugConfiguration> list = new ArrayList<ICDebugConfiguration>();
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));
}
}

View file

@ -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 <code>null</code> 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;
}
}
}

View file

@ -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.
* <p>
* This class may be instantiated. This class is not intended to be subclassed.
* </p>
*/
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<ICProject> list = new ArrayList<ICProject>(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();
}
}

View file

@ -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 <code>Shared Libraries</code> tab of the <code>GDBDebuggerPage</code>.
*/
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<String, Boolean> 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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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$
}

View file

@ -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.
* <p>
* Implementors are responsible for ensuring that the created control can be accessed via <code>getControl</code>
* </p>
*
* @param parent the parent composite
*/
public void createControl( Composite parent );
/**
* Returns the top level control for this component.
* <p>
* May return <code>null</code> if the control has not been created yet.
* </p>
*
* @return the top level control or <code>null</code>
*/
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 <code>null</code>.
*
* @return whether this component is in a valid state
*/
public boolean isValid(ILaunchConfiguration launchConfig);
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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<String> values = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
Collections.EMPTY_LIST);
ArrayList<Path> paths = new ArrayList<Path>(values.size());
Iterator<String> 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<String> autoSolibs = configuration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_AUTO_SOLIB_LIST, Collections.EMPTY_LIST );
List<File> list = new ArrayList<File>(autoSolibs.size());
Iterator<String> 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<IPath> elements = fDirList.getElements();
ArrayList<String> values = new ArrayList<String>(elements.size());
Iterator<IPath> it = elements.iterator();
while(it.hasNext()) {
values.add((it.next()).toOSString());
}
configuration.setAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH, values);
}
ArrayList<String> autoLibs = new ArrayList<String>(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<IPath> list = fDirList.getElements();
Iterator<IPath> 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<IPath> dirList = fDirList.getSelectedElements();
final HashSet<IPath> libs = new HashSet<IPath>(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();
}
}

View file

@ -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;
}
}
}

View file

@ -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 <code>null</code>
*/
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 <code>null</code> if empty.
*
* @return text or <code>null</code>
*/
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;
}
}

View file

@ -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;
}
}

View file

@ -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<IDMContext[]>(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<IThreadDMData>(getExecutor(), update) {
@Override
public void handleCompleted() {
if (!isSuccess()) {
update.setLabel("<unavailable>", 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<IThreadDMData>(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<IThreadDMData>(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();
}
}
}

View file

@ -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;
}
}

View file

@ -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.
}
}
}

View file

@ -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<IExecutionDMData>(getSession().getExecutor(), update) {
@Override
public void handleCompleted(){
if (!isSuccess()) {
update.setLabel("<unavailable>", 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<IThreadDMData>(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();
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1 @@
org.eclipse.cdt.dsf.gdb/debug = false

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.cdt.dsf.gdb</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<component id="org.eclipse.cdt.dsf.gdb" version="2">
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/GDBDebugger.java" type="org.eclipse.cdt.dsf.gdb.launching.GDBDebugger">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.GDBDebugger"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/IGDBLaunchConfigurationConstants.java" type="org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/LaunchMessages.java" type="org.eclipse.cdt.dsf.gdb.launching.LaunchMessages">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.LaunchMessages"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunchDelegate.java" type="org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControlDMContext.java" type="org.eclipse.cdt.dsf.gdb.service.command.GDBControlDMContext">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.service.command.GDBControlDMContext"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/ShutdownSequence.java" type="org.eclipse.cdt.dsf.gdb.launching.ShutdownSequence">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.ShutdownSequence"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/breakpoints/CBreakpointGdbThreadsFilterExtension.java" type="org.eclipse.cdt.dsf.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="META-INF/MANIFEST.MF">
<filter id="923795461">
<message_arguments>
<message_argument value="1.1.0.qualifier"/>
<message_argument value="1.0.0.v20080609"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/GDBServerDebugger.java" type="org.eclipse.cdt.dsf.gdb.launching.GDBServerDebugger">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.GDBServerDebugger"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/service/command/GDBControl.java" type="org.eclipse.cdt.dsf.gdb.service.command.GDBControl">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.service.command.GDBControl"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/FinalLaunchSequence.java" type="org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.FinalLaunchSequence"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/GdbLaunch.java" type="org.eclipse.cdt.dsf.gdb.launching.GdbLaunch">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.GdbLaunch"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/launching/ServicesLaunchSequence.java" type="org.eclipse.cdt.dsf.gdb.launching.ServicesLaunchSequence">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.launching.ServicesLaunchSequence"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/dd/gdb/internal/provisional/service/GDBRunControl.java" type="org.eclipse.cdt.dsf.gdb.service.GDBRunControl">
<filter id="305365105">
<message_arguments>
<message_argument value="org.eclipse.cdt.dsf.gdb.service.GDBRunControl"/>
<message_argument value="org.eclipse.dd.gdb_1.1.0"/>
</message_arguments>
</filter>
</resource>
</component>

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,24 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>About</title></head><body lang="EN-US">
<h2>About This Content</h2>
<p>June 5, 2007</p>
<h3>License</h3>
<p>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 <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
For purposes of the EPL, "Program" will mean the Content.</p>
<p>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 <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
</body></html>

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
<extension point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
delegate="org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate"
public="true"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer"
name="C/C++ Local Application (Experimental - DSF)"
id="org.eclipse.cdt.dsf.gdb.launch.localCLaunch"
modes="debug">
</launchConfigurationType>
<launchConfigurationType
delegate="org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate"
id="org.eclipse.cdt.dsf.gdb.launch.remoteCLaunch"
modes="debug"
name="C/C++ Remote Application (Experimental - DSF)"
public="true"
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer">
</launchConfigurationType>
<launchConfigurationType
delegate="org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate"
id="org.eclipse.cdt.dsf.gdb.launch.attachCLaunch"
modes="debug"
name="C/C++ Attach to Running Application (Experimental - DSF)"
public="true"
sourceLocatorId="org.eclipse.cdt.debug.core.sourceLocator"
sourcePathComputerId="org.eclipse.cdt.debug.core.sourcePathComputer">
</launchConfigurationType>
</extension>
<extension
point="org.eclipse.cdt.debug.core.BreakpointExtension">
<breakpointExtension
class="org.eclipse.cdt.dsf.gdb.breakpoints.CBreakpointGdbThreadsFilterExtension"
debugModelId="org.eclipse.cdt.dsf.gdb"
id="org.eclipse.cdt.dsf.gdb.threadFilter"
markerType="org.eclipse.cdt.debug.core.cBreakpointMarker">
</breakpointExtension>
</extension>
<!-- Binding debug model ids to context. Use the same bindings as CDT -->
<extension point="org.eclipse.debug.ui.debugModelContextBindings">
<modelContextBinding
contextId="org.eclipse.cdt.debug.ui.debugging"
debugModelId="org.eclipse.cdt.dsf.gdb"/>
</extension>
<extension
point="org.eclipse.cdt.debug.core.CDebugger">
<debugger
class="org.eclipse.cdt.dsf.gdb.launching.GDBDebugger"
cpu="native"
id="org.eclipse.cdt.dsf.gdb.GdbDebugger"
modes="dsf"
name="gdb/mi"
platform="*">
</debugger>
<debugger
class="org.eclipse.cdt.dsf.gdb.launching.GDBServerDebugger"
cpu="*"
id="org.eclipse.cdt.dsf.gdb.GdbServerDebugger"
modes="dsf"
name="gdbserver Debugger"
platform="*">
</debugger>
</extension>
</plugin>

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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<IContainerDMContext,Set<IExecutionDMContext>> fFilteredThreadsByTarget =
new HashMap<IContainerDMContext,Set<IExecutionDMContext>>(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<IContainerDMContext> 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<IExecutionDMContext> 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<IExecutionDMContext> 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<IExecutionDMContext>( Arrays.asList( threads ) ) );
}
}
}

View file

@ -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<Object> launchShutdownQuery = new Query<Object>() {
@Override
protected void execute(DataRequestMonitor<Object> 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();
}
}

View file

@ -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<MIInfo>(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<MIInfo>(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<MIInfo>(getExecutor(), requestMonitor));
} else {
requestMonitor.done();
}
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot get inferior arguments", e)); //$NON-NLS-1$
requestMonitor.done();
}
}},
/*
* 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<MIInfo>(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<MIInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
fCommandControl.queueCommand(
new RawCommand(fCommandControl.getContext(), "set pagination off"), //$NON-NLS-1$
new DataRequestMonitor<MIInfo>(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
fCommandControl.queueCommand(
new MIGDBSetNonStop(fCommandControl.getContext(), true),
new DataRequestMonitor<MIInfo>(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<MIInfo>(getExecutor(), requestMonitor));
} catch (CoreException e) {
requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot set shared library option", e)); //$NON-NLS-1$
requestMonitor.done();
}
}},
/*
* Set the shared library paths
*/
new Step() { @Override
public void execute(final RequestMonitor requestMonitor) {
try {
List<String> p = fGDBBackend.getSharedLibraryPaths();
if (p.size() > 0) {
String[] paths = p.toArray(new String[p.size()]);
fCommandControl.queueCommand(
new MIGDBSetSolibSearchPath(fCommandControl.getContext(), paths),
new DataRequestMonitor<MIInfo>(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<MIInfo>(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<MIInfo>(getExecutor(), requestMonitor));
} else {
if (!getSerialDevice(requestMonitor)) return;
fCommandControl.queueCommand(
new MITargetSelect(fCommandControl.getContext(),
fSerialDevice, fAttach),
new DataRequestMonitor<MIInfo>(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<IDMContext>(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;
}
}

View file

@ -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 {}

View file

@ -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 {}

View file

@ -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<Object>() {
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<MIInferiorProcess>() {
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<AbstractCLIProcess>() {
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.
* <p>
* 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}.
* </p>
* @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);
}
}

View file

@ -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<Object> launchShutdownQuery = new Query<Object>() {
@Override
protected void execute(DataRequestMonitor<Object> 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<IProject> getReferencedProjectSet(IProject proj, HashSet<IProject> 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<IProject> orderedProjList = null;
ICProject cProject = LaunchUtils.verifyCProject(configuration);
if (cProject != null) {
HashSet<IProject> projectSet = getReferencedProjectSet(cProject.getProject(), new HashSet<IProject>());
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<IProject> unorderedProjects = new ArrayList<IProject>(projectSet.size());
unorderedProjects.addAll(projectSet);
orderedProjList = new ArrayList<IProject>(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);
}
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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
* <code>null</code> 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;
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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.<br>
* <br>
* 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<String> 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<String> getSharedLibraryPaths() throws CoreException {
if (fSharedLibPaths == null) {
fSharedLibPaths = fLaunchConfiguration.getAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_SOLIB_PATH,
new ArrayList<String>(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<String,String>());
/*
* 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();
}
}
}
}
}

View file

@ -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<String, String>());
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<MemoryByte[]> 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);
}
}

View file

@ -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<Integer, String> fProcessNames = new HashMap<Integer, String>();
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<String, String>());
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<IThreadDMData> 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<Boolean> 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<IDMContext> rm) {
super.attachDebuggerToProcess(
procCtx,
new DataRequestMonitor<IDMContext>(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<Boolean> 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<IDMContext[]> 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<IProcessDMContext[]> 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<CLIMonitorListProcessesInfo>(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<procDmcs.length; i++) {
procDmcs[i] = createProcessContext(controlDmc, Integer.toString(processes[i].getPid()));
}
return procDmcs;
}
@Override
public void terminate(IThreadDMContext thread, RequestMonitor rm) {
if (thread instanceof IMIProcessDMContext) {
fGdb.terminate(rm);
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
rm.done();
}
}
}

View file

@ -0,0 +1,884 @@
/*******************************************************************************
* 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.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
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.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.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.IRunControl.IContainerResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
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.IMIExecutionDMContext;
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.commands.MIListThreadGroups;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITargetAttach;
import org.eclipse.cdt.dsf.mi.service.command.commands.MITargetDetach;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIThreadInfo;
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupCreatedEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupExitedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MINotifyAsyncOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
import org.eclipse.cdt.dsf.mi.service.command.output.MIThread;
import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo;
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;
/**
* This class implements the IProcesses interface for GDB 7.0
* Actually, I'm not sure what the next version of GDB will be, so technically,
* it is the one after GDB 6.8, as long as it contains multi-process support,
* which really mean it supports the new -list-thread-groups command.
*
*/
public class GDBProcesses_7_0 extends AbstractDsfService
implements IGDBProcesses, ICachingService, IEventListener {
// Below is the context hierarchy that is implemented between the
// MIProcesses service and the MIRunControl service for the MI
// implementation of DSF:
//
// MIControlDMContext
// |
// MIProcessDMC (IProcess)
// MIContainerDMC _____/ |
// (IContainer) |
// | MIThreadDMC (IThread)
// MIExecutionDMC _____/
// (IExecution)
//
/**
* Context representing a thread in GDB/MI
*/
@Immutable
private static class MIExecutionDMC extends AbstractDMContext
implements IMIExecutionDMContext
{
/**
* String ID that is used to identify the thread in the GDB/MI protocol.
*/
private final String fThreadId;
/**
* Constructor for the context. It should not be called directly by clients.
* Instead clients should call {@link IMIProcesses#createExecutionContext()}
* to create instances of this context based on the thread ID.
* <p/>
*
* @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.
* <p/>
*
* @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.
* <p/>
*
* @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<IExecutionDMContext>
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<IExecutionDMContext>
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<String, String> fThreadToGroupMap = new HashMap<String, String>();
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<String, String> fProcessNames = new HashMap<String, String>();
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<String, String>());
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<IMIExecutionDMContext> execDmcList = new ArrayList<IMIExecutionDMContext>();
Iterator<Map.Entry<String, String>> iterator = fThreadToGroupMap.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String, String> 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<IThreadDMData>) 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<IThreadDMData> 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<MIThreadInfoInfo>(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<IDMContext> 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<Boolean> rm) {
IGDBBackend backend = getServicesTracker().getService(IGDBBackend.class);
rm.setData(backend.getIsAttachSession());
rm.done();
}
public void attachDebuggerToProcess(final IProcessDMContext procCtx, final DataRequestMonitor<IDMContext> rm) {
if (procCtx instanceof IMIProcessDMContext) {
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx, ICommandControlDMContext.class);
fCommandControl.queueCommand(
new MITargetAttach(controlDmc, ((IMIProcessDMContext)procCtx).getProcId()),
new DataRequestMonitor<MIInfo>(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<Boolean> 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<MIInfo>(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<Boolean> rm) {
rm.setData(true);
rm.done();
}
public void isDebugNewProcessSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
rm.setData(false);
rm.done();
}
public void debugNewProcess(IDMContext dmc, String file,
Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
rm.done();
}
public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> 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<MIListThreadGroupsInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(makeExecutionDMCs(containerDmc, getData().getThreadInfo().getThreadList()));
rm.done();
}
});
} else {
fContainerCommandCache.execute(
new MIListThreadGroups(controlDmc),
new DataRequestMonitor<MIListThreadGroupsInfo>(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<IProcessDMContext[]> 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<MIListThreadGroupsInfo>(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<procDmcs.length; i++) {
procDmcs[i] = createProcessContext(controlDmc, processes[i].getGroupId());
}
return procDmcs;
}
public void isRunNewProcessSupported(IDMContext dmc, DataRequestMonitor<Boolean> rm) {
rm.setData(false);
rm.done();
}
public void runNewProcess(IDMContext dmc, String file,
Map<String, Object> attributes, DataRequestMonitor<IProcessDMContext> 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<Map.Entry<String, String>> iterator = fThreadToGroupMap.entrySet().iterator();
while (iterator.hasNext()){
if (iterator.next().getValue().equals(groupId)) {
iterator.remove();
}
}
}
}
}
}
}
}
}
}

View file

@ -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<String,String>());
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<Boolean>(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<IExecutionDMContext[]> rm) {
fProcService.getProcessesBeingDebugged(
containerDmc,
new DataRequestMonitor<IDMContext[]>(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<IExecutionDMContext> list = Arrays.asList(ctxts);
List<IExecutionDMContext> oldThreadList = Arrays.asList(fOldExecutionCtxts);
Iterator<IExecutionDMContext> 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());
}
}
}
}

View file

@ -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<String,String>());
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<Boolean>(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<IExecutionDMContext[]> rm) {
fProcService.getProcessesBeingDebugged(
containerDmc,
new DataRequestMonitor<IDMContext[]>(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();
}
});
}
}

View file

@ -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 <V> DMC that this event refers to
* @param <T> MIInfo object that is the direct cause of this event
* @see MIRunControl
*/
@Immutable
private static class RunControlEvent<V extends IDMContext, T extends MIEvent<? extends IDMContext>> extends AbstractDMEvent<V>
implements IDMEvent<V>, IMIDMEvent
{
final private T fMIInfo;
public RunControlEvent(V dmc, T miInfo) {
super(dmc);
fMIInfo = miInfo;
}
public T getMIEvent() { return fMIInfo; }
}
/**
* Indicates that the given thread has been suspended.
*/
@Immutable
private static class SuspendedEvent extends RunControlEvent<IExecutionDMContext, MIStoppedEvent>
implements ISuspendedDMEvent
{
SuspendedEvent(IExecutionDMContext ctx, MIStoppedEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
if (getMIEvent() instanceof MIBreakpointHitEvent) {
return StateChangeReason.BREAKPOINT;
} else if (getMIEvent() instanceof MISteppingRangeEvent) {
return StateChangeReason.STEP;
} else if (getMIEvent() instanceof MISharedLibEvent) {
return StateChangeReason.SHAREDLIB;
}else if (getMIEvent() instanceof MISignalEvent) {
return StateChangeReason.SIGNAL;
}else if (getMIEvent() instanceof MIWatchpointTriggerEvent) {
return StateChangeReason.WATCHPOINT;
}else if (getMIEvent() instanceof MIErrorEvent) {
return StateChangeReason.ERROR;
}else {
return StateChangeReason.USER_REQUEST;
}
}
}
@Immutable
private static class ResumedEvent extends RunControlEvent<IExecutionDMContext, MIRunningEvent>
implements IResumedDMEvent
{
ResumedEvent(IExecutionDMContext ctx, MIRunningEvent miInfo) {
super(ctx, miInfo);
}
public StateChangeReason getReason() {
switch(getMIEvent().getType()) {
case MIRunningEvent.CONTINUE:
return StateChangeReason.USER_REQUEST;
case MIRunningEvent.NEXT:
case MIRunningEvent.NEXTI:
return StateChangeReason.STEP;
case MIRunningEvent.STEP:
case MIRunningEvent.STEPI:
return StateChangeReason.STEP;
case MIRunningEvent.FINISH:
return StateChangeReason.STEP;
case MIRunningEvent.UNTIL:
case MIRunningEvent.RETURN:
break;
}
return StateChangeReason.UNKNOWN;
}
}
@Immutable
private static class StartedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadCreatedEvent>
implements IStartedDMEvent
{
StartedDMEvent(IMIExecutionDMContext executionDmc, MIThreadCreatedEvent miInfo) {
super(executionDmc, miInfo);
}
}
@Immutable
private static class ExitedDMEvent extends RunControlEvent<IExecutionDMContext,MIThreadExitEvent>
implements IExitedDMEvent
{
ExitedDMEvent(IMIExecutionDMContext executionDmc, MIThreadExitEvent miInfo) {
super(executionDmc, miInfo);
}
}
protected class MIThreadRunState {
// State flags
boolean fSuspended = false;
boolean fResumePending = false;
boolean fStepping = false;
StateChangeReason fStateChangeReason;
}
///////////////////////////////////////////////////////////////////////////
// MIRunControlNS
///////////////////////////////////////////////////////////////////////////
private ICommandControlService fConnection;
private boolean fTerminated = false;
// ThreadStates indexed by the execution context
protected Map<IMIExecutionDMContext, MIThreadRunState> fThreadRunStates = new HashMap<IMIExecutionDMContext, MIThreadRunState>();
///////////////////////////////////////////////////////////////////////////
// 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<String,String>());
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<IExecutionDMData>) 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<Boolean> 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<MIInfo>(getExecutor(), rm));
}
private void doSuspendContainer(IContainerDMContext context, final RequestMonitor rm) {
MIExecInterrupt cmd = new MIExecInterrupt(context, true);
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Resume
// ------------------------------------------------------------------------
public void canResume(IExecutionDMContext context, DataRequestMonitor<Boolean> rm) {
// Thread case
if (context instanceof 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<MIInfo>(getExecutor(), rm));
}
private void doResumeContainer(IContainerDMContext context, final RequestMonitor rm) {
MIExecContinue cmd = new MIExecContinue(context, true);
fConnection.queueCommand(cmd, new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Step
// ------------------------------------------------------------------------
public boolean isStepping(IExecutionDMContext context) {
// If it's a thread, just look it up
if (context instanceof 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<Boolean> 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<MIInfo>(getExecutor(), rm));
break;
case STEP_OVER:
fConnection.queueCommand(new MIExecNext(dmc),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
break;
case STEP_RETURN:
// The -exec-finish command operates on the selected stack frame, but here we always
// want it to operate on the stop stack frame. So we manually create a top-frame
// context to use with the MI command.
// We get a local instance of the stack service because the stack service can be shut
// down before the run control service is shut down. So it is possible for the
// getService() request below to return null.
MIStack stackService = getServicesTracker().getService(MIStack.class);
if (stackService != null) {
IFrameDMContext topFrameDmc = stackService.createFrameDMContext(dmc, 0);
fConnection.queueCommand(new MIExecFinish(topFrameDmc),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
} else {
rm.setStatus(new Status(IStatus.ERROR, 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<MIInfo>(getExecutor(), rm));
break;
case INSTRUCTION_STEP_OVER:
fConnection.queueCommand(new MIExecNextInstruction(dmc),
new DataRequestMonitor<MIInfo>(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<MIInfo> 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<MIInfo>(getExecutor(), rm));
}
// ------------------------------------------------------------------------
// Support functions
// ------------------------------------------------------------------------
public void getExecutionContexts(final IContainerDMContext containerDmc, final DataRequestMonitor<IExecutionDMContext[]> rm) {
IMIProcesses procService = getServicesTracker().getService(IMIProcesses.class);
procService.getProcessesBeingDebugged(
containerDmc,
new DataRequestMonitor<IDMContext[]>(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<IExecutionDMData> 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) {
}
}

View file

@ -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> V createService(Class<V> 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);
}
}

View file

@ -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);
}
}

View file

@ -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.<br>
* <br>
* 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. <br>
* <br>
* Here are some special cases: <br>
* 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. <br>
* 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)<br>
*
* @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<String> 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();
}

View file

@ -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);
}

View file

@ -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 }

View file

@ -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:<br>
* - CLI console support,<br>
* - inferior process status tracking.<br>
*/
public class GDBControl extends AbstractMIControl implements IGDBControl {
/**
* Event indicating that the back end process has started.
*/
private static class GDBControlInitializedDMEvent extends AbstractDMEvent<ICommandControlDMContext>
implements ICommandControlInitializedDMEvent
{
public GDBControlInitializedDMEvent(ICommandControlDMContext context) {
super(context);
}
}
/**
* Event indicating that the CommandControl (back end process) has terminated.
*/
private static class GDBControlShutdownDMEvent extends AbstractDMEvent<ICommandControlDMContext>
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<MIInfo>(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<MIInfo>(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<MIInfo> 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<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(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<MIBreakInsertInfo>(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<String,String>());
getSession().dispatchEvent(new GDBControlInitializedDMEvent(fControlDmc), getProperties());
requestMonitor.done();
}
@Override
protected void shutdown(RequestMonitor requestMonitor) {
unregister();
getSession().removeServiceEventListener(GDBControl.this);
requestMonitor.done();
}
}
}

View file

@ -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);
}
}

View file

@ -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:<br>
* - CLI console support,<br>
* - inferior process status tracking.<br>
*/
public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
/**
* Event indicating that the back end process has started.
*/
private static class GDBControlInitializedDMEvent extends AbstractDMEvent<ICommandControlDMContext>
implements ICommandControlInitializedDMEvent
{
public GDBControlInitializedDMEvent(ICommandControlDMContext context) {
super(context);
}
}
/**
* Event indicating that the CommandControl (back end process) has terminated.
*/
private static class GDBControlShutdownDMEvent extends AbstractDMEvent<ICommandControlDMContext>
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<MIInfo>(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<MIInfo>(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<MIInfo> 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<MIInfo> execMonitor = new DataRequestMonitor<MIInfo>(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<MIBreakInsertInfo>(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<String,String>());
getSession().dispatchEvent(new GDBControlInitializedDMEvent(fControlDmc), getProperties());
requestMonitor.done();
}
@Override
protected void shutdown(RequestMonitor requestMonitor) {
unregister();
getSession().removeServiceEventListener(GDBControl_7_0.this);
requestMonitor.done();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}

View file

@ -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<ISourceLookupDMContext,CSourceLookupDirector> fDirectors = new HashMap<ISourceLookupDMContext,CSourceLookupDirector>();
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<String> pathList = getSourceLookupPath(containers);
String[] paths = pathList.toArray(new String[pathList.size()]);
fConnection.queueCommand(
new MIEnvironmentDirectory(ctx, paths, false),
new DataRequestMonitor<MIInfo>(getExecutor(), rm));
}
private List<String> getSourceLookupPath(ISourceContainer[] containers) {
ArrayList<String> list = new ArrayList<String>(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<String, String>());
requestMonitor.done();
}
@Override
public void shutdown(final RequestMonitor requestMonitor) {
unregister();
super.shutdown(requestMonitor);
}
public void getDebuggerPath(ISourceLookupDMContext sourceLookupCtx, Object source, final DataRequestMonitor<String> 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<Object> 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();
}
}

View file

@ -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<String, Integer> getEnumerations() {
return new HashMap<String, Integer>();
}
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<IExpressionDMContext>
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<String, String>());
// 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<String[]> 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<IExpressionDMData>) rm);
} else if (dmc instanceof FormattedValueDMContext) {
getFormattedExpressionValue((FormattedValueDMContext) dmc,
(DataRequestMonitor<FormattedValueDMData>) 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 (<tt>dmc</tt>).
*
* @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<IExpressionDMData> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetVar(dmc),
new DataRequestMonitor<ExprMetaGetVarInfo>(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<IExpressionDMAddress> 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<MIDataEvaluateExpressionInfo>(addressDmc),
new DataRequestMonitor<MIDataEvaluateExpressionInfo>(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<MIDataEvaluateExpressionInfo>(sizeDmc),
new DataRequestMonitor<MIDataEvaluateExpressionInfo>(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<FormattedValueDMData> 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<ExprMetaGetValueInfo>(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<IExpressionDMContext[]> 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<IExpressionDMContext[]> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetChildren(dmc),
new DataRequestMonitor<ExprMetaGetChildrenInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
ExpressionInfo[] childrenExpr = getData().getChildrenExpressions();
IExpressionDMContext[] childArray = new IExpressionDMContext[childrenExpr.length];
for (int i=0; i<childArray.length; i++) {
childArray[i] = createExpression(
dmc.getParents()[0],
childrenExpr[i].getFullExpr(),
childrenExpr[i].getRelExpr());
}
rm.setData(childArray);
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();
}
}
/**
* Retrieves a range of children expressions of the specified expression
*
* @param exprCtx
* The context for the expression for which the children
* should be retrieved.
* @param startIndex
* The starting index within the list of all children of the parent
* expression.
* @param length
* The length or number of elements of the range requested
* @param rm
* The data request monitor that will contain the requested data
*/
public void getSubExpressions(IExpressionDMContext exprCtx, final int startIndex,
final int length, final DataRequestMonitor<IExpressionDMContext[]> rm) {
getSubExpressions(
exprCtx,
new DataRequestMonitor<IExpressionDMContext[]>(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<Integer> rm)
{
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetChildCount(dmc),
new DataRequestMonitor<ExprMetaGetChildCountInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(getData().getChildNum());
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();
}
}
/**
* This method indicates if an expression can be written to.
*
* @param dmc: The data model context representing an expression.
*
* @param rm: Data Request monitor containing True if this expression's value can be edited. False otherwise.
*/
public void canWriteExpression(IExpressionDMContext dmc, final DataRequestMonitor<Boolean> rm) {
if (dmc instanceof MIExpressionDMC) {
fExpressionCache.execute(
new ExprMetaGetAttributes(dmc),
new DataRequestMonitor<ExprMetaGetAttributesInfo>(getExecutor(), rm) {
@Override
protected void handleSuccess() {
rm.setData(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();
}
}
/**
* Changes the value of the specified expression based on the new value and format.
*
* @param expressionContext
* The context for the expression for which the value
* should be changed.
* @param expressionValue
* The new value for the specified expression
* @param formatId
* The format in which the value is specified
* @param rm
* The request monitor that will indicate the completion of the operation
*/
public void writeExpression(final IExpressionDMContext dmc, String expressionValue,
String formatId, final RequestMonitor rm) {
if (dmc instanceof MIExpressionDMC) {
// This command must not be cached, since it changes the state of the back-end.
// We must send it directly to the variable manager
varManager.writeValue(
dmc,
expressionValue,
formatId,
new RequestMonitor(getExecutor(), rm) {
@Override
protected void handleSuccess() {
// A value has changed, we should remove any references to that
// value in our cache. Since we don't have such granularity,
// we must clear the entire cache.
// We cannot use the context to do a more-specific reset, because
// the same global variable can be set with different contexts
fExpressionCache.reset();
// Issue event that the expression has changed
getSession().dispatchEvent(new ExpressionChangedEvent(dmc), getProperties());
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();
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.IResumedDMEvent e) {
fExpressionCache.setContextAvailable(e.getDMContext(), false);
if (e.getReason() != StateChangeReason.STEP) {
fExpressionCache.reset();
}
}
@DsfServiceEventHandler
public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
fExpressionCache.setContextAvailable(e.getDMContext(), true);
fExpressionCache.reset();
}
@DsfServiceEventHandler
public void eventDispatched(IMemoryChangedEvent e) {
fExpressionCache.reset();
// MIVariableManager separately traps this event
}
/**
* {@inheritDoc}
* @since 1.1
*/
public void flushCache(IDMContext context) {
fExpressionCache.reset(context);
// We must also mark all variable objects as out-of-date
// to refresh them as well
varManager.markAllOutOfDate();
}
}

View file

@ -0,0 +1,91 @@
/*******************************************************************************
* 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
* Nokia - create and use backend service.
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.cdt.dsf.concurrent.Immutable;
import org.eclipse.cdt.dsf.service.IDsfService;
/**
* Service for controlling the back end process.
* @since 1.1
*/
public interface IMIBackend extends IDsfService {
public enum State { NOT_INITIALIZED, STARTED, TERMINATED };
/**
* Event indicating that the back end process has started.
*/
@Immutable
public static class BackendStateChangedEvent {
final private String fSessionId;
final private String fBackendId;
final private State fState;
public BackendStateChangedEvent(String sessionId, String backendId, State state) {
fSessionId = sessionId;
fBackendId = backendId;
fState = state;
}
public String getSessionId() {
return fSessionId;
}
public String getBackendId() {
return fBackendId;
}
public State getState() {
return fState;
}
}
/**
* Returns the identifier of this backend service. It can be used
* to distinguish between multiple instances of this service in a
* single session.
*/
public String getId();
/**
* Requests that the backend be immediately terminated.
*/
public void destroy();
/**
* Returns the current state of the backed.
* @return
*/
public State getState();
/**
* Returns the exit code of the backend. Returns <code>-1</code> if
* the backend exit code is not available.
* @return
*/
public int getExitCode();
/**
* Returns the backend command stream.
*/
public InputStream getMIInputStream();
/**
* Returns the backend result and event stream.
* @return
*/
public OutputStream getMIOutputStream();
}

View file

@ -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.mi.service;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
/**
* An container context object. In the GDB/MI protocol, thread groups
* are used as containers of threads, and are represented by a string
* identifier. These thread groups are the basis for this context.
* @since 1.1
*/
public interface IMIContainerDMContext extends IContainerDMContext
{
/**
* Returns the GDB/MI thread group identifier of this context.
*/
public String getGroupId();
}

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* 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 org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
/**
* An execution context object. In the GDB/MI protocol, threads are represented
* by an integer identifier, which is the basis for this context. The parent of this
* context should always be a container context.
*/
public interface IMIExecutionDMContext extends IExecutionDMContext
{
/**
* Returns the GDB/MI thread identifier of this context.
* @return
*/
public int getThreadId();
}

View file

@ -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:
* Ercisson - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
/**
* A process context object. In the GDB/MI protocol, processes are represented
* by an string identifier, which is the basis for this context.
* @since 1.1
*/
public interface IMIProcessDMContext extends IProcessDMContext {
/**
* Returns the GDB/MI process identifier of this context.
* @return
*/
public String getProcId();
}

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* 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.mi.service;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
/**
* This interface provides a method for creating execution contexts.
* @since 1.1
*/
public interface IMIProcesses extends IProcesses
{
/**
* Create a thread context.
*
* @param processDmc The parent process context
* @param threadId The OS Id of the thread
*/
IThreadDMContext createThreadContext(IProcessDMContext processDmc, String threadId);
/**
* Create a process context.
*
* @param pid The OS Id of the process
*/
IProcessDMContext createProcessContext(ICommandControlDMContext controlDmc, String pid);
/**
* Create an execution context.
*
* @param containerDmc The parent process debugging context
* @param threadDmc The parent thread context
* @param threadId The thread id of the thread
*/
IMIExecutionDMContext createExecutionContext(IContainerDMContext containerDmc,
IThreadDMContext threadDmc,
String threadId);
/**
* Create a container context.
*
* @param processDmc The parent process context of this context
* @param groupId The thread group id of the process
*/
IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId);
/**
* Create a container context based on a threadId. This implies knowledge
* of which threads belong to which container.
*
* @param controlDmc The parent command control context of this context
* @param threadId The thread id belonging to the container we want to create
*/
IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId);
}

View file

@ -0,0 +1,267 @@
/*******************************************************************************
* Copyright (c) 2007 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.mi.service;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.utils.Addr64;
public class MIBreakpointDMData implements IBreakpointDMData {
/**
* MI-specific breakpoint attributes markers.
*/
public static final String DSFMIBREAKPOINT = "org.eclipse.cdt.dsf.debug.breakpoint.mi"; //$NON-NLS-1$
public static final String NUMBER = DSFMIBREAKPOINT + ".number"; //$NON-NLS-1$
public static final String TYPE = DSFMIBREAKPOINT + ".type"; //$NON-NLS-1$
public static final String THREAD_ID = DSFMIBREAKPOINT + ".threadId"; //$NON-NLS-1$
public static final String FULL_NAME = DSFMIBREAKPOINT + ".fullName"; //$NON-NLS-1$
public static final String HITS = DSFMIBREAKPOINT + ".hits"; //$NON-NLS-1$
public static final String IS_TEMPORARY = DSFMIBREAKPOINT + ".isTemporary"; //$NON-NLS-1$
public static final String IS_HARDWARE = DSFMIBREAKPOINT + ".isHardware"; //$NON-NLS-1$
public static final String LOCATION = DSFMIBREAKPOINT + ".location"; //$NON-NLS-1$
// Back-end breakpoint object
private final MIBreakpoint fBreakpoint;
private final Map<String, Object> fProperties;
// Breakpoint types
public static enum MIBreakpointNature { UNKNOWN, BREAKPOINT, WATCHPOINT, CATCHPOINT };
private final MIBreakpointNature fNature;
///////////////////////////////////////////////////////////////////////////
// Constructors
///////////////////////////////////////////////////////////////////////////
/**
* Copy constructor
*
* @param other
*/
public MIBreakpointDMData(MIBreakpointDMData other) {
fBreakpoint = new MIBreakpoint(other.fBreakpoint);
fProperties = new HashMap<String, Object>(other.fProperties);
fNature = other.fNature;
}
/**
* Constructs a DsfMIBreakpoint from a back-end object
*
* @param dsfMIBreakpoint back-end breakpoint
*/
public MIBreakpointDMData(MIBreakpoint dsfMIBreakpoint) {
// We only support breakpoint and watchpoint (so far)
fBreakpoint = dsfMIBreakpoint;
fNature = dsfMIBreakpoint.isWatchpoint() ? MIBreakpointNature.WATCHPOINT : MIBreakpointNature.BREAKPOINT;
fProperties = new HashMap<String,Object>();
switch (fNature) {
case BREAKPOINT:
{
// Generic breakpoint attributes
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
fProperties.put(MIBreakpoints.FILE_NAME, dsfMIBreakpoint.getFile());
fProperties.put(MIBreakpoints.LINE_NUMBER, dsfMIBreakpoint.getLine());
fProperties.put(MIBreakpoints.FUNCTION, dsfMIBreakpoint.getFunction());
fProperties.put(MIBreakpoints.ADDRESS, dsfMIBreakpoint.getAddress());
fProperties.put(MIBreakpoints.CONDITION, dsfMIBreakpoint.getCondition());
fProperties.put(MIBreakpoints.IGNORE_COUNT, dsfMIBreakpoint.getIgnoreCount());
fProperties.put(MIBreakpoints.IS_ENABLED, new Boolean(dsfMIBreakpoint.isEnabled()));
// MI-specific breakpoint attributes
fProperties.put(NUMBER, dsfMIBreakpoint.getNumber());
fProperties.put(TYPE, dsfMIBreakpoint.getType());
fProperties.put(THREAD_ID, dsfMIBreakpoint.getThreadId());
fProperties.put(FULL_NAME, dsfMIBreakpoint.getFullName());
fProperties.put(HITS, dsfMIBreakpoint.getTimes());
fProperties.put(IS_TEMPORARY, new Boolean(dsfMIBreakpoint.isTemporary()));
fProperties.put(IS_HARDWARE, new Boolean(dsfMIBreakpoint.isHardware()));
fProperties.put(LOCATION, formatLocation());
break;
}
case WATCHPOINT:
{
// Generic breakpoint attributes
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
fProperties.put(MIBreakpoints.EXPRESSION, dsfMIBreakpoint.getExpression());
fProperties.put(MIBreakpoints.READ, dsfMIBreakpoint.isAccessWatchpoint() || dsfMIBreakpoint.isReadWatchpoint());
fProperties.put(MIBreakpoints.WRITE, dsfMIBreakpoint.isAccessWatchpoint() || dsfMIBreakpoint.isWriteWatchpoint());
// MI-specific breakpoint attributes
fProperties.put(NUMBER, dsfMIBreakpoint.getNumber());
break;
}
// Not reachable
default:
{
fProperties.put(MIBreakpoints.BREAKPOINT_TYPE, null);
break;
}
}
}
/**
* Formats the LOCATION synthetic property from the existing fields
*
* @return The location string
*/
private String formatLocation() {
// Unlikely default location
String location = fBreakpoint.getAddress();
// Get the relevant parameters
String fileName = fBreakpoint.getFile();
Integer lineNumber = fBreakpoint.getLine();
String function = fBreakpoint.getFunction();
if (!fileName.equals("")) { //$NON-NLS-1$
if (lineNumber != -1) {
location = fileName + ":" + lineNumber; //$NON-NLS-1$
} else {
location = fileName + ":" + function; //$NON-NLS-1$
}
}
return location;
}
/**
* Checks for equality
*
* @param other
* @return
*/
public boolean equals(MIBreakpointDMData other) {
return (fNature == other.fNature) && (fProperties.equals(other.fProperties));
}
///////////////////////////////////////////////////////////////////////////
// IBreakpointDMData
///////////////////////////////////////////////////////////////////////////
public String getBreakpointType() {
return (String) fProperties.get(MIBreakpoints.BREAKPOINT_TYPE);
}
public int getReference() {
return fBreakpoint.getNumber();
}
public IAddress[] getAddresses() {
IAddress[] addresses = new IAddress[1];
addresses[0] = new Addr64(fBreakpoint.getAddress());
return addresses;
}
public String getCondition() {
return fBreakpoint.getCondition();
}
public String getExpression() {
return fBreakpoint.getExpression();
}
public String getFileName() {
return fBreakpoint.getFile();
}
public String getFunctionName() {
return fBreakpoint.getFunction();
}
public int getIgnoreCount() {
return fBreakpoint.getIgnoreCount();
}
public int getLineNumber() {
return fBreakpoint.getLine();
}
public boolean isEnabled() {
return fBreakpoint.isEnabled();
}
///////////////////////////////////////////////////////////////////////////
// MIBreakpointDMData
///////////////////////////////////////////////////////////////////////////
public int getNumber() {
return fBreakpoint.getNumber();
}
public String getThreadId() {
return fBreakpoint.getThreadId();
}
public boolean isTemporary() {
return fBreakpoint.isTemporary();
}
public boolean isHardware() {
return fBreakpoint.isHardware();
}
public String getLocation() {
return (String) fProperties.get(LOCATION);
}
public int getHits() {
return fBreakpoint.getTimes();
}
public String getFullName() {
return fBreakpoint.getFullName();
}
public String getType() {
return fBreakpoint.getType();
}
public void setCondition(String condition) {
fBreakpoint.setCondition(condition);
fProperties.put(MIBreakpoints.CONDITION, condition);
}
public void setIgnoreCount(int ignoreCount) {
fBreakpoint.setIgnoreCount(ignoreCount);
fProperties.put(MIBreakpoints.IGNORE_COUNT, ignoreCount);
}
public void setEnabled(boolean isEnabled) {
fBreakpoint.setEnabled(isEnabled);
fProperties.put(MIBreakpoints.IS_ENABLED, isEnabled);
}
public boolean isReadWatchpoint() {
return fBreakpoint.isReadWatchpoint();
}
public boolean isWriteWatchpoint() {
return fBreakpoint.isWriteWatchpoint();
}
public boolean isAccessWatchpoint() {
return fBreakpoint.isAccessWatchpoint();
}
}

Some files were not shown because too many files have changed in this diff Show more