mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-06 09:16:02 +02:00
Migrated DSF and DSF-GDB to the CDT project.
This commit is contained in:
commit
5b47187366
876 changed files with 120844 additions and 0 deletions
7
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.classpath
Normal file
7
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.classpath
Normal 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>
|
34
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.project
Normal file
34
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.project
Normal 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>
|
155
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/.api_filters
Normal file
155
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/.settings/.api_filters
Normal 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>
|
|
@ -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
|
27
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
Normal file
27
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/META-INF/MANIFEST.MF
Normal 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
|
24
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/about.html
Normal file
24
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/about.html
Normal 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>
|
18
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/build.properties
Normal file
18
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/build.properties
Normal 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
|
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/c_app.gif
Normal file
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/c_app.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1 KiB |
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/connect.gif
Executable file
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/connect.gif
Executable file
Binary file not shown.
After Width: | Height: | Size: 189 B |
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/exec_obj.gif
Normal file
BIN
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/icons/full/obj16/exec_obj.gif
Normal file
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 |
15
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
Normal file
15
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties
Normal 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
|
146
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
Normal file
146
dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml
Normal 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>
|
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
|
@ -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$
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
7
dsf-gdb/org.eclipse.cdt.dsf.gdb/.classpath
Normal file
7
dsf-gdb/org.eclipse.cdt.dsf.gdb/.classpath
Normal 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>
|
1
dsf-gdb/org.eclipse.cdt.dsf.gdb/.options
Normal file
1
dsf-gdb/org.eclipse.cdt.dsf.gdb/.options
Normal file
|
@ -0,0 +1 @@
|
|||
org.eclipse.cdt.dsf.gdb/debug = false
|
34
dsf-gdb/org.eclipse.cdt.dsf.gdb/.project
Normal file
34
dsf-gdb/org.eclipse.cdt.dsf.gdb/.project
Normal 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>
|
115
dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
Normal file
115
dsf-gdb/org.eclipse.cdt.dsf.gdb/.settings/.api_filters
Normal 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>
|
|
@ -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
|
26
dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
Normal file
26
dsf-gdb/org.eclipse.cdt.dsf.gdb/META-INF/MANIFEST.MF
Normal 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
|
24
dsf-gdb/org.eclipse.cdt.dsf.gdb/about.html
Normal file
24
dsf-gdb/org.eclipse.cdt.dsf.gdb/about.html
Normal 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>
|
17
dsf-gdb/org.eclipse.cdt.dsf.gdb/build.properties
Normal file
17
dsf-gdb/org.eclipse.cdt.dsf.gdb/build.properties
Normal 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
|
13
dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties
Normal file
13
dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.properties
Normal 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
|
||||
|
71
dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.xml
Normal file
71
dsf-gdb/org.eclipse.cdt.dsf.gdb/plugin.xml
Normal 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>
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {}
|
|
@ -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 {}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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 }
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Reference in a new issue