mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 09:46: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