Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorLluis Sanchez Gual <lluis@xamarin.com>2014-06-04 20:47:32 +0400
committerLluis Sanchez Gual <lluis@xamarin.com>2014-06-04 21:14:46 +0400
commitd60a13af675e68705083ec78861ea7ec0d9a9a7b (patch)
treeafeba355cd4fbb1ee134595d9ea136237e5d6fb0 /main
parentf6ee1d2cf8d4e8656bc8199c8620eef4e3dc6f7c (diff)
Move the gdb debugger to the main solution
Diffstat (limited to 'main')
-rw-r--r--main/Main.sln15
-rw-r--r--main/configure.in3
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/AddinInfo.cs16
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/AssemblyInfo.cs9
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/ChangeLog365
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/CommandStatus.cs38
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/GdbBacktrace.cs400
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/GdbCommandResult.cs53
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/GdbEvent.cs49
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs730
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/GdbSessionFactory.cs151
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/Makefile.am1
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/Manifest.addin.xml8
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/MonoDevelop.Debugger.Gdb.csproj100
-rw-r--r--main/src/addins/MonoDevelop.Debugger.Gdb/ResultData.cs229
15 files changed, 2166 insertions, 1 deletions
diff --git a/main/Main.sln b/main/Main.sln
index bf3350c84c..5f16bcac0f 100644
--- a/main/Main.sln
+++ b/main/Main.sln
@@ -162,6 +162,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Debugger.Tests"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Debugger.Tests.TestApp", "src\addins\MonoDevelop.Debugger\MonoDevelop.Debugger.Tests.TestApp\MonoDevelop.Debugger.Tests.TestApp.csproj", "{05EDFE55-C8D1-47E4-BB61-0BC809CD82E2}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Debugger.Gdb", "src\addins\MonoDevelop.Debugger.Gdb\MonoDevelop.Debugger.Gdb.csproj", "{FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MonoDevelop.Debugger.Win32", "MonoDevelop.Debugger.Win32", "{8F47F5EC-2F57-4030-B658-7B1002DA90C2}"
ProjectSection(SolutionItems) = preProject
src\addins\MonoDevelop.Debugger.Win32\eula.rtf = src\addins\MonoDevelop.Debugger.Win32\eula.rtf
@@ -1900,6 +1902,18 @@ Global
{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}.ReleaseMac|Any CPU.Build.0 = Release|Any CPU
{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}.ReleaseWin32|Any CPU.Build.0 = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.DebugGnome|Any CPU.Build.0 = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.DebugMac|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.DebugWin32|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.ReleaseGnome|Any CPU.ActiveCfg = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.ReleaseGnome|Any CPU.Build.0 = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.ReleaseMac|Any CPU.ActiveCfg = Release|Any CPU
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}.ReleaseWin32|Any CPU.ActiveCfg = Release|Any CPU
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FEC19BDA-4904-4005-8C09-68E82E8BEF6A}.DebugGnome|Any CPU.ActiveCfg = Debug|Any CPU
@@ -1995,6 +2009,7 @@ Global
{2357AABD-08C7-4808-A495-8FF2D3CDFDB0} = {776872D9-76FA-407B-BA69-08E25A24E5CE}
{174E6044-DD3A-49AB-9A5C-2A1F341B7B4F} = {776872D9-76FA-407B-BA69-08E25A24E5CE}
{05EDFE55-C8D1-47E4-BB61-0BC809CD82E2} = {776872D9-76FA-407B-BA69-08E25A24E5CE}
+ {FA15FC26-A7E7-4932-93B7-65FAE6D5DD33} = {776872D9-76FA-407B-BA69-08E25A24E5CE}
{9FBCC262-10DC-4E84-A5C4-17230BBF8862} = {8F47F5EC-2F57-4030-B658-7B1002DA90C2}
{69136056-BFD3-4CEC-BB41-D9991C79593C} = {8F47F5EC-2F57-4030-B658-7B1002DA90C2}
{7E4B15FB-E8C4-419A-A31C-9310FD9062BD} = {8F47F5EC-2F57-4030-B658-7B1002DA90C2}
diff --git a/main/configure.in b/main/configure.in
index bb761c1b03..94e9d58d08 100644
--- a/main/configure.in
+++ b/main/configure.in
@@ -215,7 +215,7 @@ fi
AM_CONDITIONAL(ENABLE_MACPLATFORM, [test x$enable_macplatform = xyes])
-# Mac bundle
+# Mac bundle
AC_ARG_ENABLE(macbundle,
AC_HELP_STRING([--enable-macbundle],
[enable Mac bundle packaging [default=no]]),
@@ -335,6 +335,7 @@ src/addins/MonoDevelop.SourceEditor2/Makefile
src/addins/MonoDevelop.XmlEditor/Makefile
src/addins/MonoDevelop.Refactoring/Makefile
src/addins/MonoDevelop.Debugger/Makefile
+src/addins/MonoDevelop.Debugger.Gdb/Makefile
src/addins/MonoDevelop.Debugger.Soft/Makefile
src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/Makefile
src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.AspNet/Makefile
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/AddinInfo.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/AddinInfo.cs
new file mode 100644
index 0000000000..3cd8505305
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/AddinInfo.cs
@@ -0,0 +1,16 @@
+
+using System;
+using Mono.Addins;
+using Mono.Addins.Description;
+
+[assembly:Addin ("Debugger.Gdb",
+ Namespace = "MonoDevelop",
+ Version = MonoDevelop.BuildInfo.Version,
+ Category = "Debugging")]
+
+[assembly:AddinName ("GDB Debugger Support")]
+[assembly:AddinDescription ("Support for debugging native applications using the GDB debugger")]
+
+[assembly:AddinDependency ("Core", MonoDevelop.BuildInfo.Version)]
+[assembly:AddinDependency ("Ide", MonoDevelop.BuildInfo.Version)]
+[assembly:AddinDependency ("Debugger", MonoDevelop.BuildInfo.Version)]
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/AssemblyInfo.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/AssemblyInfo.cs
new file mode 100644
index 0000000000..ad3b28e1a8
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/AssemblyInfo.cs
@@ -0,0 +1,9 @@
+// Autogenerated from Manifest.addin.xml
+
+using System.Reflection;
+
+[assembly: AssemblyProduct ("MonoDevelop")]
+[assembly: AssemblyTitle ("GDB support for Mono.Debugging")]
+[assembly: AssemblyDescription ("GNU Debugger support for Mono.Debugging")]
+[assembly: AssemblyVersion ("2.6")]
+[assembly: AssemblyCopyright ("MIT X11")]
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/ChangeLog b/main/src/addins/MonoDevelop.Debugger.Gdb/ChangeLog
new file mode 100644
index 0000000000..ce5286dfe1
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/ChangeLog
@@ -0,0 +1,365 @@
+2010-06-14 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure: Bump MD version.
+
+2010-05-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure: Bump MD version.
+
+2010-05-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2010-05-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2010-05-03 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Increased console creation timeout.
+
+2010-04-28 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2010-04-19 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+ * MonoDevelop.Debugger.csproj: Flush.
+
+2010-03-22 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * AssemblyInfo.cs:
+ * Manifest.addin.xml: Bumped MD version.
+
+2010-03-17 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.csproj: Flush.
+
+2010-03-17 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.csproj: Merged MD.Projects into
+ MD.Core, and MD.Projects.Gui, MD.Core.Gui and MD.Components
+ into MD.Ide.
+
+2010-03-15 David Makovský <yakeen@sannyas-on.net>
+
+ * GdbBacktrace.cs: fixes for C++ structures (thx Martin Vejnár
+ <avakar@ratatanek.cz>)
+
+2010-03-08 Jonathan Pryor <jpryor@novell.com>
+
+ * configure: Create a $(CSC) make variable.
+ * MonoDevelop.Debugger.Gdb.make: Set $(ASSEMBLY_COMPILER_COMMAND) to
+ $(CSC). This allows a top-level CSC override to be used within this
+ module (e.g. top-level `make CSC=dmcs` for a v4 build).
+
+2010-03-03 Michael Hutchinson <mhutchinson@novell.com>
+
+ * GdbSession.cs: Name the reader thread.
+
+2010-03-01 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.sln: The invariant policy can't be
+ used anymore as base policy set.
+
+2010-02-22 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2010-02-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Add missing method.
+
+2010-02-19 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2010-02-16 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Manifest.addin.xml:
+ * GdbSessionFactory.cs: Track api changes. Some engine info is
+ now taken from extension node metadata.
+
+ * MonoDevelop.Debugger.csproj:
+ * MonoDevelop.Debugger.Gdb.sln: Flush.
+
+ * GdbSession.cs: Expressions are now printed by the debugging
+ service.
+
+2009-12-11 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2009-11-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs: Implement Id property.
+
+2009-11-18 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2009-11-12 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbEvent.cs: Reason can be an array. Handle this case.
+
+ * MonoDevelop.Debugger.csproj: Flush.
+
+ * GdbSession.cs: If there is an error while initializing,
+ report that the process has exited.
+
+2009-10-30 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * AssemblyInfo.cs:
+ * Manifest.addin.xml: Bump MD version.
+
+2009-10-18 Michael Hutchinson <mhutchinson@novell.com>
+
+ * GdbSession.cs: Fix Pocess/Process spelling.
+
+2009-10-16 Michael Hutchinson <mhutchinson@novell.com>
+
+ * GdbSessionFactory.cs: Fix spelling of GetAttachableProcesses
+ API.
+
+2009-10-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * AssemblyInfo.cs:
+ * Manifest.addin.xml: Bump MD version.
+
+2009-10-05 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs:
+ * GdbBacktrace.cs: Use long for thread and process id.
+
+2009-10-01 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.sln:
+
+ * GdbSession.cs: Don't crash if a breakpoint can't be set.
+
+2009-08-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.csproj:
+ * MonoDevelop.Debugger.Gdb.sln: Updated.
+
+ * GdbSession.cs: Quote file names when needed.
+
+2009-05-19 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.csproj: Flush.
+
+2009-04-27 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs:
+ * MonoDevelop.Debugger.csproj:
+ * MonoDevelop.Debugger.Gdb.make: Track api changes.
+
+2009-04-15 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * AssemblyInfo.cs:
+ * Manifest.addin.xml: Bump MD version.
+
+2009-03-04 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs: Removed unused CanDebugPlatform and
+ rename CanDebugFile to CanDebugCommand.
+
+2009-03-04 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs: Changed the way execution handlers
+ work. We are not using platform ids anymore. Instead, we use
+ command strings when looking for execution handlers.
+ IExecutionHandlerFactory has been removed and now everything
+ is handled by IExecutionHandler, which has a new CanExecute
+ method. This model is more simple and more generic.
+
+2009-02-26 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.sln: Flush.
+
+2009-02-25 Michael Hutchinson <mhutchinson@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.sln: Set policies. Remove unused
+ name attribute.
+
+2009-02-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.csproj: Updated references.
+
+2009/02/06 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.mdp:
+ * MonoDevelop.Debugger.mds:
+ * MonoDevelop.Debugger.csproj:
+ * MonoDevelop.Debugger.Gdb.mds:
+ * MonoDevelop.Debugger.Gdb.sln: Migrated to MSBuild file format.
+
+2009/02/03 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * AssemblyInfo.cs:
+ * Manifest.addin.xml: Bump MD version.
+
+2009-01-26 Michael Hutchinson <mhutchinson@novell.com>
+
+ * MonoDevelop.Debugger.mdp: Flush project format changes.
+
+2008-12-19 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.mdp: Updated.
+
+ * GdbBacktrace.cs: Track api changes.
+
+2008-12-09 Levi Bard <taktaktaktaktaktaktaktaktaktak@gmail.com>
+
+ * GdbSession.cs: Fallback to relative source file path.
+
+2008-12-04 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Manifest.addin.xml: Set correct add-in category.
+
+ * GdbSession.cs:
+ * GdbSessionFactory.cs:
+ * MonoDevelop.Debugger.mdp: Track api changes.
+
+2008-12-02 Michael Hutchinson <mhutchinson@novell.com>
+
+ * Manifest.addin.xml: Change addin version number to match
+ configure/tarball version number.
+
+2008-12-02 Michael Hutchinson <mhutchinson@novell.com>
+
+ * AssemblyInfo.cs: Add AssemblyInfo.cs files that are autogenerated from
+ the addin manifests.
+
+2008-12-02 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.mdp:
+ * MonoDevelop.Debugger.Gdb.make: Remove .pc file. It's not required.
+
+2008-11-25 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Manifest.addin.xml: Track api changes.
+
+2008-11-05 Lluis Sanchez Gual <lluis@novell.com>
+
+ * configure:
+ * Manifest.addin.xml: Bump MD version.
+
+2008-10-16 Michael Hutchinson <mhutchinson@novell.com>
+
+ * configure: Fix tarball name.
+
+2008-09-26 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs, GdbSession.cs: When debugging a mono process, try to
+ get managed method names for unknown stack frames.
+
+2008-09-17 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.mdp: Updated projects.
+
+2008-09-03 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2008-08-22 Lluis Sanchez Gual <lluis@novell.com>
+
+ * Manifest.addin.xml, MonoDevelop.Debugger.mdp: Extension point
+ location has changed.
+
+2008-08-18 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.mdp: Fix reference to Mono.TextEditor. The
+ incorrect add-in version number causes problems in the makefile
+ synchronization.
+
+2008-08-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Implemented support for conditions, trace expressions
+ and hit counts.
+
+2008-08-05 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2008-07-25 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Implement GetAllLocals.
+
+2008-07-16 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2008-07-11 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs: Fix construction process command line string.
+ * GdbSession.cs: Track api changes.
+
+2008-07-09 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.make: Install the assemblies to the correct
+ directory.
+
+2008-07-09 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2008-07-09 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Added support for code completion.
+
+2008-07-09 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+ * GdbSession.cs: Clean temporary variables.
+
+2008-07-07 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Track api changes.
+
+2008-07-02 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs: Support modifying variable values.
+ * GdbSession.cs: Implemented support for disassembling files.
+
+2008-07-01 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Track api changes.
+
+2008-06-26 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbBacktrace.cs, GdbSession.cs: Allow setting the active thread.
+ Implemented GetThreads and GetProcesses.
+ * ResultData.cs: Handle weird case where a tuple can have several
+ values for a property.
+
+2008-06-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSession.cs: Implemented detach.
+
+2008-06-20 Lluis Sanchez Gual <lluis@novell.com>
+
+ * GdbSessionFactory.cs, GdbBacktrace.cs, GdbSession.cs, ResultData.cs:
+ Implemented process attaching, variable query, disassemble.
+
+2008-06-17 Lluis Sanchez Gual <lluis@novell.com>
+
+ * MonoDevelop.Debugger.Gdb.make, configure, MonoDevelop.Debugger.mdp,
+ MonoDevelop.Debugger.mds, Makefile.include, rules.make,
+ monodevelop.debugger.gdb.pc.in, Makefile: Added missing build
+ files.
+
+2008-06-17 Lluis Sanchez Gual <lluis@novell.com>
+
+ * AssemblyInfo.cs, GdbBacktrace.cs, GdbEvent.cs, GdbSession.cs,
+ CommandStatus.cs, GdbSessionFactory.cs, ResultData.cs,
+ GdbCommandResult.cs, Manifest.addin.xml: Initial support for gdb
+ integration.
+
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/CommandStatus.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/CommandStatus.cs
new file mode 100644
index 0000000000..683c304cbe
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/CommandStatus.cs
@@ -0,0 +1,38 @@
+// CommandStatus.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ enum CommandStatus
+ {
+ Done,
+ Running,
+ Error
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbBacktrace.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbBacktrace.cs
new file mode 100644
index 0000000000..7aec2df3d0
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbBacktrace.cs
@@ -0,0 +1,400 @@
+// GdbBacktrace.cs
+//
+// Authors: Lluis Sanchez Gual <lluis@novell.com>
+// Jeffrey Stedfast <jeff@xamarin.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2012 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ class GdbBacktrace: IBacktrace, IObjectValueSource
+ {
+ int fcount;
+ StackFrame firstFrame;
+ GdbSession session;
+ DissassemblyBuffer[] disBuffers;
+ int currentFrame = -1;
+ long threadId;
+
+ public GdbBacktrace (GdbSession session, long threadId, int count, ResultData firstFrame)
+ {
+ fcount = count;
+ this.threadId = threadId;
+ if (firstFrame != null)
+ this.firstFrame = CreateFrame (firstFrame);
+ this.session = session;
+ }
+
+ public int FrameCount {
+ get {
+ return fcount;
+ }
+ }
+
+ public StackFrame[] GetStackFrames (int firstIndex, int lastIndex)
+ {
+ List<StackFrame> frames = new List<StackFrame> ();
+ if (firstIndex == 0 && firstFrame != null) {
+ frames.Add (firstFrame);
+ firstIndex++;
+ }
+
+ if (lastIndex >= fcount)
+ lastIndex = fcount - 1;
+
+ if (firstIndex > lastIndex)
+ return frames.ToArray ();
+
+ session.SelectThread (threadId);
+ GdbCommandResult res = session.RunCommand ("-stack-list-frames", firstIndex.ToString (), lastIndex.ToString ());
+ ResultData stack = res.GetObject ("stack");
+ for (int n=0; n<stack.Count; n++) {
+ ResultData frd = stack.GetObject (n);
+ frames.Add (CreateFrame (frd.GetObject ("frame")));
+ }
+ return frames.ToArray ();
+ }
+
+ public ObjectValue[] GetLocalVariables (int frameIndex, EvaluationOptions options)
+ {
+ List<ObjectValue> values = new List<ObjectValue> ();
+ SelectFrame (frameIndex);
+
+ GdbCommandResult res = session.RunCommand ("-stack-list-locals", "0");
+ foreach (ResultData data in res.GetObject ("locals"))
+ values.Add (CreateVarObject (data.GetValue ("name")));
+
+ return values.ToArray ();
+ }
+
+ public ObjectValue[] GetParameters (int frameIndex, EvaluationOptions options)
+ {
+ List<ObjectValue> values = new List<ObjectValue> ();
+ SelectFrame (frameIndex);
+ GdbCommandResult res = session.RunCommand ("-stack-list-arguments", "0", frameIndex.ToString (), frameIndex.ToString ());
+ foreach (ResultData data in res.GetObject ("stack-args").GetObject (0).GetObject ("frame").GetObject ("args"))
+ values.Add (CreateVarObject (data.GetValue ("name")));
+
+ return values.ToArray ();
+ }
+
+ public ObjectValue GetThisReference (int frameIndex, EvaluationOptions options)
+ {
+ return null;
+ }
+
+ public ObjectValue[] GetAllLocals (int frameIndex, EvaluationOptions options)
+ {
+ List<ObjectValue> locals = new List<ObjectValue> ();
+ locals.AddRange (GetParameters (frameIndex, options));
+ locals.AddRange (GetLocalVariables (frameIndex, options));
+ return locals.ToArray ();
+ }
+
+ public ObjectValue[] GetExpressionValues (int frameIndex, string[] expressions, EvaluationOptions options)
+ {
+ List<ObjectValue> values = new List<ObjectValue> ();
+ SelectFrame (frameIndex);
+ foreach (string exp in expressions)
+ values.Add (CreateVarObject (exp));
+ return values.ToArray ();
+ }
+
+ public ExceptionInfo GetException (int frameIndex, EvaluationOptions options)
+ {
+ return null;
+ }
+
+ public ValidationResult ValidateExpression (int frameIndex, string expression, EvaluationOptions options)
+ {
+ return new ValidationResult (true, null);
+ }
+
+ public CompletionData GetExpressionCompletionData (int frameIndex, string exp)
+ {
+ SelectFrame (frameIndex);
+
+ bool pointer = exp.EndsWith ("->");
+ int i;
+
+ if (pointer || exp.EndsWith (".")) {
+ exp = exp.Substring (0, exp.Length - (pointer ? 2 : 1));
+ i = 0;
+ while (i < exp.Length) {
+ ObjectValue val = CreateVarObject (exp);
+ if (!val.IsUnknown && !val.IsError) {
+ CompletionData data = new CompletionData ();
+ foreach (ObjectValue cv in val.GetAllChildren ())
+ data.Items.Add (new CompletionItem (cv.Name, cv.Flags));
+ data.ExpressionLength = 0;
+ return data;
+ }
+ i++;
+ }
+ return null;
+ }
+
+ i = exp.Length - 1;
+ bool lastWastLetter = false;
+ while (i >= 0) {
+ char c = exp [i--];
+ if (!char.IsLetterOrDigit (c) && c != '_')
+ break;
+ lastWastLetter = !char.IsDigit (c);
+ }
+
+ if (lastWastLetter) {
+ string partialWord = exp.Substring (i+1);
+
+ CompletionData cdata = new CompletionData ();
+ cdata.ExpressionLength = partialWord.Length;
+
+ // Local variables
+
+ GdbCommandResult res = session.RunCommand ("-stack-list-locals", "0");
+ foreach (ResultData data in res.GetObject ("locals")) {
+ string name = data.GetValue ("name");
+ if (name.StartsWith (partialWord))
+ cdata.Items.Add (new CompletionItem (name, ObjectValueFlags.Variable));
+ }
+
+ // Parameters
+
+ res = session.RunCommand ("-stack-list-arguments", "0", frameIndex.ToString (), frameIndex.ToString ());
+ foreach (ResultData data in res.GetObject ("stack-args").GetObject (0).GetObject ("frame").GetObject ("args")) {
+ string name = data.GetValue ("name");
+ if (name.StartsWith (partialWord))
+ cdata.Items.Add (new CompletionItem (name, ObjectValueFlags.Parameter));
+ }
+
+ if (cdata.Items.Count > 0)
+ return cdata;
+ }
+ return null;
+ }
+
+
+ ObjectValue CreateVarObject (string exp)
+ {
+ try {
+ session.SelectThread (threadId);
+ exp = exp.Replace ("\"", "\\\"");
+ GdbCommandResult res = session.RunCommand ("-var-create", "-", "*", "\"" + exp + "\"");
+ string vname = res.GetValue ("name");
+ session.RegisterTempVariableObject (vname);
+ return CreateObjectValue (exp, res);
+ } catch {
+ return ObjectValue.CreateUnknown (exp);
+ }
+ }
+
+ ObjectValue CreateObjectValue (string name, ResultData data)
+ {
+ string vname = data.GetValue ("name");
+ string typeName = data.GetValue ("type");
+ string value = data.GetValue ("value");
+ int nchild = data.GetInt ("numchild");
+
+ ObjectValue val;
+ ObjectValueFlags flags = ObjectValueFlags.Variable;
+
+ // There can be 'public' et al children for C++ structures
+ if (typeName == null)
+ typeName = "none";
+
+ if (typeName.EndsWith ("]")) {
+ val = ObjectValue.CreateArray (this, new ObjectPath (vname), typeName, nchild, flags, null);
+ } else if (value == "{...}" || typeName.EndsWith ("*") || nchild > 0) {
+ val = ObjectValue.CreateObject (this, new ObjectPath (vname), typeName, value, flags, null);
+ } else {
+ val = ObjectValue.CreatePrimitive (this, new ObjectPath (vname), typeName, new EvaluationResult (value), flags);
+ }
+ val.Name = name;
+ return val;
+ }
+
+ public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+ {
+ List<ObjectValue> children = new List<ObjectValue> ();
+ session.SelectThread (threadId);
+ GdbCommandResult res = session.RunCommand ("-var-list-children", "2", path.Join ("."));
+ ResultData cdata = res.GetObject ("children");
+
+ // The response may not contain the "children" list at all.
+ if (cdata == null)
+ return children.ToArray ();
+
+ if (index == -1) {
+ index = 0;
+ count = cdata.Count;
+ }
+
+ for (int n=index; n<cdata.Count && n<index+count; n++) {
+ ResultData data = cdata.GetObject (n);
+ ResultData child = data.GetObject ("child");
+
+ string name = child.GetValue ("exp");
+ if (name.Length > 0 && char.IsNumber (name [0]))
+ name = "[" + name + "]";
+
+ // C++ structures may contain typeless children named
+ // "public", "private" and "protected".
+ if (child.GetValue("type") == null) {
+ ObjectPath childPath = new ObjectPath (child.GetValue ("name").Split ('.'));
+ ObjectValue[] subchildren = GetChildren (childPath, -1, -1, options);
+ children.AddRange(subchildren);
+ } else {
+ ObjectValue val = CreateObjectValue (name, child);
+ children.Add (val);
+ }
+ }
+ return children.ToArray ();
+ }
+
+ public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+ {
+ session.SelectThread (threadId);
+ session.RunCommand ("-var-assign", path.Join ("."), value);
+ return new EvaluationResult (value);
+ }
+
+ public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+ {
+ throw new NotSupportedException ();
+ }
+
+ void SelectFrame (int frame)
+ {
+ session.SelectThread (threadId);
+ if (frame != currentFrame) {
+ session.RunCommand ("-stack-select-frame", frame.ToString ());
+ currentFrame = frame;
+ }
+ }
+
+ StackFrame CreateFrame (ResultData frameData)
+ {
+ string lang = "Native";
+ string func = frameData.GetValue ("func");
+ string sadr = frameData.GetValue ("addr");
+
+ if (func == "??" && session.IsMonoProcess) {
+ // Try to get the managed func name
+ try {
+ ResultData data = session.RunCommand ("-data-evaluate-expression", "mono_pmip(" + sadr + ")");
+ string val = data.GetValue ("value");
+ if (val != null) {
+ int i = val.IndexOf ('"');
+ if (i != -1) {
+ func = val.Substring (i).Trim ('"',' ');
+ lang = "Mono";
+ }
+ }
+ } catch {
+ }
+ }
+
+ int line = -1;
+ string sline = frameData.GetValue ("line");
+ if (sline != null)
+ line = int.Parse (sline);
+
+ string sfile = frameData.GetValue ("fullname");
+ if (sfile == null)
+ sfile = frameData.GetValue ("file");
+ if (sfile == null)
+ sfile = frameData.GetValue ("from");
+ SourceLocation loc = new SourceLocation (func ?? "?", sfile, line);
+
+ long addr;
+ if (!string.IsNullOrEmpty (sadr))
+ addr = long.Parse (sadr.Substring (2), NumberStyles.HexNumber);
+ else
+ addr = 0;
+
+ return new StackFrame (addr, loc, lang);
+ }
+
+ public AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count)
+ {
+ SelectFrame (frameIndex);
+ if (disBuffers == null)
+ disBuffers = new DissassemblyBuffer [fcount];
+
+ DissassemblyBuffer buffer = disBuffers [frameIndex];
+ if (buffer == null) {
+ ResultData data = session.RunCommand ("-stack-info-frame");
+ long addr = long.Parse (data.GetObject ("frame").GetValue ("addr").Substring (2), NumberStyles.HexNumber);
+ buffer = new GdbDissassemblyBuffer (session, addr);
+ disBuffers [frameIndex] = buffer;
+ }
+
+ return buffer.GetLines (firstLine, firstLine + count - 1);
+ }
+
+ public object GetRawValue (ObjectPath path, EvaluationOptions options)
+ {
+ return null;
+ }
+
+ public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+ {
+ }
+ }
+
+ class GdbDissassemblyBuffer: DissassemblyBuffer
+ {
+ GdbSession session;
+
+ public GdbDissassemblyBuffer (GdbSession session, long addr): base (addr)
+ {
+ this.session = session;
+ }
+
+ public override AssemblyLine[] GetLines (long startAddr, long endAddr)
+ {
+ try {
+ ResultData data = session.RunCommand ("-data-disassemble", "-s", startAddr.ToString (), "-e", endAddr.ToString (), "--", "0");
+ ResultData ins = data.GetObject ("asm_insns");
+
+ AssemblyLine[] alines = new AssemblyLine [ins.Count];
+ for (int n=0; n<ins.Count; n++) {
+ ResultData aline = ins.GetObject (n);
+ long addr = long.Parse (aline.GetValue ("address").Substring (2), NumberStyles.HexNumber);
+ AssemblyLine line = new AssemblyLine (addr, aline.GetValue ("inst"));
+ alines [n] = line;
+ }
+ return alines;
+ } catch {
+ return new AssemblyLine [0];
+ }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbCommandResult.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbCommandResult.cs
new file mode 100644
index 0000000000..a8790d74ad
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbCommandResult.cs
@@ -0,0 +1,53 @@
+// GdbCommandResult.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ class GdbCommandResult: ResultData
+ {
+ public CommandStatus Status;
+ public string ErrorMessage;
+
+ public GdbCommandResult (string line)
+ {
+ if (line.StartsWith ("^done")) {
+ Status = CommandStatus.Done;
+ ReadResults (line, 6);
+ } else if (line.StartsWith ("^error")) {
+ Status = CommandStatus.Error;
+ if (line.Length > 7) {
+ ReadResults (line, 7);
+ ErrorMessage = GetValue ("msg");
+ }
+ } else if (line.StartsWith ("^running")) {
+ Status = CommandStatus.Running;
+ }
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbEvent.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbEvent.cs
new file mode 100644
index 0000000000..cf631cfb70
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbEvent.cs
@@ -0,0 +1,49 @@
+// GdbEvent.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ class GdbEvent: ResultData
+ {
+ public string Name;
+ public string Reason;
+
+ public GdbEvent (string line)
+ {
+ int i = line.IndexOf (',');
+ if (i == -1)
+ i = line.Length;
+ Name = line.Substring (1, i - 1);
+ ReadResults (line, i+1);
+ object[] reasons = GetAllValues ("reason");
+ if (reasons.Length > 0)
+ Reason = (string) reasons [0];
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs
new file mode 100644
index 0000000000..c585ab86b5
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSession.cs
@@ -0,0 +1,730 @@
+// GdbSession.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Globalization;
+using System.Text;
+using System.IO;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+using Mono.Debugging.Client;
+using MonoDevelop.Core;
+using MonoDevelop.Core.Execution;
+using Mono.Unix.Native;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ class GdbSession: DebuggerSession
+ {
+ Process proc;
+ StreamReader sout;
+ StreamWriter sin;
+ IProcessAsyncOperation console;
+ GdbCommandResult lastResult;
+ bool running;
+ Thread thread;
+ long currentThread = -1;
+ long activeThread = -1;
+ bool isMonoProcess;
+ string currentProcessName;
+ List<string> tempVariableObjects = new List<string> ();
+ Dictionary<int,BreakEventInfo> breakpoints = new Dictionary<int,BreakEventInfo> ();
+ List<BreakEventInfo> breakpointsWithHitCount = new List<BreakEventInfo> ();
+
+ DateTime lastBreakEventUpdate = DateTime.Now;
+ Dictionary<int, WaitCallback> breakUpdates = new Dictionary<int,WaitCallback> ();
+ bool breakUpdateEventsQueued;
+ const int BreakEventUpdateNotifyDelay = 500;
+
+ bool internalStop;
+ bool logGdb;
+
+ object syncLock = new object ();
+ object eventLock = new object ();
+ object gdbLock = new object ();
+
+ public GdbSession ()
+ {
+ logGdb = !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONODEVELOP_GDB_LOG"));
+ }
+
+ protected override void OnRun (DebuggerStartInfo startInfo)
+ {
+ lock (gdbLock) {
+ // Create a script to be run in a terminal
+ string script = Path.GetTempFileName ();
+ string ttyfile = Path.GetTempFileName ();
+ string ttyfileDone = ttyfile + "_done";
+ string tty;
+
+ try {
+ File.WriteAllText (script, "tty > " + ttyfile + "\ntouch " + ttyfileDone + "\nsleep 10000d");
+ Mono.Unix.Native.Syscall.chmod (script, FilePermissions.ALLPERMS);
+
+ console = Runtime.ProcessService.StartConsoleProcess (script, "", ".", ExternalConsoleFactory.Instance.CreateConsole (true), null);
+ DateTime tim = DateTime.Now;
+ while (!File.Exists (ttyfileDone)) {
+ System.Threading.Thread.Sleep (100);
+ if ((DateTime.Now - tim).TotalSeconds > 10)
+ throw new InvalidOperationException ("Console could not be created.");
+ }
+ tty = File.ReadAllText (ttyfile).Trim (' ','\n');
+ } finally {
+ try {
+ if (File.Exists (script))
+ File.Delete (script);
+ if (File.Exists (ttyfile))
+ File.Delete (ttyfile);
+ if (File.Exists (ttyfileDone))
+ File.Delete (ttyfileDone);
+ } catch {
+ // Ignore
+ }
+ }
+
+ StartGdb ();
+
+ // Initialize the terminal
+ RunCommand ("-inferior-tty-set", Escape (tty));
+
+ try {
+ RunCommand ("-file-exec-and-symbols", Escape (startInfo.Command));
+ } catch {
+ FireTargetEvent (TargetEventType.TargetExited, null);
+ throw;
+ }
+
+ RunCommand ("-environment-cd", Escape (startInfo.WorkingDirectory));
+
+ // Set inferior arguments
+ if (!string.IsNullOrEmpty (startInfo.Arguments))
+ RunCommand ("-exec-arguments", startInfo.Arguments);
+
+ currentProcessName = startInfo.Command + " " + startInfo.Arguments;
+
+ CheckIsMonoProcess ();
+ OnStarted ();
+
+ RunCommand ("-exec-run");
+ }
+ }
+
+ protected override void OnAttachToProcess (long processId)
+ {
+ lock (gdbLock) {
+ StartGdb ();
+ currentProcessName = "PID " + processId.ToString ();
+ RunCommand ("attach", processId.ToString ());
+ currentThread = activeThread = 1;
+ CheckIsMonoProcess ();
+ OnStarted ();
+ FireTargetEvent (TargetEventType.TargetStopped, null);
+ }
+ }
+
+ public bool IsMonoProcess {
+ get { return isMonoProcess; }
+ }
+
+ void CheckIsMonoProcess ()
+ {
+ try {
+ RunCommand ("-data-evaluate-expression", "mono_pmip");
+ isMonoProcess = true;
+ } catch {
+ isMonoProcess = false;
+ // Ignore
+ }
+ }
+
+ void StartGdb ()
+ {
+ proc = new Process ();
+ proc.StartInfo.FileName = "gdb";
+ proc.StartInfo.Arguments = "-quiet -fullname -i=mi2";
+ proc.StartInfo.UseShellExecute = false;
+ proc.StartInfo.RedirectStandardInput = true;
+ proc.StartInfo.RedirectStandardOutput = true;
+ proc.StartInfo.RedirectStandardError = true;
+ proc.Start ();
+
+ sout = proc.StandardOutput;
+ sin = proc.StandardInput;
+
+ thread = new Thread (OutputInterpreter);
+ thread.Name = "GDB output interpeter";
+ thread.IsBackground = true;
+ thread.Start ();
+ }
+
+ public override void Dispose ()
+ {
+ if (console != null && !console.IsCompleted) {
+ console.Cancel ();
+ console = null;
+ }
+
+ if (thread != null)
+ thread.Abort ();
+ }
+
+ protected override void OnSetActiveThread (long processId, long threadId)
+ {
+ activeThread = threadId;
+ }
+
+ protected override void OnStop ()
+ {
+ Syscall.kill (proc.Id, Signum.SIGINT);
+ }
+
+ protected override void OnDetach ()
+ {
+ lock (gdbLock) {
+ InternalStop ();
+ RunCommand ("detach");
+ FireTargetEvent (TargetEventType.TargetExited, null);
+ }
+ }
+
+ protected override void OnExit ()
+ {
+ lock (gdbLock) {
+ InternalStop ();
+ RunCommand ("kill");
+ TargetEventArgs args = new TargetEventArgs (TargetEventType.TargetExited);
+ OnTargetEvent (args);
+/* proc.Kill ();
+ TargetEventArgs args = new TargetEventArgs (TargetEventType.TargetExited);
+ OnTargetEvent (args);
+*/ }
+ }
+
+ protected override void OnStepLine ()
+ {
+ SelectThread (activeThread);
+ RunCommand ("-exec-step");
+ }
+
+ protected override void OnNextLine ()
+ {
+ SelectThread (activeThread);
+ RunCommand ("-exec-next");
+ }
+
+ protected override void OnStepInstruction ()
+ {
+ SelectThread (activeThread);
+ RunCommand ("-exec-step-instruction");
+ }
+
+ protected override void OnNextInstruction ()
+ {
+ SelectThread (activeThread);
+ RunCommand ("-exec-next-instruction");
+ }
+
+ protected override void OnFinish ()
+ {
+ SelectThread (activeThread);
+ GdbCommandResult res = RunCommand ("-stack-info-depth", "2");
+ if (res.GetValue ("depth") == "1") {
+ RunCommand ("-exec-continue");
+ } else {
+ RunCommand ("-stack-select-frame", "0");
+ RunCommand ("-exec-finish");
+ }
+ }
+
+ protected override BreakEventInfo OnInsertBreakEvent (BreakEvent be)
+ {
+ Breakpoint bp = be as Breakpoint;
+ if (bp == null)
+ throw new NotSupportedException ();
+
+ BreakEventInfo bi = new BreakEventInfo ();
+
+ lock (gdbLock) {
+ bool dres = InternalStop ();
+ try {
+ string extraCmd = string.Empty;
+ if (bp.HitCount > 0) {
+ extraCmd += "-i " + bp.HitCount;
+ breakpointsWithHitCount.Add (bi);
+ }
+ if (!string.IsNullOrEmpty (bp.ConditionExpression)) {
+ if (!bp.BreakIfConditionChanges)
+ extraCmd += " -c " + bp.ConditionExpression;
+ }
+
+ GdbCommandResult res = null;
+ string errorMsg = null;
+
+ if (bp is FunctionBreakpoint) {
+ try {
+ res = RunCommand ("-break-insert", extraCmd.Trim (), ((FunctionBreakpoint) bp).FunctionName);
+ } catch (Exception ex) {
+ errorMsg = ex.Message;
+ }
+ } else {
+ // Breakpoint locations must be double-quoted if files contain spaces.
+ // For example: -break-insert "\"C:/Documents and Settings/foo.c\":17"
+ RunCommand ("-environment-directory", Escape (Path.GetDirectoryName (bp.FileName)));
+
+ try {
+ res = RunCommand ("-break-insert", extraCmd.Trim (), Escape (Escape (bp.FileName) + ":" + bp.Line));
+ } catch (Exception ex) {
+ errorMsg = ex.Message;
+ }
+
+ if (res == null) {
+ try {
+ res = RunCommand ("-break-insert", extraCmd.Trim (), Escape (Escape (Path.GetFileName (bp.FileName)) + ":" + bp.Line));
+ }
+ catch {
+ // Ignore
+ }
+ }
+ }
+
+ if (res == null) {
+ bi.SetStatus (BreakEventStatus.Invalid, errorMsg);
+ return bi;
+ }
+ int bh = res.GetObject ("bkpt").GetInt ("number");
+ if (!be.Enabled)
+ RunCommand ("-break-disable", bh.ToString ());
+ breakpoints [bh] = bi;
+ bi.Handle = bh;
+ bi.SetStatus (BreakEventStatus.Bound, null);
+ return bi;
+ } finally {
+ InternalResume (dres);
+ }
+ }
+ }
+
+ bool CheckBreakpoint (int handle)
+ {
+ BreakEventInfo binfo;
+ if (!breakpoints.TryGetValue (handle, out binfo))
+ return true;
+
+ Breakpoint bp = (Breakpoint) binfo.BreakEvent;
+
+ if (!string.IsNullOrEmpty (bp.ConditionExpression) && bp.BreakIfConditionChanges) {
+ // Update the condition expression
+ GdbCommandResult res = RunCommand ("-data-evaluate-expression", Escape (bp.ConditionExpression));
+ string val = res.GetValue ("value");
+ RunCommand ("-break-condition", handle.ToString (), "(" + bp.ConditionExpression + ") != " + val);
+ }
+
+ if (!string.IsNullOrEmpty (bp.TraceExpression) && bp.HitAction == HitAction.PrintExpression) {
+ GdbCommandResult res = RunCommand ("-data-evaluate-expression", Escape (bp.TraceExpression));
+ string val = res.GetValue ("value");
+ NotifyBreakEventUpdate (binfo, 0, val);
+ return false;
+ }
+ return true;
+ }
+
+ void NotifyBreakEventUpdate (BreakEventInfo binfo, int hitCount, string lastTrace)
+ {
+ bool notify = false;
+
+ WaitCallback nc = delegate {
+ if (hitCount != -1)
+ binfo.IncrementHitCount ();
+ if (lastTrace != null)
+ binfo.UpdateLastTraceValue (lastTrace);
+ };
+
+ lock (breakUpdates)
+ {
+ int span = (int) (DateTime.Now - lastBreakEventUpdate).TotalMilliseconds;
+ if (span >= BreakEventUpdateNotifyDelay && !breakUpdateEventsQueued) {
+ // Last update was more than 0.5s ago. The update can be sent.
+ lastBreakEventUpdate = DateTime.Now;
+ notify = true;
+ } else {
+ // Queue the event notifications to avoid wasting too much time
+ breakUpdates [(int)binfo.Handle] = nc;
+ if (!breakUpdateEventsQueued) {
+ breakUpdateEventsQueued = true;
+
+ ThreadPool.QueueUserWorkItem (delegate {
+ Thread.Sleep (BreakEventUpdateNotifyDelay - span);
+ List<WaitCallback> copy;
+ lock (breakUpdates) {
+ copy = new List<WaitCallback> (breakUpdates.Values);
+ breakUpdates.Clear ();
+ breakUpdateEventsQueued = false;
+ lastBreakEventUpdate = DateTime.Now;
+ }
+ foreach (WaitCallback wc in copy)
+ wc (null);
+ });
+ }
+ }
+ }
+ if (notify)
+ nc (null);
+ }
+
+ void UpdateHitCountData ()
+ {
+ foreach (BreakEventInfo bp in breakpointsWithHitCount) {
+ GdbCommandResult res = RunCommand ("-break-info", bp.Handle.ToString ());
+ string val = res.GetObject ("BreakpointTable").GetObject ("body").GetObject (0).GetObject ("bkpt").GetValue ("ignore");
+ if (val != null)
+ NotifyBreakEventUpdate (bp, int.Parse (val), null);
+ else
+ NotifyBreakEventUpdate (bp, 0, null);
+ }
+ breakpointsWithHitCount.Clear ();
+ }
+
+ protected override void OnRemoveBreakEvent (BreakEventInfo binfo)
+ {
+ lock (gdbLock) {
+ if (binfo.Handle == null)
+ return;
+ bool dres = InternalStop ();
+ breakpointsWithHitCount.Remove (binfo);
+ breakpoints.Remove ((int)binfo.Handle);
+ try {
+ RunCommand ("-break-delete", binfo.Handle.ToString ());
+ } finally {
+ InternalResume (dres);
+ }
+ }
+ }
+
+ protected override void OnEnableBreakEvent (BreakEventInfo binfo, bool enable)
+ {
+ lock (gdbLock) {
+ if (binfo.Handle == null)
+ return;
+ bool dres = InternalStop ();
+ try {
+ if (enable)
+ RunCommand ("-break-enable", binfo.Handle.ToString ());
+ else
+ RunCommand ("-break-disable", binfo.Handle.ToString ());
+ } finally {
+ InternalResume (dres);
+ }
+ }
+ }
+
+ protected override void OnUpdateBreakEvent (BreakEventInfo binfo)
+ {
+ Breakpoint bp = binfo.BreakEvent as Breakpoint;
+ if (bp == null)
+ throw new NotSupportedException ();
+
+ if (binfo.Handle == null)
+ return;
+
+ bool ss = InternalStop ();
+
+ try {
+ if (bp.HitCount > 0) {
+ RunCommand ("-break-after", binfo.Handle.ToString (), bp.HitCount.ToString ());
+ breakpointsWithHitCount.Add (binfo);
+ } else
+ breakpointsWithHitCount.Remove (binfo);
+
+ if (!string.IsNullOrEmpty (bp.ConditionExpression) && !bp.BreakIfConditionChanges)
+ RunCommand ("-break-condition", binfo.Handle.ToString (), bp.ConditionExpression);
+ else
+ RunCommand ("-break-condition", binfo.Handle.ToString ());
+ } finally {
+ InternalResume (ss);
+ }
+ }
+
+ protected override void OnContinue ()
+ {
+ SelectThread (activeThread);
+ RunCommand ("-exec-continue");
+ }
+
+ protected override ThreadInfo[] OnGetThreads (long processId)
+ {
+ List<ThreadInfo> list = new List<ThreadInfo> ();
+ ResultData data = RunCommand ("-thread-list-ids").GetObject ("thread-ids");
+ foreach (string id in data.GetAllValues ("thread-id"))
+ list.Add (GetThread (long.Parse (id)));
+ return list.ToArray ();
+ }
+
+ protected override ProcessInfo[] OnGetProcesses ()
+ {
+ ProcessInfo p = new ProcessInfo (0, currentProcessName);
+ return new ProcessInfo [] { p };
+ }
+
+ ThreadInfo GetThread (long id)
+ {
+ return new ThreadInfo (0, id, "Thread #" + id, null);
+ }
+
+ protected override Backtrace OnGetThreadBacktrace (long processId, long threadId)
+ {
+ ResultData data = SelectThread (threadId);
+ GdbCommandResult res = RunCommand ("-stack-info-depth");
+ int fcount = int.Parse (res.GetValue ("depth"));
+ GdbBacktrace bt = new GdbBacktrace (this, threadId, fcount, data != null ? data.GetObject ("frame") : null);
+ return new Backtrace (bt);
+ }
+
+ protected override AssemblyLine[] OnDisassembleFile (string file)
+ {
+ List<AssemblyLine> lines = new List<AssemblyLine> ();
+ int cline = 1;
+ do {
+ ResultData data = null;
+ try {
+ data = RunCommand ("-data-disassemble", "-f", file, "-l", cline.ToString (), "--", "1");
+ } catch {
+ break;
+ }
+ ResultData asm_insns = data.GetObject ("asm_insns");
+ int newLine = cline;
+ for (int n=0; n<asm_insns.Count; n++) {
+ ResultData src_and_asm_line = asm_insns.GetObject (n).GetObject ("src_and_asm_line");
+ newLine = src_and_asm_line.GetInt ("line");
+ ResultData line_asm_insn = src_and_asm_line.GetObject ("line_asm_insn");
+ for (int i=0; i<line_asm_insn.Count; i++) {
+ ResultData asm = line_asm_insn.GetObject (i);
+ long addr = long.Parse (asm.GetValue ("address").Substring (2), NumberStyles.HexNumber);
+ string code = asm.GetValue ("inst");
+ lines.Add (new AssemblyLine (addr, code, newLine));
+ }
+ }
+ if (newLine <= cline)
+ break;
+ cline = newLine + 1;
+
+ } while (true);
+
+ return lines.ToArray ();
+ }
+
+ public ResultData SelectThread (long id)
+ {
+ if (id == currentThread)
+ return null;
+ currentThread = id;
+ return RunCommand ("-thread-select", id.ToString ());
+ }
+
+ string Escape (string str)
+ {
+ if (str == null)
+ return null;
+ else if (str.IndexOf (' ') != -1 || str.IndexOf ('"') != -1) {
+ str = str.Replace ("\"", "\\\"");
+ return "\"" + str + "\"";
+ }
+ else
+ return str;
+ }
+
+ public GdbCommandResult RunCommand (string command, params string[] args)
+ {
+ lock (gdbLock) {
+ lock (syncLock) {
+ lastResult = null;
+
+ lock (eventLock) {
+ running = true;
+ }
+
+ if (logGdb)
+ Console.WriteLine ("gdb<: " + command + " " + string.Join (" ", args));
+
+ sin.WriteLine (command + " " + string.Join (" ", args));
+
+ if (!Monitor.Wait (syncLock, 4000))
+ throw new InvalidOperationException ("Command execution timeout.");
+ if (lastResult.Status == CommandStatus.Error)
+ throw new InvalidOperationException (lastResult.ErrorMessage);
+ return lastResult;
+ }
+ }
+ }
+
+ bool InternalStop ()
+ {
+ lock (eventLock) {
+ if (!running)
+ return false;
+ internalStop = true;
+ Syscall.kill (proc.Id, Signum.SIGINT);
+ if (!Monitor.Wait (eventLock, 4000))
+ throw new InvalidOperationException ("Target could not be interrupted.");
+ }
+ return true;
+ }
+
+ void InternalResume (bool resume)
+ {
+ if (resume)
+ RunCommand ("-exec-continue");
+ }
+
+ void OutputInterpreter ()
+ {
+ string line;
+ while ((line = sout.ReadLine ()) != null) {
+ try {
+ ProcessOutput (line);
+ } catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
+ }
+ }
+
+ void ProcessOutput (string line)
+ {
+ if (logGdb)
+ Console.WriteLine ("dbg>: '" + line + "'");
+ switch (line [0]) {
+ case '^':
+ lock (syncLock) {
+ lastResult = new GdbCommandResult (line);
+ running = (lastResult.Status == CommandStatus.Running);
+ Monitor.PulseAll (syncLock);
+ }
+ break;
+
+ case '~':
+ case '&':
+ if (line.Length > 1 && line[1] == '"')
+ line = line.Substring (2, line.Length - 5);
+ ThreadPool.QueueUserWorkItem (delegate {
+ OnTargetOutput (false, line + "\n");
+ });
+ break;
+
+ case '*':
+ GdbEvent ev;
+ lock (eventLock) {
+ running = false;
+ ev = new GdbEvent (line);
+ string ti = ev.GetValue ("thread-id");
+ if (ti != null && ti != "all")
+ currentThread = activeThread = int.Parse (ti);
+ Monitor.PulseAll (eventLock);
+ if (internalStop) {
+ internalStop = false;
+ return;
+ }
+ }
+ ThreadPool.QueueUserWorkItem (delegate {
+ try {
+ HandleEvent (ev);
+ } catch (Exception ex) {
+ Console.WriteLine (ex);
+ }
+ });
+ break;
+ }
+ }
+
+ void HandleEvent (GdbEvent ev)
+ {
+ if (ev.Name != "stopped") {
+ Console.WriteLine ("Unknown event: " + ev.Name);
+ return;
+ }
+
+ CleanTempVariableObjects ();
+
+ TargetEventType type;
+ switch (ev.Reason) {
+ case "breakpoint-hit":
+ type = TargetEventType.TargetHitBreakpoint;
+ if (!CheckBreakpoint (ev.GetInt ("bkptno"))) {
+ RunCommand ("-exec-continue");
+ return;
+ }
+ break;
+ case "signal-received":
+ if (ev.GetValue ("signal-name") == "SIGINT")
+ type = TargetEventType.TargetInterrupted;
+ else
+ type = TargetEventType.TargetSignaled;
+ break;
+ case "exited":
+ case "exited-signalled":
+ case "exited-normally":
+ type = TargetEventType.TargetExited;
+ break;
+ default:
+ type = TargetEventType.TargetStopped;
+ break;
+ }
+
+ ResultData curFrame = ev.GetObject ("frame");
+ FireTargetEvent (type, curFrame);
+ }
+
+ void FireTargetEvent (TargetEventType type, ResultData curFrame)
+ {
+ UpdateHitCountData ();
+
+ TargetEventArgs args = new TargetEventArgs (type);
+
+ if (type != TargetEventType.TargetExited) {
+ GdbCommandResult res = RunCommand ("-stack-info-depth");
+ int fcount = int.Parse (res.GetValue ("depth"));
+
+ GdbBacktrace bt = new GdbBacktrace (this, activeThread, fcount, curFrame);
+ args.Backtrace = new Backtrace (bt);
+ args.Thread = GetThread (activeThread);
+ }
+ OnTargetEvent (args);
+ }
+
+ internal void RegisterTempVariableObject (string var)
+ {
+ tempVariableObjects.Add (var);
+ }
+
+ void CleanTempVariableObjects ()
+ {
+ foreach (string s in tempVariableObjects)
+ RunCommand ("-var-delete", s);
+ tempVariableObjects.Clear ();
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSessionFactory.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSessionFactory.cs
new file mode 100644
index 0000000000..a4e11b6877
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/GdbSessionFactory.cs
@@ -0,0 +1,151 @@
+// GdbSessionFactory.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+using MonoDevelop.Core.Execution;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ public class GdbSessionFactory: IDebuggerEngine
+ {
+ struct FileData {
+ public DateTime LastCheck;
+ public bool IsExe;
+ }
+
+ Dictionary<string,FileData> fileCheckCache = new Dictionary<string, FileData> ();
+
+ public bool CanDebugCommand (ExecutionCommand command)
+ {
+ NativeExecutionCommand cmd = command as NativeExecutionCommand;
+ if (cmd == null)
+ return false;
+
+ string file = FindFile (cmd.Command);
+ if (!File.Exists (file)) {
+ // The provided file is not guaranteed to exist. If it doesn't
+ // we assume we can execute it because otherwise the run command
+ // in the IDE will be disabled, and that's not good because that
+ // command will build the project if the exec doesn't yet exist.
+ return true;
+ }
+
+ file = Path.GetFullPath (file);
+ DateTime currentTime = File.GetLastWriteTime (file);
+
+ FileData data;
+ if (fileCheckCache.TryGetValue (file, out data)) {
+ if (data.LastCheck == currentTime)
+ return data.IsExe;
+ }
+ data.LastCheck = currentTime;
+ try {
+ data.IsExe = IsExecutable (file);
+ } catch {
+ data.IsExe = false;
+ }
+ fileCheckCache [file] = data;
+ return data.IsExe;
+ }
+
+ public DebuggerStartInfo CreateDebuggerStartInfo (ExecutionCommand command)
+ {
+ NativeExecutionCommand pec = (NativeExecutionCommand) command;
+ DebuggerStartInfo startInfo = new DebuggerStartInfo ();
+ startInfo.Command = pec.Command;
+ startInfo.Arguments = pec.Arguments;
+ startInfo.WorkingDirectory = pec.WorkingDirectory;
+ if (pec.EnvironmentVariables.Count > 0) {
+ foreach (KeyValuePair<string,string> val in pec.EnvironmentVariables)
+ startInfo.EnvironmentVariables [val.Key] = val.Value;
+ }
+ return startInfo;
+ }
+
+ public bool IsExecutable (string file)
+ {
+ // HACK: this is a quick but not very reliable way of checking if a file
+ // is a native executable. Actually, we are interested in checking that
+ // the file is not a script.
+ using (StreamReader sr = new StreamReader (file)) {
+ char[] chars = new char[3];
+ int n = 0, nr = 0;
+ while (n < chars.Length && (nr = sr.ReadBlock (chars, n, chars.Length - n)) != 0)
+ n += nr;
+ if (nr != chars.Length)
+ return true;
+ if (chars [0] == '#' && chars [1] == '!')
+ return false;
+ }
+ return true;
+ }
+
+ public DebuggerSession CreateSession ()
+ {
+ GdbSession ds = new GdbSession ();
+ return ds;
+ }
+
+ public ProcessInfo[] GetAttachableProcesses ()
+ {
+ List<ProcessInfo> procs = new List<ProcessInfo> ();
+ foreach (string dir in Directory.GetDirectories ("/proc")) {
+ int id;
+ if (!int.TryParse (Path.GetFileName (dir), out id))
+ continue;
+ try {
+ File.ReadAllText (Path.Combine (dir, "sessionid"));
+ } catch {
+ continue;
+ }
+ string cmdline = File.ReadAllText (Path.Combine (dir, "cmdline"));
+ cmdline = cmdline.Replace ('\0',' ');
+ ProcessInfo pi = new ProcessInfo (id, cmdline);
+ procs.Add (pi);
+ }
+ return procs.ToArray ();
+ }
+
+ string FindFile (string cmd)
+ {
+ if (Path.IsPathRooted (cmd))
+ return cmd;
+ string pathVar = Environment.GetEnvironmentVariable ("PATH");
+ string[] paths = pathVar.Split (Path.PathSeparator);
+ foreach (string path in paths) {
+ string file = Path.Combine (path, cmd);
+ if (File.Exists (file))
+ return file;
+ }
+ return cmd;
+ }
+ }
+}
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/Makefile.am b/main/src/addins/MonoDevelop.Debugger.Gdb/Makefile.am
new file mode 100644
index 0000000000..c9cc87438f
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/xbuild.include
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/Manifest.addin.xml b/main/src/addins/MonoDevelop.Debugger.Gdb/Manifest.addin.xml
new file mode 100644
index 0000000000..238f37937e
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/Manifest.addin.xml
@@ -0,0 +1,8 @@
+<ExtensionModel>
+ <Extension path="/MonoDevelop/Debugging/DebuggerEngines">
+ <DebuggerEngine id="Mono.Debugger.Gdb"
+ name="GNU Debugger (GDB)"
+ features="ConditionalBreakpoints, Tracepoints, Catchpoints, Attaching, DebugFile, Stepping, Pause, Breakpoints, Disassembly"
+ type="MonoDevelop.Debugger.Gdb.GdbSessionFactory" />
+ </Extension>
+</ExtensionModel> \ No newline at end of file
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/MonoDevelop.Debugger.Gdb.csproj b/main/src/addins/MonoDevelop.Debugger.Gdb/MonoDevelop.Debugger.Gdb.csproj
new file mode 100644
index 0000000000..d555a666ea
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/MonoDevelop.Debugger.Gdb.csproj
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{FA15FC26-A7E7-4932-93B7-65FAE6D5DD33}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AssemblyName>MonoDevelop.Debugger.Gdb</AssemblyName>
+ <RootNamespace>MonoDevelop.Debugger</RootNamespace>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\AddIns\MonoDevelop.Debugger.Gdb</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <Execution>
+ <Execution clr-version="Net_2_0" />
+ </Execution>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\build\AddIns\MonoDevelop.Debugger.Gdb</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <Execution>
+ <Execution clr-version="Net_2_0" />
+ </Execution>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="Mono.TextEditor, Version=1.0.0.0, Culture=neutral">
+ <Package>monodevelop</Package>
+ </Reference>
+ <Reference Include="Mono.Posix" />
+ <Reference Include="Mono.Debugging, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5e9ce85b0923c84f">
+ <Package>monodevelop</Package>
+ </Reference>
+ <Reference Include="Mono.Debugging.Soft, Version=0.0.0.0, Culture=neutral, PublicKeyToken=5e9ce85b0923c84f">
+ <Package>monodevelop-core-addins</Package>
+ </Reference>
+ <Reference Include="Mono.Debugger.Soft, Version=0.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
+ <Package>monodevelop-core-addins</Package>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AssemblyInfo.cs" />
+ <Compile Include="GdbSession.cs" />
+ <Compile Include="GdbSessionFactory.cs" />
+ <Compile Include="GdbBacktrace.cs" />
+ <Compile Include="CommandStatus.cs" />
+ <Compile Include="ResultData.cs" />
+ <Compile Include="GdbEvent.cs" />
+ <Compile Include="GdbCommandResult.cs" />
+ <Compile Include="AddinInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Manifest.addin.xml">
+ <LogicalName>Manifest.addin.xml</LogicalName>
+ </EmbeddedResource>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ProjectExtensions>
+ <MonoDevelop>
+ <Properties>
+ <Deployment.LinuxDeployData generatePcFile="False" />
+ </Properties>
+ </MonoDevelop>
+ </ProjectExtensions>
+ <ItemGroup>
+ <ProjectReference Include="..\MonoDevelop.Debugger\MonoDevelop.Debugger.csproj">
+ <Project>{2357AABD-08C7-4808-A495-8FF2D3CDFDB0}</Project>
+ <Name>MonoDevelop.Debugger</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj">
+ <Project>{7525BB88-6142-4A26-93B9-A30C6983390A}</Project>
+ <Name>MonoDevelop.Core</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\..\core\MonoDevelop.Ide\MonoDevelop.Ide.csproj">
+ <Project>{27096E7F-C91C-4AC6-B289-6897A701DF21}</Project>
+ <Name>MonoDevelop.Ide</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj">
+ <Project>{91DD5A2D-9FE3-4C3C-9253-876141874DAD}</Project>
+ <Name>Mono.Addins</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
diff --git a/main/src/addins/MonoDevelop.Debugger.Gdb/ResultData.cs b/main/src/addins/MonoDevelop.Debugger.Gdb/ResultData.cs
new file mode 100644
index 0000000000..73c5612a6c
--- /dev/null
+++ b/main/src/addins/MonoDevelop.Debugger.Gdb/ResultData.cs
@@ -0,0 +1,229 @@
+// ResultData.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace MonoDevelop.Debugger.Gdb
+{
+ class ResultData: IEnumerable
+ {
+ Hashtable props;
+ object[] array;
+ bool isArrayProperty;
+
+ public int Count {
+ get {
+ if (array != null)
+ return array.Length;
+ else if (props != null)
+ return props.Count;
+ else
+ return 0;
+ }
+ }
+
+ public string GetValue (string name)
+ {
+ return (string) props [name];
+ }
+
+ public int GetInt (string name)
+ {
+ return int.Parse (GetValue (name));
+ }
+
+ public string GetValue (int index)
+ {
+ return (string) array [index];
+ }
+
+ public ResultData GetObject (string name)
+ {
+ return (ResultData) props [name];
+ }
+
+ public ResultData GetObject (int index)
+ {
+ return (ResultData) array [index];
+ }
+
+ public object[] GetAllValues (string name)
+ {
+ object ob = props [name];
+ if (ob == null)
+ return new object [0];
+ ResultData rd = ob as ResultData;
+ if (rd != null && rd.isArrayProperty)
+ return rd.array;
+ else
+ return new object[] { ob };
+ }
+
+ protected void ReadResults (string str, int pos)
+ {
+ ReadTuple (str, ref pos, this);
+ }
+
+ void ReadResult (string str, ref int pos, out string name, out object value)
+ {
+ name = null;
+ value = null;
+
+ name = ReadString (str, '=', ref pos);
+ ReadChar (str, ref pos, '=');
+ value = ReadValue (str, ref pos);
+ }
+
+ string ReadString (string str, char term, ref int pos)
+ {
+ StringBuilder sb = new StringBuilder ();
+ while (pos < str.Length && str [pos] != term) {
+ if (str [pos] == '\\') {
+ pos++;
+ if (pos >= str.Length)
+ break;
+ }
+ sb.Append (str [pos]);
+ pos++;
+ }
+ return sb.ToString ();
+ }
+
+ object ReadValue (string str, ref int pos)
+ {
+ if (str [pos] == '"') {
+ pos++;
+ string ret = ReadString (str, '"', ref pos);
+ pos++;
+ return ret;
+ }
+ if (str [pos] == '{') {
+ pos++;
+ ResultData data = new ResultData ();
+ ReadTuple (str, ref pos, data);
+ return data;
+ }
+ if (str [pos] == '[') {
+ pos++;
+ return ReadArray (str, ref pos);
+ }
+
+ // Single value tuple
+ string name;
+ object val;
+ ReadResult (str, ref pos, out name, out val);
+ ResultData sdata = new ResultData ();
+ sdata.props = new Hashtable ();
+ sdata.props [name] = val;
+ return sdata;
+ }
+
+ void ReadTuple (string str, ref int pos, ResultData data)
+ {
+ if (data.props == null)
+ data.props = new Hashtable ();
+
+ while (pos < str.Length && str [pos] != '}') {
+ string name;
+ object val;
+ ReadResult (str, ref pos, out name, out val);
+ if (data.props.ContainsKey (name)) {
+ object ob = data.props [name];
+ ResultData rd = ob as ResultData;
+ if (rd != null && rd.isArrayProperty) {
+ object[] newArr = new object [rd.array.Length + 1];
+ Array.Copy (rd.array, newArr, rd.array.Length);
+ newArr [rd.array.Length] = val;
+ rd.array = newArr;
+ } else {
+ rd = new ResultData ();
+ rd.isArrayProperty = true;
+ rd.array = new object [2];
+ rd.array [0] = ob;
+ rd.array [1] = val;
+ data.props [name] = rd;
+ }
+ } else {
+ data.props [name] = val;
+ }
+ TryReadChar (str, ref pos, ',');
+ }
+ TryReadChar (str, ref pos, '}');
+ }
+
+ ResultData ReadArray (string str, ref int pos)
+ {
+ ArrayList list = new ArrayList ();
+ while (pos < str.Length && str [pos] != ']') {
+ object val = ReadValue (str, ref pos);
+ list.Add (val);
+ TryReadChar (str, ref pos, ',');
+ }
+ TryReadChar (str, ref pos, ']');
+ ResultData arr = new ResultData ();
+ arr.array = list.ToArray ();
+ return arr;
+ }
+
+ void ReadChar (string str, ref int pos, char c)
+ {
+ if (!TryReadChar (str, ref pos, c))
+ ThrownParseError (str, pos);
+ }
+
+ bool TryReadChar (string str, ref int pos, char c)
+ {
+ if (pos >= str.Length || str [pos] != c)
+ return false;
+ pos++;
+ return true;
+ }
+
+ void ThrownParseError (string str, int pos)
+ {
+ if (pos > str.Length)
+ pos = str.Length;
+ str = str.Insert (pos, "[!]");
+ throw new InvalidOperationException ("Error parsing result: " + str);
+ }
+
+ public IEnumerator GetEnumerator ()
+ {
+ if (props != null)
+ return props.Values.GetEnumerator ();
+ else if (array != null)
+ return array.GetEnumerator ();
+ else
+ return new object[0].GetEnumerator ();
+ }
+ }
+}