[Pkg-cli-libs-commits] [mono-debugger-libs] 01/02: Imported Upstream version 0+20131201.3459502

Jo Shields directhex at moszumanska.debian.org
Sun Dec 1 12:42:02 UTC 2013


This is an automated email from the git hooks/post-receive script.

directhex pushed a commit to annotated tag debian/0+20131201.3459502-1
in repository mono-debugger-libs.

commit 25200ecf4209472a409063d972d4b18627aab46c
Author: Jo Shields <directhex at apebox.org>
Date:   Sun Dec 1 10:58:12 2013 +0000

    Imported Upstream version 0+20131201.3459502
---
 .gitignore                                         |   13 +
 Mono.Debugger.Soft/Locale.cs                       |   51 +
 Mono.Debugger.Soft/Makefile.am                     |    3 +
 Mono.Debugger.Soft/Mono.Debugger.Soft.csproj       |  127 +
 .../AbsentInformationException.cs                  |   10 +
 .../Mono.Debugger.Soft/AppDomainCreateEvent.cs     |   20 +
 .../Mono.Debugger.Soft/AppDomainMirror.cs          |   96 +
 .../Mono.Debugger.Soft/AppDomainUnloadEvent.cs     |   20 +
 .../Mono.Debugger.Soft/ArrayMirror.cs              |  143 ++
 .../Mono.Debugger.Soft/AssemblyLoadEvent.cs        |   20 +
 .../Mono.Debugger.Soft/AssemblyLoadEventRequest.cs |   11 +
 .../Mono.Debugger.Soft/AssemblyMirror.cs           |  100 +
 .../Mono.Debugger.Soft/AssemblyUnloadEvent.cs      |   20 +
 .../Mono.Debugger.Soft/BreakpointEvent.cs          |   20 +
 .../Mono.Debugger.Soft/BreakpointEventRequest.cs   |   28 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/ChangeLog    |  210 ++
 .../Mono.Debugger.Soft/Connection.cs               | 2393 ++++++++++++++++++
 .../CustomAttributeDataMirror.cs                   |  147 ++
 .../CustomAttributeNamedArgumentMirror.cs          |   37 +
 .../CustomAttributeTypedArgumentMirror.cs          |   59 +
 .../Mono.Debugger.Soft/DataConverter.cs            | 1836 ++++++++++++++
 .../Mono.Debugger.Soft/EnumMirror.cs               |   48 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/Event.cs     |   50 +
 .../Mono.Debugger.Soft/EventQueueImpl.cs           |  133 +
 .../Mono.Debugger.Soft/EventRequest.cs             |  142 ++
 Mono.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs  |   34 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/EventType.cs |   32 +
 .../Mono.Debugger.Soft/ExceptionEvent.cs           |   20 +
 .../Mono.Debugger.Soft/ExceptionEventRequest.cs    |   48 +
 .../Mono.Debugger.Soft/FieldInfoMirror.cs          |  181 ++
 .../Mono.Debugger.Soft/IInvokeAsyncResult.cs       |   10 +
 .../Mono.Debugger.Soft/ILExceptionHandler.cs       |   33 +
 .../Mono.Debugger.Soft/ILInstruction.cs            |   67 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs   |   20 +
 .../Mono.Debugger.Soft/ITargetProcess.cs           |   74 +
 .../Mono.Debugger.Soft/InterfaceMappingMirror.cs   |   26 +
 .../InvalidStackFrameException.cs                  |   10 +
 .../Mono.Debugger.Soft/InvocationException.cs      |   20 +
 .../Mono.Debugger.Soft/InvokeOptions.cs            |   18 +
 .../Mono.Debugger.Soft/LocalVariable.cs            |   79 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/Location.cs  |   68 +
 .../Mono.Debugger.Soft/MethodBodyMirror.cs         |  216 ++
 .../Mono.Debugger.Soft/MethodEntryEvent.cs         |   20 +
 .../Mono.Debugger.Soft/MethodEntryEventRequest.cs  |   10 +
 .../Mono.Debugger.Soft/MethodExitEvent.cs          |   20 +
 .../Mono.Debugger.Soft/MethodExitEventRequest.cs   |   10 +
 .../Mono.Debugger.Soft/MethodMirror.cs             |  411 +++
 Mono.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs    |   39 +
 .../Mono.Debugger.Soft/ModuleMirror.cs             |   66 +
 .../Mono.Debugger.Soft/ObjectCollectedException.cs |   10 +
 .../Mono.Debugger.Soft/ObjectMirror.cs             |  380 +++
 .../Mono.Debugger.Soft/ParameterInfoMirror.cs      |   64 +
 .../Mono.Debugger.Soft/PointerValue.cs             |   65 +
 .../Mono.Debugger.Soft/PrimitiveValue.cs           |   56 +
 .../Mono.Debugger.Soft/PropertyInfoMirror.cs       |  139 ++
 .../Mono.Debugger.Soft/StackFrame.cs               |  208 ++
 Mono.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs |   27 +
 .../Mono.Debugger.Soft/StepEventRequest.cs         |   91 +
 .../Mono.Debugger.Soft/StringMirror.cs             |   43 +
 .../Mono.Debugger.Soft/StructMirror.cs             |   71 +
 .../Mono.Debugger.Soft/SuspendPolicy.cs            |   10 +
 .../Mono.Debugger.Soft/ThreadDeathEvent.cs         |    8 +
 .../Mono.Debugger.Soft/ThreadMirror.cs             |   95 +
 .../Mono.Debugger.Soft/ThreadStartEvent.cs         |    8 +
 .../Mono.Debugger.Soft/TypeLoadEvent.cs            |   20 +
 .../Mono.Debugger.Soft/TypeLoadEventRequest.cs     |   43 +
 .../Mono.Debugger.Soft/TypeMirror.cs               |  868 +++++++
 .../Mono.Debugger.Soft/UserBreakEvent.cs           |    8 +
 .../Mono.Debugger.Soft/UserLogEvent.cs             |   33 +
 .../Mono.Debugger.Soft/VMDeathEvent.cs             |   10 +
 .../Mono.Debugger.Soft/VMDisconnectEvent.cs        |   10 +
 .../Mono.Debugger.Soft/VMDisconnectedException.cs  |   10 +
 .../Mono.Debugger.Soft/VMMismatchException.cs      |   10 +
 .../Mono.Debugger.Soft/VMStartEvent.cs             |   10 +
 Mono.Debugger.Soft/Mono.Debugger.Soft/Value.cs     |   14 +
 .../Mono.Debugger.Soft/VirtualMachine.cs           |  701 ++++++
 .../Mono.Debugger.Soft/VirtualMachineManager.cs    |  339 +++
 Mono.Debugger.Soft/mono-git-revision               |    1 +
 Mono.Debugger.Soft/mono.snk                        |  Bin 0 -> 596 bytes
 Mono.Debugging.Soft/ArrayAdaptor.cs                |   89 +
 Mono.Debugging.Soft/AssemblyInfo.cs                |   29 +
 Mono.Debugging.Soft/ChangeLog                      |  264 ++
 Mono.Debugging.Soft/FieldValueReference.cs         |  170 ++
 Mono.Debugging.Soft/Makefile.am                    |    1 +
 Mono.Debugging.Soft/Mono.Debugging.Soft.csproj     |   79 +
 Mono.Debugging.Soft/PropertyValueReference.cs      |  128 +
 Mono.Debugging.Soft/SoftDebuggerAdaptor.cs         | 1825 ++++++++++++++
 Mono.Debugging.Soft/SoftDebuggerBacktrace.cs       |  215 ++
 Mono.Debugging.Soft/SoftDebuggerSession.cs         | 2638 ++++++++++++++++++++
 Mono.Debugging.Soft/SoftDebuggerStartInfo.cs       |  203 ++
 Mono.Debugging.Soft/SoftEvaluationContext.cs       |  186 ++
 Mono.Debugging.Soft/StringAdaptor.cs               |   76 +
 Mono.Debugging.Soft/VariableValueReference.cs      |   88 +
 Mono.Debugging/ChangeLog                           | 1032 ++++++++
 Mono.Debugging/Makefile.am                         |    1 +
 .../Mono.Debugging.Backend/DissassemblyBuffer.cs   |  154 ++
 .../Mono.Debugging.Backend/EvaluationResult.cs     |   55 +
 .../Mono.Debugging.Backend/IBacktrace.cs           |   20 +
 .../IDebuggerBackendObject.cs                      |   34 +
 .../IDebuggerSessionFrontend.cs                    |   44 +
 .../Mono.Debugging.Backend/IObjectValueSource.cs   |   43 +
 .../IObjectValueUpdateCallback.cs                  |   37 +
 .../Mono.Debugging.Backend/IObjectValueUpdater.cs  |   37 +
 Mono.Debugging/Mono.Debugging.Backend/IRawValue.cs |   40 +
 .../Mono.Debugging.Backend/IRawValueArray.cs       |   40 +
 .../Mono.Debugging.Backend/IRawValueString.cs      |   39 +
 .../Mono.Debugging.Backend/UpdateCallback.cs       |   68 +
 .../Mono.Debugging.Client/AssemblyLine.cs          |   90 +
 Mono.Debugging/Mono.Debugging.Client/Backtrace.cs  |   67 +
 Mono.Debugging/Mono.Debugging.Client/BreakEvent.cs |  338 +++
 .../Mono.Debugging.Client/BreakEventArgs.cs        |   45 +
 .../Mono.Debugging.Client/BreakEventInfo.cs        |  164 ++
 .../Mono.Debugging.Client/BreakEventStatus.cs      |   57 +
 Mono.Debugging/Mono.Debugging.Client/Breakpoint.cs |  237 ++
 .../Mono.Debugging.Client/BreakpointEventArgs.cs   |   45 +
 .../Mono.Debugging.Client/BreakpointStore.cs       |  583 +++++
 Mono.Debugging/Mono.Debugging.Client/Catchpoint.cs |   81 +
 .../Mono.Debugging.Client/CatchpointEventArgs.cs   |   45 +
 .../Mono.Debugging.Client/CompletionData.cs        |   77 +
 .../Mono.Debugging.Client/DebuggerException.cs     |   47 +
 .../Mono.Debugging.Client/DebuggerFeatures.cs      |   47 +
 .../DebuggerLoggingService.cs                      |   71 +
 .../Mono.Debugging.Client/DebuggerSession.cs       | 1538 ++++++++++++
 .../DebuggerSessionOptions.cs                      |   38 +
 .../Mono.Debugging.Client/DebuggerStartInfo.cs     |   80 +
 .../Mono.Debugging.Client/EvaluationOptions.cs     |  117 +
 .../Mono.Debugging.Client/ExceptionInfo.cs         |  254 ++
 .../Mono.Debugging.Client/FunctionBreakpoint.cs    |  189 ++
 .../Mono.Debugging.Client/IExpressionEvaluator.cs  |   38 +
 Mono.Debugging/Mono.Debugging.Client/ObjectPath.cs |  101 +
 .../Mono.Debugging.Client/ObjectValue.cs           |  787 ++++++
 .../Mono.Debugging.Client/ObjectValueFlags.cs      |   71 +
 .../Mono.Debugging.Client/ProcessEventArgs.cs      |   47 +
 .../Mono.Debugging.Client/ProcessInfo.cs           |   78 +
 Mono.Debugging/Mono.Debugging.Client/RawValue.cs   |  280 +++
 .../Mono.Debugging.Client/SourceLocation.cs        |   32 +
 Mono.Debugging/Mono.Debugging.Client/StackFrame.cs |  313 +++
 .../Mono.Debugging.Client/TargetEventArgs.cs       |   57 +
 .../Mono.Debugging.Client/TargetEventType.cs       |   19 +
 .../Mono.Debugging.Client/ThreadEventArgs.cs       |   47 +
 Mono.Debugging/Mono.Debugging.Client/ThreadInfo.cs |  135 +
 .../Mono.Debugging.Evaluation/ArrayElementGroup.cs |  359 +++
 .../ArrayValueReference.cs                         |   79 +
 .../AsyncEvaluationTracker.cs                      |  147 ++
 .../AsyncOperationManager.cs                       |  241 ++
 .../Mono.Debugging.Evaluation/BaseBacktrace.cs     |  245 ++
 .../BaseTypeViewSource.cs                          |   89 +
 .../Mono.Debugging.Evaluation/EvaluationContext.cs |  145 ++
 .../ExceptionInfoSource.cs                         |  160 ++
 .../ExpressionEvaluator.cs                         |  232 ++
 .../FilteredMembersSource.cs                       |  123 +
 .../ICollectionAdaptor.cs                          |   41 +
 .../Mono.Debugging.Evaluation/IObjectSource.cs     |   35 +
 .../Mono.Debugging.Evaluation/IStringAdaptor.cs    |   37 +
 .../LiteralValueReference.cs                       |  181 ++
 .../NRefactoryExpressionEvaluator.cs               |  242 ++
 .../NRefactoryExpressionEvaluatorVisitor.cs        | 1375 ++++++++++
 .../NRefactoryExpressionResolverVisitor.cs         |  131 +
 .../NRefactoryExtensions.cs                        |  182 ++
 .../NamespaceValueReference.cs                     |  150 ++
 .../NullValueReference.cs                          |   97 +
 .../ObjectValueAdaptor.cs                          | 1380 ++++++++++
 .../Mono.Debugging.Evaluation/RawViewSource.cs     |   83 +
 .../Mono.Debugging.Evaluation/RemoteFrameObject.cs |   76 +
 .../Mono.Debugging.Evaluation/RemoteRawValue.cs    |  214 ++
 .../Mono.Debugging.Evaluation/TimeOutException.cs  |   38 +
 .../Mono.Debugging.Evaluation/TimedEvaluator.cs    |  254 ++
 .../TypeValueReference.cs                          |  207 ++
 .../UserVariableReference.cs                       |   73 +
 .../Mono.Debugging.Evaluation/ValueReference.cs    |  266 ++
 Mono.Debugging/Mono.Debugging.csproj               |  140 ++
 Mono.Debugging/mono.debugging.snk                  |  Bin 0 -> 596 bytes
 README.md                                          |   15 +
 UnitTests/UnitTests/DebugTests.cs                  |  110 +
 UnitTests/UnitTests/EvaluationTests.cs             |  695 ++++++
 UnitTests/UnitTests/SdbEvaluationTests.cs          |   48 +
 UnitTests/UnitTests/SdbStackFrameTests.cs          |   49 +
 UnitTests/UnitTests/StackFrameTests.cs             |  122 +
 UnitTests/UnitTests/UnitTests.TestApp/Main.cs      |  179 ++
 .../UnitTests.TestApp/Properties/AssemblyInfo.cs   |   27 +
 .../UnitTests.TestApp/UnitTests.TestApp.csproj     |   39 +
 UnitTests/UnitTests/UnitTests.csproj               |   63 +
 debugger-libs.sln                                  |  302 +++
 183 files changed, 33142 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3ab4775
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+bin
+obj
+*~
+*.sln.cache
+*.suo
+*.user
+*.dotCover
+*.pidb
+*.userprefs
+*.usertasks
+*.mdb
+.DS_Store
+Makefile.in
diff --git a/Mono.Debugger.Soft/Locale.cs b/Mono.Debugger.Soft/Locale.cs
new file mode 100644
index 0000000..7293ab2
--- /dev/null
+++ b/Mono.Debugger.Soft/Locale.cs
@@ -0,0 +1,51 @@
+//
+// Locale.cs
+//
+// Author:
+//   Miguel de Icaza (miguel at ximian.com)
+//   Andreas Nahr (ClassDevelopment at A-SoftTech.com)
+//
+// (C) 2001 - 2003 Ximian, Inc (http://www.ximian.com)
+//
+
+//
+// Copyright (C) 2004 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;
+
+internal sealed class Locale {
+
+	private Locale ()
+	{
+	}
+
+	public static string GetText (string msg)
+	{
+		return msg;
+	}
+
+	public static string GetText (string fmt, params object [] args)
+	{
+		return String.Format (fmt, args);
+	}
+}
diff --git a/Mono.Debugger.Soft/Makefile.am b/Mono.Debugger.Soft/Makefile.am
new file mode 100644
index 0000000..c5d0ed3
--- /dev/null
+++ b/Mono.Debugger.Soft/Makefile.am
@@ -0,0 +1,3 @@
+include $(top_srcdir)/xbuild.include
+
+XBUILD_OUTPUT=$(XBUILD_OUTPUT_BIN)/MonoDevelop.Debugger.Soft
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft.csproj b/Mono.Debugger.Soft/Mono.Debugger.Soft.csproj
new file mode 100644
index 0000000..7278c3f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft.csproj
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Mono.Debugger.Soft</RootNamespace>
+    <AssemblyName>Mono.Debugger.Soft</AssemblyName>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>mono.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>MONO_DATACONVERTER_STATIC_METHODS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <DefineConstants>MONO_DATACONVERTER_STATIC_METHODS</DefineConstants>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Compile Include="Mono.Debugger.Soft\AbsentInformationException.cs" />
+    <Compile Include="Mono.Debugger.Soft\AppDomainCreateEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\AppDomainMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\AppDomainUnloadEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\ArrayMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\AssemblyLoadEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\AssemblyMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\AssemblyUnloadEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\BreakpointEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\BreakpointEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\Connection.cs" />
+    <Compile Include="Mono.Debugger.Soft\CustomAttributeDataMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\CustomAttributeNamedArgumentMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\CustomAttributeTypedArgumentMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\DataConverter.cs" />
+    <Compile Include="Mono.Debugger.Soft\EnumMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\Event.cs" />
+    <Compile Include="Mono.Debugger.Soft\EventQueueImpl.cs" />
+    <Compile Include="Mono.Debugger.Soft\EventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\EventSet.cs" />
+    <Compile Include="Mono.Debugger.Soft\EventType.cs" />
+    <Compile Include="Mono.Debugger.Soft\ExceptionEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\ExceptionEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\FieldInfoMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\IInvokeAsyncResult.cs" />
+    <Compile Include="Mono.Debugger.Soft\ILExceptionHandler.cs" />
+    <Compile Include="Mono.Debugger.Soft\ILInstruction.cs" />
+    <Compile Include="Mono.Debugger.Soft\IMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\InterfaceMappingMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\InvalidStackFrameException.cs" />
+    <Compile Include="Mono.Debugger.Soft\InvocationException.cs" />
+    <Compile Include="Mono.Debugger.Soft\InvokeOptions.cs" />
+    <Compile Include="Mono.Debugger.Soft\ITargetProcess.cs" />
+    <Compile Include="Mono.Debugger.Soft\LocalVariable.cs" />
+    <Compile Include="Mono.Debugger.Soft\Location.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodBodyMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodEntryEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodEntryEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodExitEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodExitEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\MethodMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\Mirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\ModuleMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\ObjectCollectedException.cs" />
+    <Compile Include="Mono.Debugger.Soft\ObjectMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\ParameterInfoMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\PrimitiveValue.cs" />
+    <Compile Include="Mono.Debugger.Soft\PropertyInfoMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\StackFrame.cs" />
+    <Compile Include="Mono.Debugger.Soft\StepEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\StepEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\StringMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\StructMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\SuspendPolicy.cs" />
+    <Compile Include="Mono.Debugger.Soft\ThreadDeathEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\ThreadMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\ThreadStartEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\TypeLoadEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\TypeLoadEventRequest.cs" />
+    <Compile Include="Mono.Debugger.Soft\TypeMirror.cs" />
+    <Compile Include="Mono.Debugger.Soft\UserBreakEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\UserLogEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\Value.cs" />
+    <Compile Include="Mono.Debugger.Soft\VirtualMachine.cs" />
+    <Compile Include="Mono.Debugger.Soft\VirtualMachineManager.cs" />
+    <Compile Include="Mono.Debugger.Soft\VMDeathEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\VMDisconnectedException.cs" />
+    <Compile Include="Mono.Debugger.Soft\VMDisconnectEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\VMMismatchException.cs" />
+    <Compile Include="Mono.Debugger.Soft\VMStartEvent.cs" />
+    <Compile Include="Mono.Debugger.Soft\AssemblyLoadEventRequest.cs" />
+    <Compile Include="Locale.cs" />
+    <Compile Include="Mono.Debugger.Soft\PointerValue.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Makefile.am" />
+    <None Include="mono-git-revision" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System.Core" />
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
+      <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
+      <Name>Mono.Cecil</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AbsentInformationException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AbsentInformationException.cs
new file mode 100644
index 0000000..5ce9ee2
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AbsentInformationException.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class AbsentInformationException : Exception {
+		
+		public AbsentInformationException () : base ("Debug information is not available for this frame.") {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainCreateEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainCreateEvent.cs
new file mode 100644
index 0000000..ae2a3e9
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainCreateEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class AppDomainCreateEvent : Event {
+		AppDomainMirror domain;
+		long id;
+
+		internal AppDomainCreateEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.AppDomainCreate, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public AppDomainMirror Domain {
+			get {
+				if (domain == null)
+					domain = vm.GetDomain (id);
+				return domain;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainMirror.cs
new file mode 100644
index 0000000..0b934c1
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainMirror.cs
@@ -0,0 +1,96 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class AppDomainMirror : Mirror
+	{
+		string friendly_name;
+		AssemblyMirror entry_assembly, corlib;
+
+		internal AppDomainMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		public string FriendlyName {
+			get {
+				/* The name can't be empty during domain creation */
+				if (friendly_name == null || friendly_name == String.Empty)
+					friendly_name = vm.conn.Domain_GetName (id);
+				return friendly_name;
+			}
+	    }
+
+		// Not cached
+		public AssemblyMirror[] GetAssemblies () {
+			long[] ids = vm.conn.Domain_GetAssemblies (id);
+			AssemblyMirror[] assemblies = new AssemblyMirror [ids.Length];
+			// FIXME: Uniqueness
+			for (int i = 0; i < ids.Length; ++i)
+				assemblies [i] = vm.GetAssembly (ids [i]);
+			return assemblies;
+	    }
+
+		// This returns null when called before the first AssemblyLoad event
+		public AssemblyMirror GetEntryAssembly () {
+			if (entry_assembly == null) {
+				long ass_id = vm.conn.Domain_GetEntryAssembly (id);
+
+				entry_assembly = vm.GetAssembly (ass_id);
+			}
+			return entry_assembly;
+	    }
+
+		public AssemblyMirror Corlib {
+			get {
+				if (corlib == null) {
+					long ass_id = vm.conn.Domain_GetCorlib (id);
+
+					corlib = vm.GetAssembly (ass_id);
+				}
+				return corlib;
+			}
+	    }
+
+		public StringMirror CreateString (string s) {
+			if (s == null)
+				throw new ArgumentNullException ("s");
+
+			return vm.GetObject<StringMirror> (vm.conn.Domain_CreateString (id, s));
+		}
+
+		public ObjectMirror CreateBoxedValue (Value value) {
+			if (value == null)
+				throw new ArgumentNullException ("value");
+			if (!(value is PrimitiveValue) && !(value is StructMirror))
+				throw new ArgumentException ("Value must be a PrimitiveValue or a StructMirror", "value");
+			if ((value is PrimitiveValue) && (value as PrimitiveValue).Value == null)
+				return null;
+
+			TypeMirror t = null;
+			if (value is PrimitiveValue)
+				t = GetCorrespondingType ((value as PrimitiveValue).Value.GetType ());
+			else
+				t = (value as StructMirror).Type;
+
+			return vm.GetObject<ObjectMirror> (vm.conn.Domain_CreateBoxedValue (id, t.Id, vm.EncodeValue (value)));
+		}
+
+		TypeMirror[] primitiveTypes = new TypeMirror [32];
+		
+		public TypeMirror GetCorrespondingType (Type t) {
+			if (t == null)
+				throw new ArgumentNullException ("t");
+			TypeCode tc = Type.GetTypeCode (t);
+
+			if (tc == TypeCode.Empty || tc == TypeCode.Object)
+				throw new ArgumentException ("t must be a primitive type", "t");
+
+			int tc_index = (int)tc;
+			if (primitiveTypes [tc_index] == null) {
+				primitiveTypes [tc_index] = Corlib.GetType ("System." + t.Name, false, false);
+				if (primitiveTypes [tc_index] == null)
+					throw new NotImplementedException ();
+			}
+			return primitiveTypes [tc_index];
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainUnloadEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainUnloadEvent.cs
new file mode 100644
index 0000000..e2ad5a9
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AppDomainUnloadEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class AppDomainUnloadEvent : Event {
+		AppDomainMirror domain;
+		long id;
+
+		internal AppDomainUnloadEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.AppDomainUnload, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public AppDomainMirror Domain {
+			get {
+				if (domain == null)
+					domain = vm.GetDomain (id);
+				return domain;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ArrayMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ArrayMirror.cs
new file mode 100644
index 0000000..57a7951
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ArrayMirror.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public class ArrayMirror : ObjectMirror, IEnumerable {
+
+		public int[] lengths;
+		public int[] lower_bounds;
+		public int rank;
+
+		internal ArrayMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		internal ArrayMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id, type, domain) {
+		}
+
+		public int Length {
+			get {
+				GetLengths ();
+
+				int length = lengths [0];
+
+				for (int i = 1; i < Rank; i++) {
+					length *= lengths [i];
+				}
+
+				return length;
+			}
+		}
+
+		public int Rank {
+			get {
+				GetLengths ();
+
+				return rank;
+			}
+		}
+
+		public int GetLength (int dimension) {
+			GetLengths ();
+
+			if (dimension < 0 || dimension >= Rank)
+				throw new ArgumentOutOfRangeException ("dimension");
+
+			return lengths [dimension];
+		}
+
+		public int GetLowerBound (int dimension) {
+			GetLengths ();
+
+			if (dimension < 0 || dimension >= Rank)
+				throw new ArgumentOutOfRangeException ("dimension");
+
+			return lower_bounds [dimension];
+		}
+
+		void GetLengths () {
+			if (lengths == null)
+				lengths = vm.conn.Array_GetLength (id, out this.rank, out this.lower_bounds);
+		}
+
+		public Value this [int index] {
+			get {
+				// FIXME: Multiple dimensions
+				if (index < 0 || index > Length - 1)
+					throw new IndexOutOfRangeException ();
+				return vm.DecodeValue (vm.conn.Array_GetValues (id, index, 1) [0]);
+			}
+			set {
+				// FIXME: Multiple dimensions
+				if (index < 0 || index > Length - 1)
+					throw new IndexOutOfRangeException ();
+				vm.conn.Array_SetValues (id, index, new ValueImpl [] { vm.EncodeValue (value) });
+			}
+		}
+
+		public IList<Value> GetValues (int index, int length) {
+			// FIXME: Multiple dimensions
+				if (index < 0 || index > Length - length)
+					throw new IndexOutOfRangeException ();
+			return vm.DecodeValues (vm.conn.Array_GetValues (id, index, length));
+		}
+
+		public void SetValues (int index, Value[] values) {
+			if (values == null)
+				throw new ArgumentNullException ("values");
+			// FIXME: Multiple dimensions
+			if (index < 0 || index > Length - values.Length)
+				throw new IndexOutOfRangeException ();
+			vm.conn.Array_SetValues (id, index, vm.EncodeValues (values));
+		}
+
+		IEnumerator IEnumerable.GetEnumerator ()
+		{
+			return new SimpleEnumerator (this);
+		}
+
+		internal class SimpleEnumerator : IEnumerator, ICloneable
+		{
+			ArrayMirror arr;
+			int pos, length;
+
+			public SimpleEnumerator (ArrayMirror arr)
+			{
+				this.arr = arr;
+				this.pos = -1;
+				this.length = arr.Length;
+			}
+
+			public object Current {
+				get {
+					if (pos < 0 )
+						throw new InvalidOperationException ("Enumeration has not started.");
+					if  (pos >= length)
+						throw new InvalidOperationException ("Enumeration has already ended");
+					return arr [pos];
+				}
+			}
+
+			public bool MoveNext()
+			{
+				if (pos < length)
+					pos++;
+				if(pos < length)
+					return true;
+				else
+					return false;
+			}
+
+			public void Reset()
+			{
+				pos = -1;
+			}
+
+			public object Clone ()
+			{
+				return MemberwiseClone ();
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEvent.cs
new file mode 100644
index 0000000..df9c691
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class AssemblyLoadEvent : Event {
+		AssemblyMirror assembly;
+		long id;
+
+		internal AssemblyLoadEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.AssemblyLoad, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public AssemblyMirror Assembly {
+			get {
+				if (assembly == null)
+					assembly = vm.GetAssembly (id);
+				return assembly;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEventRequest.cs
new file mode 100644
index 0000000..0ecc1b1
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEventRequest.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class AssemblyLoadEventRequest : EventRequest {		
+		internal AssemblyLoadEventRequest (VirtualMachine vm) : base (vm, EventType.AssemblyLoad) {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyMirror.cs
new file mode 100644
index 0000000..475b28a
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyMirror.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Reflection;
+using Mono.Debugger;
+using Mono.Cecil;
+
+namespace Mono.Debugger.Soft
+{
+	public class AssemblyMirror : Mirror
+	{
+		string location;
+		MethodMirror entry_point;
+		bool entry_point_set;
+		ModuleMirror main_module;
+		AssemblyName aname;
+		AssemblyDefinition meta;
+
+		internal AssemblyMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		public string Location {
+			get {
+				if (location == null)
+					location = vm.conn.Assembly_GetLocation (id);
+				return location;
+			}
+	    }
+
+		public MethodMirror EntryPoint {
+			get {
+				if (!entry_point_set) {
+					long mid = vm.conn.Assembly_GetEntryPoint (id);
+
+					if (mid != 0)
+						entry_point = vm.GetMethod (mid);
+					entry_point_set = true;
+				}
+				return entry_point;
+			}
+	    }
+
+		public ModuleMirror ManifestModule {
+			get {
+				if (main_module == null) {
+					main_module = vm.GetModule (vm.conn.Assembly_GetManifestModule (id));
+				}
+				return main_module;
+			}
+		}
+
+		public virtual AssemblyName GetName () {
+			if (aname == null) {
+				string name = vm.conn.Assembly_GetName (id);
+				aname = new AssemblyName (name);
+			}
+			return aname;
+		}
+
+		public ObjectMirror GetAssemblyObject () {
+			return vm.GetObject (vm.conn.Assembly_GetObject (id));
+		}
+
+		public TypeMirror GetType (string name, bool throwOnError, bool ignoreCase)
+		{
+			if (name == null)
+				throw new ArgumentNullException (name);
+			if (name.Length == 0)
+				throw new ArgumentException ("name", "Name cannot be empty");
+
+			if (throwOnError)
+				throw new NotImplementedException ();
+			return vm.GetType (vm.conn.Assembly_GetType (id, name, ignoreCase));
+		}
+
+		public TypeMirror GetType (String name, Boolean throwOnError)
+		{
+			return GetType (name, throwOnError, false);
+		}
+
+		public TypeMirror GetType (String name) {
+			return GetType (name, false, false);
+		}
+
+		/* 
+		 * An optional Cecil assembly which could be used to access metadata instead
+		 * of reading it from the debuggee.
+		 */
+		public AssemblyDefinition Metadata {
+			get {
+				return meta;
+			}
+			set {
+				if (value.MainModule.Name != ManifestModule.Name)
+					throw new ArgumentException ("The supplied assembly is named '" + value.MainModule.Name + "', while the assembly in the debuggee is named '" + ManifestModule.Name + "'.");
+				if (value.MainModule.Mvid != ManifestModule.ModuleVersionId)
+					throw new ArgumentException ("The supplied assembly's main module has guid '" + value.MainModule.Mvid + ", while the assembly in the debuggee has guid '" + ManifestModule.ModuleVersionId + "'.", "value");
+				meta = value;
+			}
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyUnloadEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyUnloadEvent.cs
new file mode 100644
index 0000000..cc34f8e
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/AssemblyUnloadEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class AssemblyUnloadEvent : Event {
+		AssemblyMirror assembly;
+		long id;
+
+		internal AssemblyUnloadEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.AssemblyUnload, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public AssemblyMirror Assembly {
+			get {
+				if (assembly == null)
+					assembly = vm.GetAssembly (id);
+				return assembly;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEvent.cs
new file mode 100644
index 0000000..cd52f7e
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class BreakpointEvent : Event {
+		MethodMirror method;
+		long id;
+
+		internal BreakpointEvent (VirtualMachine vm, int req_id, long thread_id, long id, long loc) : base (EventType.Breakpoint, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public MethodMirror Method {
+			get {
+				if (method == null)
+					method = vm.GetMethod (id);
+				return method;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEventRequest.cs
new file mode 100644
index 0000000..cb94851
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/BreakpointEventRequest.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class BreakpointEventRequest : EventRequest {
+
+		MethodMirror method;
+		long location;
+		
+		internal BreakpointEventRequest (VirtualMachine vm, MethodMirror method, long location) : base (vm, EventType.Breakpoint) {
+			if (method == null)
+				throw new ArgumentNullException ("method");
+			CheckMirror (vm, method);
+			if (method.Locations.Count > 0 && !method.Locations.Any (l => l.ILOffset == location))
+				throw new ArgumentException ("A breakpoint can only be set at an IL offset which is equal to the ILOffset property of one of the locations in method.Locations", "location");
+			this.method = method;
+			this.location = location;
+		}
+
+		public override void Enable () {
+			var mods = new List <Modifier> ();
+			mods.Add (new LocationModifier () { Method = method.Id, Location = location });
+			SendReq (mods);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ChangeLog b/Mono.Debugger.Soft/Mono.Debugger.Soft/ChangeLog
new file mode 100644
index 0000000..47f2476
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ChangeLog
@@ -0,0 +1,210 @@
+2010-06-17  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachine.cs Connection.cs: Group events received together into an EventSet,
+	like it is done in JDI. Add a GetNextEventSet () method.
+
+2010-06-04  Zoltan Varga  <vargaz at gmail.com>
+
+	* StackFrame.cs (GetVisibleVariables): New method to return the set of variables
+	visible at the current stack frame.
+
+2010-05-24  Martin Baulig  <martin at ximian.com>
+
+	* Connection.cs (VersionInfo): Make this public.
+
+	* VirtualMachine.cs (Version): New public property.
+
+2010-05-07  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachine.cs (ErrorHandler): Convert ABSENT_INFORMATION to
+	AbsentInformationException.
+
+	* AbsentInformationException.cs: New file.
+
+2010-04-30  Zoltan Varga  <vargaz at gmail.com>
+
+	* TypeMirror.cs: Add new overload for GetSourceFiles () which returns full paths.
+
+2010-04-27  Lluis Sanchez  <lluis at novell.com>
+
+	* ITargetProcess.cs:
+	* VirtualMachine.cs:
+	* VirtualMachineManager.cs:
+	Restored old API. Renamed IProcess to ITargetProcess everywhere
+	to avoid naming conflicts.
+
+2010-04-26  Lluis Sanchez  <lluis at novell.com>
+
+	* IProcess.cs:
+	* VirtualMachine.cs:
+	* VirtualMachineManager.cs:
+	Added new IProcess interface which wraps the debugged process.
+	This abstraction makes it easier to support debugging processes
+	for which we don't have a direct Process reference (for example,
+	if the process is remote).
+
+2010-04-10  Zoltan Varga  <vargaz at gmail.com>
+
+	* ThreadMirror.cs: Add a ThreadId property.
+
+2010-03-05  Martin Baulig  <martin at ximian.com>
+
+	Add support for aborting invocations.
+
+	* IInvokeAsyncResult.cs: New file.
+	(IInvokeAsyncResult): New public interface; derives from
+	`IAsyncResult' and contains an Abort() method.
+
+	* Connection.cs
+	(Connection.VM_BeginInvokeMethod): Return the `id'.
+	(Connection.VM_AbortInvoke): New method.
+
+	* ObjectMirror.cs
+	(ObjectMirror.AbortInvoke): New internal static method.
+
+2010-03-01  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachine.cs: Allow working with runtimes implementing a different
+	minor version of the debugger protocol.
+
+2010-03-01  Zoltan Varga  <vargaz at gmail.com>
+
+	* Connection.cs: Send the protocol version used by the client to the debuggee
+	after the handshake.
+
+2010-03-01  Zoltan Varga  <vargaz at gmail.com>
+
+	* Location.cs: Implement ToString ().
+
+	* AppDomainMirror.cs (CreateBoxedValue): New method to create a boxed value from
+	a primitive value or struct.
+
+2010-02-26  Zoltan Varga  <vargaz at gmail.com>
+
+	* Connection.cs: Throw a NotSupportedException if the protocol version doesn't
+	support the caught/uncaught flags in an exception modifier.
+
+2010-02-20  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachine.cs (CreateExceptionRequest): Add an overload taking two
+	booleans which specify whenever to report caught/uncaught exceptions.
+
+	* ExceptionRequest.cs: Add public properties for them.
+
+	* Connections.cs: Pass the caught/uncaught flags to the debuggee. Bump protocol
+	minor version.
+
+2010-02-11  Zoltan Varga  <vargaz at gmail.com>
+
+	* AssemblyMirror.cs: Add missing GetType () overloads.
+
+2010-02-04  Zoltan Varga  <vargaz at gmail.com>
+
+	* TypeMirror.cs (EnumUnderlyingType): New property.
+
+	* EnumMirror.cs: Use it.
+
+	* VirtualMachine.cs (CreateEnumMirror): New method to create an EnumMirror.
+
+	* AppDomainMirror.cs (GetCorrespondingType): New method to return a TypeMirror
+	corresponding to a primitive type.
+
+	* TypeMirror.cs (IsEnum): Implement.
+
+	* EnumMirror.cs (.ctor): New internal constructor called from CreateEnumMirror
+	which does lots of error checking.
+
+2010-01-28  Zoltan Varga  <vargaz at gmail.com>
+
+	* AssemblyUnloadEvent: New file.
+
+	* VirtualMachine.cs Connection.cs: Add support for assembly unload events.
+
+2009-12-05  Lluis Sanchez  <lluis at novell.com>
+
+	* StructMirror.cs: Fix field indexer for structs with static fields.
+	* VirtualMachineManager.cs: Added an option to LaunchOptions which
+	allows providing a custom method for launching the process. This
+	allows launching mono in a wrapper process.
+
+2009-12-03  Zoltan Varga  <vargaz at gmail.com>
+
+	* StructMirror.cs (this): Ignore static fields.
+
+2009-12-02  Geoff Norton  <gnorton at novell.com>
+
+	* VirtualMachineManager.cs: We might get a SocketException (interrupted)
+	here, so lets just handle all Exceptions to our Accept pattern the same
+	way
+
+2009-12-01  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachine.cs (ErrorHandler): Handle NOT_SUSPENDED error code too.
+
+2009-11-24  Zoltan Varga  <vargaz at gmail.com>
+
+	* ObjectMirror.cs TypeMirror.cs StructMirror.cs: Make the BeginInvokeMethod
+	which takes a 'vm' argument obsolete, it was added by mistake, add a version
+	without that argument instead.
+
+2009-11-19  Zoltan Varga  <vargaz at gmail.com>
+
+	* AssemblyMirror.cs: Add a GetName () method.
+
+2009-11-17  Zoltan Varga  <vargaz at gmail.com>
+
+	* Connection.cs ObjectMirror.cs: Implement invokes in a real asynchronous way,
+	without waiting.
+
+2009-11-14  Zoltan Varga  <vargaz at gmail.com>
+
+	* InvokeOptions.cs: Add SingleThreaded option, not yet works.
+
+	* VirtualMachineManager.cs (Launch): Pass options to BeginLaunch.
+
+	* ObjectMirror.cs TypeMirror.cs StructMirror.cs: Implement an async version of
+	InvokeMethod ().
+
+2009-11-13  Zoltan Varga  <vargaz at gmail.com>
+
+	* InvokeOptions.cs: New file.
+
+	* ObjectMirror.cs TypeMirror.cs StructMirror.cs: Add support for passing flags
+	to InvokeMethod ().
+
+	* Connection.cs: Bump protocol version.
+
+2009-11-12  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachineManager.cs: Put back the old Launch (string[], LaunchOptions)
+	overload.
+
+2009-11-11  Geoff Norton  <gnorton at novell.com>
+
+	* VirtualMachineManager.cs: Refactor the APIs to have async methods.
+	Remove a bunch of Listen overloads that are pointless.  Refactor
+	Launch to take a ProcessStartInfo instead of string arguments.
+
+2009-11-10  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachineManager.cs (Launch): Close the listening socket instead of
+	shutting it down since Shutdown throws on exception on non-connected sockets
+	in ms.net.
+
+2009-11-05  Zoltan Varga  <vargaz at gmail.com>
+
+	* VirtualMachineManager.cs (Listen): Resurrect the old listen method.
+
+	* VirtualMachineManager.cs (Connect): New method to connect to a runtime
+	listening at the provided address.
+
+2009-11-04  Lluis Sanchez  <lluis at novell.com>
+
+	* VirtualMachineManager.cs: Properly redirect standard output.
+
+2009-11-03  Zoltan Varga  <vargaz at gmail.com>
+
+	* EventRequest.cs (AssemblyFilter): New property to filter
+	events based on a list of assemblies.
+
+	* Connection.cs: Add assembly filters to the protocol implementation.
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
new file mode 100644
index 0000000..28ddb0f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
@@ -0,0 +1,2393 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class VersionInfo {
+		public string VMVersion {
+			get; set;
+		}
+
+		public int MajorVersion {
+			get; set;
+		}
+
+		public int MinorVersion {
+			get; set;
+		}
+
+		/*
+		 * Check that this version is at least major:minor
+		 */
+		public bool AtLeast (int major, int minor) {
+			if ((MajorVersion > major) || ((MajorVersion == major && MinorVersion >= minor)))
+				return true;
+			else
+				return false;
+		}
+	}
+
+	struct SourceInfo {
+		public string source_file;
+		public byte[] guid, hash;
+	}
+
+	class DebugInfo {
+		public int max_il_offset;
+		public int[] il_offsets;
+		public int[] line_numbers;
+		public int[] column_numbers;
+		public SourceInfo[] source_files;
+	}
+
+	struct FrameInfo {
+		public long id;
+		public long method;
+		public int il_offset;
+		public StackFrameFlags flags;
+	}
+
+	class TypeInfo {
+		public string ns, name, full_name;
+		public long assembly, module, base_type, element_type;
+		public int token, rank, attributes;
+		public bool is_byref, is_pointer, is_primitive, is_valuetype, is_enum;
+		public bool is_gtd, is_generic_type;
+		public long[] nested;
+		public long gtd;
+		public long[] type_args;
+	}
+
+	struct IfaceMapInfo {
+		public long iface_id;
+		public long[] iface_methods;
+		public long[] target_methods;
+	}
+
+	class MethodInfo {
+		public int attributes, iattributes, token;
+		public bool is_gmd, is_generic_method;
+		public long gmd;
+		public long[] type_args;
+	}
+
+	class MethodBodyInfo {
+		public byte[] il;
+		public ExceptionClauseInfo[] clauses;
+	}
+
+	struct ExceptionClauseInfo {
+		public ExceptionClauseFlags flags;
+		public int try_offset;
+		public int try_length;
+		public int handler_offset;
+		public int handler_length;
+		public int filter_offset;
+		public long catch_type_id;
+	}
+
+	[Flags]
+	enum ExceptionClauseFlags {
+		None = 0x0,
+		Filter = 0x1,
+		Finally = 0x2,
+		Fault = 0x4,
+	}
+
+	struct ParamInfo {
+		public int call_conv;
+		public int param_count;
+		public int generic_param_count;
+		public long ret_type;
+		public long[] param_types;
+		public string[] param_names;
+	}
+
+	struct LocalsInfo {
+		public long[] types;
+		public string[] names;
+		public int[] live_range_start;
+		public int[] live_range_end;
+	}
+
+	struct PropInfo {
+		public long id;
+		public string name;
+		public long get_method, set_method;
+		public int attrs;
+	}
+
+	class CattrNamedArgInfo {
+		public bool is_property;
+		public long id;
+		public ValueImpl value;
+	}
+
+	class CattrInfo {
+		public long ctor_id;
+		public ValueImpl[] ctor_args;
+		public CattrNamedArgInfo[] named_args;
+	}
+
+	class ThreadInfo {
+		public bool is_thread_pool;
+	}
+
+	struct ObjectRefInfo {
+		public long type_id;
+		public long domain_id;
+	}
+
+	enum ValueTypeId {
+		VALUE_TYPE_ID_NULL = 0xf0,
+		VALUE_TYPE_ID_TYPE = 0xf1
+	}
+
+	[Flags]
+	enum InvokeFlags {
+		NONE = 0x0,
+		DISABLE_BREAKPOINTS = 0x1,
+		SINGLE_THREADED = 0x2
+	}
+
+	enum ElementType {
+		End		 = 0x00,
+		Void		= 0x01,
+		Boolean	 = 0x02,
+		Char		= 0x03,
+		I1		  = 0x04,
+		U1		  = 0x05,
+		I2		  = 0x06,
+		U2		  = 0x07,
+		I4		  = 0x08,
+		U4		  = 0x09,
+		I8		  = 0x0a,
+		U8		  = 0x0b,
+		R4		  = 0x0c,
+		R8		  = 0x0d,
+		String	  = 0x0e,
+		Ptr		 = 0x0f,
+		ByRef	   = 0x10,
+		ValueType   = 0x11,
+		Class	   = 0x12,
+		Var        = 0x13,
+		Array	   = 0x14,
+		GenericInst = 0x15,
+		TypedByRef  = 0x16,
+		I		   = 0x18,
+		U		   = 0x19,
+		FnPtr	   = 0x1b,
+		Object	  = 0x1c,
+		SzArray	 = 0x1d,
+		MVar       = 0x1e,
+		CModReqD	= 0x1f,
+		CModOpt	 = 0x20,
+		Internal	= 0x21,
+		Modifier	= 0x40,
+		Sentinel	= 0x41,
+		Pinned	  = 0x45,
+
+		Type		= 0x50,
+		Boxed	   = 0x51,
+		Enum		= 0x55
+	}
+
+	class ValueImpl {
+		public ElementType Type; /* or one of the VALUE_TYPE_ID constants */
+		public long Objid;
+		public object Value;
+		public long Klass; // For ElementType.ValueType
+		public ValueImpl[] Fields; // for ElementType.ValueType
+		public bool IsEnum; // For ElementType.ValueType
+		public long Id; /* For VALUE_TYPE_ID_TYPE */
+	}
+
+	class ModuleInfo {
+		public string Name, ScopeName, FQName, Guid;
+		public long Assembly;
+	}		
+
+	enum TokenType {
+		STRING = 0,
+		TYPE = 1,
+		FIELD = 2,
+		METHOD = 3,
+		UNKNOWN = 4
+	}
+
+	[Flags]
+	enum StackFrameFlags {
+		NONE = 0,
+		DEBUGGER_INVOKE = 1,
+		NATIVE_TRANSITION = 2
+	}
+
+	class ResolvedToken {
+		public TokenType Type;
+		public string Str;
+		public long Id;
+	}
+
+	class Modifier {
+	}
+
+	class CountModifier : Modifier {
+		public int Count {
+			get; set;
+		}
+	}
+
+	class LocationModifier : Modifier {
+		public long Method {
+			get; set;
+		}
+
+		public long Location {
+			get; set;
+		}
+	}
+
+	class StepModifier : Modifier {
+		public long Thread {
+			get; set;
+		}
+
+		public int Depth {
+			get; set;
+		}
+
+		public int Size {
+			get; set;
+		}
+
+		public int Filter {
+			get; set;
+		}
+	}
+
+	class ThreadModifier : Modifier {
+		public long Thread {
+			get; set;
+		}
+	}
+
+	class ExceptionModifier : Modifier {
+		public long Type {
+			get; set;
+		}
+		public bool Caught {
+			get; set;
+		}
+		public bool Uncaught {
+			get; set;
+		}
+		public bool Subclasses {
+			get; set;
+		}
+	}
+
+	class AssemblyModifier : Modifier {
+		public long[] Assemblies {
+			get; set;
+		}
+	}
+
+	class SourceFileModifier : Modifier {
+		public string[] SourceFiles {
+			get; set;
+		}
+	}
+
+	class TypeNameModifier : Modifier {
+		public string[] TypeNames {
+			get; set;
+		}
+	}
+
+	class EventInfo {
+		public EventType EventType {
+			get; set;
+		}
+
+		public int ReqId {
+			get; set;
+		}
+
+		public SuspendPolicy SuspendPolicy {
+			get; set;
+		}
+
+		public long ThreadId {
+			get; set;
+		}
+
+		public long Id {
+			get; set;
+		}
+
+		public long Location {
+			get; set;
+		}
+
+		public int Level {
+			get; set;
+		}
+
+		public string Category {
+			get; set;
+		}
+
+		public string Message {
+			get; set;
+		}
+
+		public EventInfo (EventType type, int req_id) {
+			EventType = type;
+			ReqId = req_id;
+		}
+	}
+
+	public enum ErrorCode {
+		NONE = 0,
+		INVALID_OBJECT = 20,
+		INVALID_FIELDID = 25,
+		INVALID_FRAMEID = 30,
+		NOT_IMPLEMENTED = 100,
+		NOT_SUSPENDED = 101,
+		INVALID_ARGUMENT = 102,
+		ERR_UNLOADED = 103,
+		ERR_NO_INVOCATION = 104,
+		ABSENT_INFORMATION = 105,
+		NO_SEQ_POINT_AT_IL_OFFSET = 106
+	}
+
+	public class ErrorHandlerEventArgs : EventArgs {
+
+		public ErrorCode ErrorCode {
+			get; set;
+		}
+	}
+
+	/*
+	 * Represents the connection to the debuggee
+	 */
+	public abstract class Connection
+	{
+		/*
+		 * The protocol and the packet format is based on JDWP, the differences 
+		 * are in the set of supported events, and the commands.
+		 */
+		internal const string HANDSHAKE_STRING = "DWP-Handshake";
+
+		internal const int HEADER_LENGTH = 11;
+
+		static readonly bool EnableConnectionLogging = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONO_SDB_LOG"));
+		static int ConnectionId;
+		readonly StreamWriter LoggingStream = EnableConnectionLogging ? 
+			new StreamWriter (string.Format ("/tmp/sdb_conn_log_{0}", ConnectionId++), false) : null;
+
+		/*
+		 * Th version of the wire-protocol implemented by the library. The library
+		 * and the debuggee can communicate if they implement the same major version.
+		 * If they implement a different minor version, they can communicate, but some
+		 * features might not be available. This allows older clients to communicate
+		 * with newer runtimes, and vice versa.
+		 */
+		internal const int MAJOR_VERSION = 2;
+		internal const int MINOR_VERSION = 26;
+
+		enum WPSuspendPolicy {
+			NONE = 0,
+			EVENT_THREAD = 1,
+			ALL = 2
+		}
+
+		enum CommandSet {
+			VM = 1,
+			OBJECT_REF = 9,
+			STRING_REF = 10,
+			THREAD = 11,
+			ARRAY_REF = 13,
+			EVENT_REQUEST = 15,
+			STACK_FRAME = 16,
+			APPDOMAIN = 20,
+			ASSEMBLY = 21,
+			METHOD = 22,
+			TYPE = 23,
+			MODULE = 24,
+			EVENT = 64
+		}
+
+		enum EventKind {
+			VM_START = 0,
+			VM_DEATH = 1,
+			THREAD_START = 2,
+			THREAD_DEATH = 3,
+			APPDOMAIN_CREATE = 4, // Not in JDI
+			APPDOMAIN_UNLOAD = 5, // Not in JDI
+			METHOD_ENTRY = 6,
+			METHOD_EXIT = 7,
+			ASSEMBLY_LOAD = 8,
+			ASSEMBLY_UNLOAD = 9,
+			BREAKPOINT = 10,
+			STEP = 11,
+			TYPE_LOAD = 12,
+			EXCEPTION = 13,
+			KEEPALIVE = 14,
+			USER_BREAK = 15,
+			USER_LOG = 16
+		}
+
+		enum ModifierKind {
+			COUNT = 1,
+			THREAD_ONLY = 3,
+			LOCATION_ONLY = 7,
+			EXCEPTION_ONLY = 8,
+			STEP = 10,
+			ASSEMBLY_ONLY = 11,
+			SOURCE_FILE_ONLY = 12,
+			TYPE_NAME_ONLY = 13
+		}
+
+		enum CmdVM {
+			VERSION = 1,
+			ALL_THREADS = 2,
+			SUSPEND = 3,
+			RESUME = 4,
+			EXIT = 5,
+			DISPOSE = 6,
+			INVOKE_METHOD = 7,
+			SET_PROTOCOL_VERSION = 8,
+			ABORT_INVOKE = 9,
+			SET_KEEPALIVE = 10,
+			GET_TYPES_FOR_SOURCE_FILE = 11,
+			GET_TYPES = 12,
+			INVOKE_METHODS = 13
+		}
+
+		enum CmdEvent {
+			COMPOSITE = 100
+		}
+
+		enum CmdThread {
+			GET_FRAME_INFO = 1,
+			GET_NAME = 2,
+			GET_STATE = 3,
+			GET_INFO = 4,
+			/* FIXME: Merge into GET_INFO when the major protocol version is increased */
+			GET_ID = 5,
+			/* Ditto */
+			GET_TID = 6
+		}
+
+		enum CmdEventRequest {
+			SET = 1,
+			CLEAR = 2,
+			CLEAR_ALL_BREAKPOINTS = 3
+		}
+
+		enum CmdAppDomain {
+			GET_ROOT_DOMAIN = 1,
+			GET_FRIENDLY_NAME = 2,
+			GET_ASSEMBLIES = 3,
+			GET_ENTRY_ASSEMBLY = 4,
+			CREATE_STRING = 5,
+			GET_CORLIB = 6,
+			CREATE_BOXED_VALUE = 7
+		}
+
+		enum CmdAssembly {
+			GET_LOCATION = 1,
+			GET_ENTRY_POINT = 2,
+			GET_MANIFEST_MODULE = 3,
+			GET_OBJECT = 4,
+			GET_TYPE = 5,
+			GET_NAME = 6
+		}
+
+		enum CmdModule {
+			GET_INFO = 1,
+		}
+
+		enum CmdMethod {
+			GET_NAME = 1,
+			GET_DECLARING_TYPE = 2,
+			GET_DEBUG_INFO = 3,
+			GET_PARAM_INFO = 4,
+			GET_LOCALS_INFO = 5,
+			GET_INFO = 6,
+			GET_BODY = 7,
+			RESOLVE_TOKEN = 8,
+			GET_CATTRS = 9,
+			MAKE_GENERIC_METHOD = 10
+		}
+
+		enum CmdType {
+			GET_INFO = 1,
+			GET_METHODS = 2,
+			GET_FIELDS = 3,
+			GET_VALUES = 4,
+			GET_OBJECT = 5,
+			GET_SOURCE_FILES = 6,
+			SET_VALUES = 7,
+			IS_ASSIGNABLE_FROM = 8,
+			GET_PROPERTIES = 9,
+			GET_CATTRS = 10,
+			GET_FIELD_CATTRS = 11,
+			GET_PROPERTY_CATTRS = 12,
+			/* FIXME: Merge into GET_SOURCE_FILES when the major protocol version is increased */
+			GET_SOURCE_FILES_2 = 13,
+			/* FIXME: Merge into GET_VALUES when the major protocol version is increased */
+			GET_VALUES_2 = 14,
+			CMD_TYPE_GET_METHODS_BY_NAME_FLAGS = 15,
+			GET_INTERFACES = 16,
+			GET_INTERFACE_MAP = 17,
+			IS_INITIALIZED = 18
+		}
+
+		[Flags]
+		enum BindingFlagsExtensions {
+			BINDING_FLAGS_IGNORE_CASE = 0x70000000,
+		}
+
+		enum CmdStackFrame {
+			GET_VALUES = 1,
+			GET_THIS = 2,
+			SET_VALUES = 3
+		}
+
+		enum CmdArrayRef {
+			GET_LENGTH = 1,
+			GET_VALUES = 2,
+			SET_VALUES = 3
+		}
+
+		enum CmdStringRef {
+			GET_VALUE = 1,
+			GET_LENGTH = 2,
+			GET_CHARS = 3
+		}
+
+		enum CmdObjectRef {
+			GET_TYPE = 1,
+			GET_VALUES = 2,
+			IS_COLLECTED = 3,
+			GET_ADDRESS = 4,
+			GET_DOMAIN = 5,
+			SET_VALUES = 6,
+			GET_INFO = 7,
+		}
+
+		class Header {
+			public int id;
+			public int command_set;
+			public int command;
+			public int flags;
+		}			
+
+		internal static int GetPacketLength (byte[] header) {
+			int offset = 0;
+			return decode_int (header, ref offset);
+		}
+
+		internal static bool IsReplyPacket (byte[] packet) {
+			int offset = 8;
+			return decode_byte (packet, ref offset) == 0x80;
+		}
+
+		internal static int GetPacketId (byte[] packet) {
+			int offset = 4;
+			return decode_int (packet, ref offset);
+		}
+
+		static int decode_byte (byte[] packet, ref int offset) {
+			return packet [offset++];
+		}
+
+		static int decode_short (byte[] packet, ref int offset) {
+			int res = ((int)packet [offset] << 8) | (int)packet [offset + 1];
+			offset += 2;
+			return res;
+		}
+
+		static int decode_int (byte[] packet, ref int offset) {
+			int res = ((int)packet [offset] << 24) | ((int)packet [offset + 1] << 16) | ((int)packet [offset + 2] << 8) | (int)packet [offset + 3];
+			offset += 4;
+			return res;
+		}
+
+		static long decode_id (byte[] packet, ref int offset) {
+			return decode_int (packet, ref offset);
+		}
+
+		static long decode_long (byte[] packet, ref int offset) {
+			uint high = (uint)decode_int (packet, ref offset);
+			uint low = (uint)decode_int (packet, ref offset);
+
+			return (long)(((ulong)high << 32) | (ulong)low);
+		}
+
+		internal static SuspendPolicy decode_suspend_policy (int suspend_policy) {
+			switch ((WPSuspendPolicy)suspend_policy) {
+			case WPSuspendPolicy.NONE:
+				return SuspendPolicy.None;
+			case WPSuspendPolicy.EVENT_THREAD:
+				return SuspendPolicy.EventThread;
+			case WPSuspendPolicy.ALL:
+				return SuspendPolicy.All;
+			default:
+				throw new NotImplementedException ();
+			}
+		}
+
+		static Header decode_command_header (byte[] packet) {
+			int offset = 0;
+			Header res = new Header ();
+
+			decode_int (packet, ref offset);
+			res.id = decode_int (packet, ref offset);
+			res.flags = decode_byte (packet, ref offset);
+			res.command_set = decode_byte (packet, ref offset);
+			res.command = decode_byte (packet, ref offset);
+
+			return res;
+		}
+
+		static void encode_byte (byte[] buf, int b, ref int offset) {
+			buf [offset] = (byte)b;
+			offset ++;
+		}
+
+		static void encode_int (byte[] buf, int i, ref int offset) {
+			buf [offset] = (byte)((i >> 24) & 0xff);
+			buf [offset + 1] = (byte)((i >> 16) & 0xff);
+			buf [offset + 2] = (byte)((i >> 8) & 0xff);
+			buf [offset + 3] = (byte)((i >> 0) & 0xff);
+			offset += 4;
+		}
+
+		static void encode_id (byte[] buf, long id, ref int offset) {
+			encode_int (buf, (int)id, ref offset);
+		}
+
+		static void encode_long (byte[] buf, long l, ref int offset) {
+			encode_int (buf, (int)((l >> 32) & 0xffffffff), ref offset);
+			encode_int (buf, (int)(l & 0xffffffff), ref offset);
+		}
+
+		internal static byte[] EncodePacket (int id, int commandSet, int command, byte[] data, int dataLen) {
+			byte[] buf = new byte [dataLen + 11];
+			int offset = 0;
+			
+			encode_int (buf, buf.Length, ref offset);
+			encode_int (buf, id, ref offset);
+			encode_byte (buf, 0, ref offset);
+			encode_byte (buf, commandSet, ref offset);
+			encode_byte (buf, command, ref offset);
+
+			for (int i = 0; i < dataLen; ++i)
+				buf [offset + i] = data [i];
+
+			return buf;
+		}
+
+		class PacketReader {
+			byte[] packet;
+			int offset;
+
+			public PacketReader (byte[] packet) {
+				this.packet = packet;
+
+				// For event packets
+				Header header = decode_command_header (packet);
+				CommandSet = (CommandSet)header.command_set;
+				Command = header.command;
+
+				// For reply packets
+				offset = 0;
+				ReadInt (); // length
+				ReadInt (); // id
+				ReadByte (); // flags
+				ErrorCode = ReadShort ();
+			}
+
+			public CommandSet CommandSet {
+				get; set;
+			}
+
+			public int Command {
+				get; set;
+			}
+
+			public int ErrorCode {
+				get; set;
+			}
+
+			public int Offset {
+				get {
+					return offset;
+				}
+			}
+
+			public int ReadByte () {
+				return decode_byte (packet, ref offset);
+			}
+
+			public int ReadShort () {
+				return decode_short (packet, ref offset);
+			}
+
+			public int ReadInt () {
+				return decode_int (packet, ref offset);
+			}
+
+			public long ReadId () {
+				return decode_id (packet, ref offset);
+			}
+
+			public long ReadLong () {
+				return decode_long (packet, ref offset);
+			}
+
+			public float ReadFloat () {
+				float f = DataConverter.FloatFromBE (packet, offset);
+				offset += 4;
+				return f;
+			}
+
+			public double ReadDouble () {
+				double d = DataConverter.DoubleFromBE (packet, offset);
+				offset += 8;
+				return d;
+			}
+
+			public string ReadString () {
+				int len = decode_int (packet, ref offset);
+				string res = new String (Encoding.UTF8.GetChars (packet, offset, len));
+				offset += len;
+				return res;
+			}
+
+			public ValueImpl ReadValue () {
+				ElementType etype = (ElementType)ReadByte ();
+
+				switch (etype) {
+				case ElementType.Void:
+					return new ValueImpl { Type = etype };
+				case ElementType.I1:
+					return new ValueImpl { Type = etype, Value = (sbyte)ReadInt () };
+				case ElementType.U1:
+					return new ValueImpl { Type = etype, Value = (byte)ReadInt () };
+				case ElementType.Boolean:
+					return new ValueImpl { Type = etype, Value = ReadInt () != 0 };
+				case ElementType.I2:
+					return new ValueImpl { Type = etype, Value = (short)ReadInt () };
+				case ElementType.U2:
+					return new ValueImpl { Type = etype, Value = (ushort)ReadInt () };
+				case ElementType.Char:
+					return new ValueImpl { Type = etype, Value = (char)ReadInt () };
+				case ElementType.I4:
+					return new ValueImpl { Type = etype, Value = ReadInt () };
+				case ElementType.U4:
+					return new ValueImpl { Type = etype, Value = (uint)ReadInt () };
+				case ElementType.I8:
+					return new ValueImpl { Type = etype, Value = ReadLong () };
+				case ElementType.U8:
+					return new ValueImpl { Type = etype, Value = (ulong)ReadLong () };
+				case ElementType.R4:
+					return new ValueImpl { Type = etype, Value = ReadFloat () };
+				case ElementType.R8:
+					return new ValueImpl { Type = etype, Value = ReadDouble () };
+				case ElementType.I:
+				case ElementType.U:
+				case ElementType.Ptr:
+					// FIXME: The client and the debuggee might have different word sizes
+					return new ValueImpl { Type = etype, Value = ReadLong () };
+				case ElementType.String:
+				case ElementType.SzArray:
+				case ElementType.Class:
+				case ElementType.Array:
+				case ElementType.Object:
+					long objid = ReadId ();
+					return new ValueImpl () { Type = etype, Objid = objid };
+				case ElementType.ValueType:
+					bool is_enum = ReadByte () == 1;
+					long klass = ReadId ();
+					long nfields = ReadInt ();
+					ValueImpl[] fields = new ValueImpl [nfields];
+					for (int i = 0; i < nfields; ++i)
+						fields [i] = ReadValue ();
+					return new ValueImpl () { Type = etype, Klass = klass, Fields = fields, IsEnum = is_enum };
+				case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
+					return new ValueImpl { Type = etype };
+				case (ElementType)ValueTypeId.VALUE_TYPE_ID_TYPE:
+					return new ValueImpl () { Type = etype, Id = ReadId () };
+				default:
+					throw new NotImplementedException ("Unable to handle type " + etype);
+				}
+			}
+
+			public long[] ReadIds (int n) {
+				long[] res = new long [n];
+				for (int i = 0; i < n; ++i)
+					res [i] = ReadId ();
+				return res;
+			}
+		}
+
+		class PacketWriter {
+
+			byte[] data;
+			int offset;
+
+			public PacketWriter () {
+				data = new byte [1024];
+				offset = 0;
+			}
+
+			void MakeRoom (int size) {
+				if (offset + size >= data.Length) {
+					int new_len = data.Length * 2;
+					while (new_len < offset + size) {
+						new_len *= 2;
+					}
+					byte[] new_data = new byte [new_len];
+					Array.Copy (data, new_data, data.Length);
+					data = new_data;
+				}
+			}
+
+			public PacketWriter WriteByte (byte val) {
+				MakeRoom (1);
+				encode_byte (data, val, ref offset);
+				return this;
+			}
+
+			public PacketWriter WriteInt (int val) {
+				MakeRoom (4);
+				encode_int (data, val, ref offset);
+				return this;
+			}
+
+			public PacketWriter WriteId (long id) {
+				MakeRoom (8);
+				encode_id (data, id, ref offset);
+				return this;
+			}
+
+			public PacketWriter WriteLong (long val) {
+				MakeRoom (8);
+				encode_long (data, val, ref offset);
+				return this;
+			}
+
+			public PacketWriter WriteFloat (float f) {
+				MakeRoom (8);
+				byte[] b = DataConverter.GetBytesBE (f);
+				for (int i = 0; i < 4; ++i)
+					data [offset + i] = b [i];
+				offset += 4;
+				return this;
+			}
+
+			public PacketWriter WriteDouble (double d) {
+				MakeRoom (8);
+				byte[] b = DataConverter.GetBytesBE (d);
+				for (int i = 0; i < 8; ++i)
+					data [offset + i] = b [i];
+				offset += 8;
+				return this;
+			}
+
+			public PacketWriter WriteInts (int[] ids) {
+				for (int i = 0; i < ids.Length; ++i)
+					WriteInt (ids [i]);
+				return this;
+			}
+
+			public PacketWriter WriteIds (long[] ids) {
+				for (int i = 0; i < ids.Length; ++i)
+					WriteId (ids [i]);
+				return this;
+			}
+
+			public PacketWriter WriteString (string s) {
+				if (s == null)
+					return WriteInt (-1);
+
+				byte[] b = Encoding.UTF8.GetBytes (s);
+				MakeRoom (4);
+				encode_int (data, b.Length, ref offset);
+				MakeRoom (b.Length);
+				Buffer.BlockCopy (b, 0, data, offset, b.Length);
+				offset += b.Length;
+				return this;
+			}
+
+			public PacketWriter WriteBool (bool val) {
+				WriteByte (val ? (byte)1 : (byte)0);
+				return this;
+			}
+
+			public PacketWriter WriteValue (ValueImpl v) {
+				ElementType t;
+
+				if (v.Value != null)
+					t = TypeCodeToElementType (Type.GetTypeCode (v.Value.GetType ()));
+				else
+					t = v.Type;
+				WriteByte ((byte)t);
+				switch (t) {
+				case ElementType.Boolean:
+					WriteInt ((bool)v.Value ? 1 : 0);
+					break;
+				case ElementType.Char:
+					WriteInt ((int)(char)v.Value);
+					break;
+				case ElementType.I1:
+					WriteInt ((int)(sbyte)v.Value);
+					break;
+				case ElementType.U1:
+					WriteInt ((int)(byte)v.Value);
+					break;
+				case ElementType.I2:
+					WriteInt ((int)(short)v.Value);
+					break;
+				case ElementType.U2:
+					WriteInt ((int)(ushort)v.Value);
+					break;
+				case ElementType.I4:
+					WriteInt ((int)(int)v.Value);
+					break;
+				case ElementType.U4:
+					WriteInt ((int)(uint)v.Value);
+					break;
+				case ElementType.I8:
+					WriteLong ((long)(long)v.Value);
+					break;
+				case ElementType.U8:
+					WriteLong ((long)(ulong)v.Value);
+					break;
+				case ElementType.R4:
+					WriteFloat ((float)v.Value);
+					break;
+				case ElementType.R8:
+					WriteDouble ((double)v.Value);
+					break;
+				case ElementType.String:
+				case ElementType.SzArray:
+				case ElementType.Class:
+				case ElementType.Array:
+				case ElementType.Object:
+					WriteId (v.Objid);
+					break;
+				case ElementType.ValueType:
+					// FIXME: 
+					if (v.IsEnum)
+						throw new NotImplementedException ();
+					WriteByte (0);
+					WriteId (v.Klass);
+					WriteInt (v.Fields.Length);
+					for (int i = 0; i < v.Fields.Length; ++i)
+						WriteValue (v.Fields [i]);
+					break;
+				case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
+					break;
+				default:
+					throw new NotImplementedException ();
+				}
+
+				return this;
+			}
+
+			public PacketWriter WriteValues (ValueImpl[] values) {
+				for (int i = 0; i < values.Length; ++i)
+					WriteValue (values [i]);
+				return this;
+			}
+
+			public byte[] Data {
+				get {
+					return data;
+				}
+			}
+
+			public int Offset {
+				get {
+					return offset;
+				}
+			}
+		}
+
+		delegate void ReplyCallback (int packet_id, byte[] packet);
+
+		bool closed;
+		Thread receiver_thread;
+		Dictionary<int, byte[]> reply_packets;
+		Dictionary<int, ReplyCallback> reply_cbs;
+		Dictionary<int, int> reply_cb_counts;
+		object reply_packets_monitor;
+
+		internal event EventHandler<ErrorHandlerEventArgs> ErrorHandler;
+
+		protected Connection () {
+			closed = false;
+			reply_packets = new Dictionary<int, byte[]> ();
+			reply_cbs = new Dictionary<int, ReplyCallback> ();
+			reply_cb_counts = new Dictionary<int, int> ();
+			reply_packets_monitor = new Object ();
+		}
+		
+		protected abstract int TransportReceive (byte[] buf, int buf_offset, int len);
+		protected abstract int TransportSend (byte[] buf, int buf_offset, int len);
+		protected abstract void TransportSetTimeouts (int send_timeout, int receive_timeout);
+		protected abstract void TransportClose ();
+
+		internal VersionInfo Version;
+		
+		int Receive (byte[] buf, int buf_offset, int len) {
+			int offset = 0;
+
+			while (offset < len) {
+				int n = TransportReceive (buf, buf_offset + offset, len - offset);
+
+				if (n == 0)
+					return offset;
+				offset += n;
+			}
+
+			return offset;
+		}
+		
+		// Do the wire protocol handshake
+		internal void Connect () {
+			byte[] buf = new byte [HANDSHAKE_STRING.Length];
+			char[] cbuf = new char [buf.Length];
+
+			// FIXME: Add a timeout
+			int n = Receive (buf, 0, buf.Length);
+			if (n == 0)
+				throw new IOException ("DWP Handshake failed.");
+			for (int i = 0; i < buf.Length; ++i)
+				cbuf [i] = (char)buf [i];
+
+			if (new String (cbuf) != HANDSHAKE_STRING)
+				throw new IOException ("DWP Handshake failed.");
+			
+			TransportSend (buf, 0, buf.Length);
+
+			receiver_thread = new Thread (new ThreadStart (receiver_thread_main));
+			receiver_thread.Name = "SDB Receiver";
+			receiver_thread.IsBackground = true;
+			receiver_thread.Start ();
+
+			Version = VM_GetVersion ();
+
+			//
+			// Tell the debuggee our protocol version, so newer debuggees can work
+			// with older clients
+			//
+
+			//
+			// Older debuggees might not support this request
+			EventHandler<ErrorHandlerEventArgs> OrigErrorHandler = ErrorHandler;
+			ErrorHandler = null;
+			ErrorHandler += delegate (object sender, ErrorHandlerEventArgs args) {
+				throw new NotSupportedException ();
+			};
+			try {
+				VM_SetProtocolVersion (MAJOR_VERSION, MINOR_VERSION);
+			} catch (NotSupportedException) {
+			}
+			ErrorHandler = OrigErrorHandler;
+		}
+
+		internal byte[] ReadPacket () {
+			// FIXME: Throw ClosedConnectionException () if the connection is closed
+			// FIXME: Throw ClosedConnectionException () if another thread closes the connection
+			// FIXME: Locking
+			byte[] header = new byte [HEADER_LENGTH];
+
+			int len = Receive (header, 0, header.Length);
+			if (len == 0)
+				return new byte [0];
+			if (len != HEADER_LENGTH) {
+				// FIXME:
+				throw new IOException ("Packet of length " + len + " is read.");
+			}
+
+			int packetLength = GetPacketLength (header);
+			if (packetLength < 11)
+				throw new IOException ("Invalid packet length.");
+
+			if (packetLength == 11) {
+				return header;
+			} else {
+				byte[] buf = new byte [packetLength];
+				for (int i = 0; i < header.Length; ++i)
+					buf [i] = header [i];
+				len = Receive (buf, header.Length, packetLength - header.Length);
+				if (len != packetLength - header.Length)
+					throw new IOException ();
+				return buf;
+			}
+		}
+
+		internal void WritePacket (byte[] packet) {
+			// FIXME: Throw ClosedConnectionException () if the connection is closed
+			// FIXME: Throw ClosedConnectionException () if another thread closes the connection
+			// FIXME: Locking
+			TransportSend (packet, 0, packet.Length);
+		}
+
+		internal void Close () {
+			closed = true;
+		}
+
+		internal bool IsClosed {
+			get {
+				return closed;
+			}
+		}
+
+		bool disconnected;
+
+		void receiver_thread_main () {
+			while (!closed) {
+				try {
+					bool res = ReceivePacket ();
+					if (!res)
+						break;
+				} catch (Exception ex) {
+					if (!closed) {
+						Console.WriteLine (ex);
+					}
+					break;
+				}
+			}
+
+			lock (reply_packets_monitor) {
+				disconnected = true;
+				Monitor.PulseAll (reply_packets_monitor);
+				TransportClose ();
+			}
+			EventHandler.VMDisconnect (0, 0, null);
+		}
+
+		bool ReceivePacket () {
+				byte[] packet = ReadPacket ();
+
+				if (packet.Length == 0) {
+					return false;
+				}
+
+				if (IsReplyPacket (packet)) {
+					int id = GetPacketId (packet);
+					ReplyCallback cb = null;
+					lock (reply_packets_monitor) {
+						reply_cbs.TryGetValue (id, out cb);
+						if (cb == null) {
+							reply_packets [id] = packet;
+							Monitor.PulseAll (reply_packets_monitor);
+						} else {
+							int c = reply_cb_counts [id];
+							c --;
+							if (c == 0) {
+								reply_cbs.Remove (id);
+								reply_cb_counts.Remove (id);
+							}
+						}
+					}
+
+					if (cb != null)
+						cb.Invoke (id, packet);
+				} else {
+					PacketReader r = new PacketReader (packet);
+
+					if (r.CommandSet == CommandSet.EVENT && r.Command == (int)CmdEvent.COMPOSITE) {
+						int spolicy = r.ReadByte ();
+						int nevents = r.ReadInt ();
+
+						SuspendPolicy suspend_policy = decode_suspend_policy (spolicy);
+
+						EventInfo[] events = new EventInfo [nevents];
+
+						for (int i = 0; i < nevents; ++i) {
+							EventKind kind = (EventKind)r.ReadByte ();
+							int req_id = r.ReadInt ();
+
+							EventType etype = (EventType)kind;
+
+							if (kind == EventKind.VM_START) {
+								long thread_id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id };
+								//EventHandler.VMStart (req_id, thread_id, null);
+							} else if (kind == EventKind.VM_DEATH) {
+								//EventHandler.VMDeath (req_id, 0, null);
+								events [i] = new EventInfo (etype, req_id) { };
+							} else if (kind == EventKind.THREAD_START) {
+								long thread_id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
+								//EventHandler.ThreadStart (req_id, thread_id, thread_id);
+							} else if (kind == EventKind.THREAD_DEATH) {
+								long thread_id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
+								//EventHandler.ThreadDeath (req_id, thread_id, thread_id);
+							} else if (kind == EventKind.ASSEMBLY_LOAD) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.AssemblyLoad (req_id, thread_id, id);
+							} else if (kind == EventKind.ASSEMBLY_UNLOAD) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.AssemblyUnload (req_id, thread_id, id);
+							} else if (kind == EventKind.TYPE_LOAD) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.TypeLoad (req_id, thread_id, id);
+							} else if (kind == EventKind.METHOD_ENTRY) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.MethodEntry (req_id, thread_id, id);
+							} else if (kind == EventKind.METHOD_EXIT) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.MethodExit (req_id, thread_id, id);
+							} else if (kind == EventKind.BREAKPOINT) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								long loc = r.ReadLong ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
+								//EventHandler.Breakpoint (req_id, thread_id, id, loc);
+							} else if (kind == EventKind.STEP) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								long loc = r.ReadLong ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
+								//EventHandler.Step (req_id, thread_id, id, loc);
+							} else if (kind == EventKind.EXCEPTION) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								long loc = 0; // FIXME
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
+								//EventHandler.Exception (req_id, thread_id, id, loc);
+							} else if (kind == EventKind.APPDOMAIN_CREATE) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.AppDomainCreate (req_id, thread_id, id);
+							} else if (kind == EventKind.APPDOMAIN_UNLOAD) {
+								long thread_id = r.ReadId ();
+								long id = r.ReadId ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
+								//EventHandler.AppDomainUnload (req_id, thread_id, id);
+							} else if (kind == EventKind.USER_BREAK) {
+								long thread_id = r.ReadId ();
+								long id = 0;
+								long loc = 0;
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
+								//EventHandler.Exception (req_id, thread_id, id, loc);
+							} else if (kind == EventKind.USER_LOG) {
+								long thread_id = r.ReadId ();
+								int level = r.ReadInt ();
+								string category = r.ReadString ();
+								string message = r.ReadString ();
+								events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Level = level, Category = category, Message = message };
+								//EventHandler.Exception (req_id, thread_id, id, loc);
+							} else if (kind == EventKind.KEEPALIVE) {
+								events [i] = new EventInfo (etype, req_id) { };
+							} else {
+								throw new NotImplementedException ("Unknown event kind: " + kind);
+							}
+						}
+
+						EventHandler.Events (suspend_policy, events);
+					}
+				}
+
+				return true;
+		}
+
+		internal IEventHandler EventHandler {
+			get; set;
+		}
+
+		static String CommandString (CommandSet command_set, int command)
+		{
+			string cmd;
+			switch (command_set) {
+			case CommandSet.VM:
+				cmd = ((CmdVM)command).ToString ();
+				break;
+			case CommandSet.OBJECT_REF:
+				cmd = ((CmdObjectRef)command).ToString ();
+				break;
+			case CommandSet.STRING_REF:
+				cmd = ((CmdStringRef)command).ToString ();
+				break;
+			case CommandSet.THREAD:
+				cmd = ((CmdThread)command).ToString ();
+				break;
+			case CommandSet.ARRAY_REF:
+				cmd = ((CmdArrayRef)command).ToString ();
+				break;
+			case CommandSet.EVENT_REQUEST:
+				cmd = ((CmdEventRequest)command).ToString ();
+				break;
+			case CommandSet.STACK_FRAME:
+				cmd = ((CmdStackFrame)command).ToString ();
+				break;
+			case CommandSet.APPDOMAIN:
+				cmd = ((CmdAppDomain)command).ToString ();
+				break;
+			case CommandSet.ASSEMBLY:
+				cmd = ((CmdAssembly)command).ToString ();
+				break;
+			case CommandSet.METHOD:
+				cmd = ((CmdMethod)command).ToString ();
+				break;
+			case CommandSet.TYPE:
+				cmd = ((CmdType)command).ToString ();
+				break;
+			case CommandSet.MODULE:
+				cmd = ((CmdModule)command).ToString ();
+				break;
+			case CommandSet.EVENT:
+				cmd = ((CmdEvent)command).ToString ();
+				break;
+			default:
+				cmd = command.ToString ();
+				break;
+			}
+			return string.Format ("[{0} {1}]", command_set, cmd);
+		}
+
+		long total_protocol_ticks;
+
+		void LogPacket (int packet_id, byte[] encoded_packet, byte[] reply_packet, CommandSet command_set, int command, Stopwatch watch) {
+			watch.Stop ();
+			total_protocol_ticks += watch.ElapsedTicks;
+			var ts = TimeSpan.FromTicks (total_protocol_ticks);
+			string msg = string.Format ("Packet: {0} sent: {1} received: {2} ms: {3} total ms: {4} {5}",
+			   packet_id, encoded_packet.Length, reply_packet.Length, watch.ElapsedMilliseconds,
+			   (ts.Seconds * 1000) + ts.Milliseconds,
+			   CommandString (command_set, command));
+
+			LoggingStream.WriteLine (msg);
+			LoggingStream.Flush ();
+		}
+
+		/* Send a request and call cb when a result is received */
+		int Send (CommandSet command_set, int command, PacketWriter packet, Action<PacketReader> cb, int count) {
+			int id = IdGenerator;
+
+			Stopwatch watch = null;
+			if (EnableConnectionLogging)
+				watch = Stopwatch.StartNew ();
+
+			byte[] encoded_packet;
+			if (packet == null)
+				encoded_packet = EncodePacket (id, (int)command_set, command, null, 0);
+			else
+				encoded_packet = EncodePacket (id, (int)command_set, command, packet.Data, packet.Offset);
+
+			lock (reply_packets_monitor) {
+				reply_cbs [id] = delegate (int packet_id, byte[] p) {
+					if (EnableConnectionLogging)
+						LogPacket (packet_id, encoded_packet, p, command_set, command, watch);
+					/* Run the callback on a tp thread to avoid blocking the receive thread */
+					PacketReader r = new PacketReader (p);
+					cb.BeginInvoke (r, null, null);
+				};
+				reply_cb_counts [id] = count;
+			}
+
+			WritePacket (encoded_packet);
+
+			return id;
+		}
+
+		PacketReader SendReceive (CommandSet command_set, int command, PacketWriter packet) {
+			int id = IdGenerator;
+			Stopwatch watch = null;
+
+			if (disconnected)
+				throw new VMDisconnectedException ();
+
+			if (EnableConnectionLogging)
+				watch = Stopwatch.StartNew ();
+
+			byte[] encoded_packet;
+
+			if (packet == null)
+				encoded_packet = EncodePacket (id, (int)command_set, command, null, 0);
+			else
+				encoded_packet = EncodePacket (id, (int)command_set, command, packet.Data, packet.Offset);
+
+			WritePacket (encoded_packet);
+
+			int packetId = id;
+
+			/* Wait for the reply packet */
+			while (true) {
+				lock (reply_packets_monitor) {
+					if (reply_packets.ContainsKey (packetId)) {
+						byte[] reply = reply_packets [packetId];
+						reply_packets.Remove (packetId);
+						PacketReader r = new PacketReader (reply);
+
+						if (EnableConnectionLogging)
+							LogPacket (packetId, encoded_packet, reply, command_set, command, watch);
+						if (r.ErrorCode != 0) {
+							if (ErrorHandler != null)
+								ErrorHandler (this, new ErrorHandlerEventArgs () { ErrorCode = (ErrorCode)r.ErrorCode });
+							throw new NotImplementedException ("No error handler set.");
+						} else {
+							return r;
+						}
+					} else {
+						if (disconnected)
+							throw new VMDisconnectedException ();
+						Monitor.Wait (reply_packets_monitor);
+					}
+				}
+			}
+		}
+
+		PacketReader SendReceive (CommandSet command_set, int command) {
+			return SendReceive (command_set, command, null);
+		}
+
+		int packet_id_generator;
+
+		int IdGenerator {
+			get {
+				return Interlocked.Increment (ref packet_id_generator);
+			}
+		}
+
+		CattrInfo[] ReadCattrs (PacketReader r) {
+			CattrInfo[] res = new CattrInfo [r.ReadInt ()];
+			for (int i = 0; i < res.Length; ++i) {
+				CattrInfo info = new CattrInfo ();
+				info.ctor_id = r.ReadId ();
+				info.ctor_args = new ValueImpl [r.ReadInt ()];
+				for (int j = 0; j < info.ctor_args.Length; ++j) {
+					info.ctor_args [j] = r.ReadValue ();
+				}
+				info.named_args = new CattrNamedArgInfo [r.ReadInt ()];
+				for (int j = 0; j < info.named_args.Length; ++j) {
+					CattrNamedArgInfo arg = new CattrNamedArgInfo ();
+					int arg_type = r.ReadByte ();
+					arg.is_property = arg_type == 0x54;
+					arg.id = r.ReadId ();
+					arg.value = r.ReadValue ();
+					info.named_args [j] = arg;
+				}
+				res [i] = info;
+			}
+			return res;
+		}
+
+		static ElementType TypeCodeToElementType (TypeCode c) {
+			switch (c) {
+			case TypeCode.Boolean:
+				return ElementType.Boolean;
+			case TypeCode.Char:
+				return ElementType.Char;
+			case TypeCode.SByte:
+				return ElementType.I1;
+			case TypeCode.Byte:
+				return ElementType.U1;
+			case TypeCode.Int16:
+				return ElementType.I2;
+			case TypeCode.UInt16:
+				return ElementType.U2;
+			case TypeCode.Int32:
+				return ElementType.I4;
+			case TypeCode.UInt32:
+				return ElementType.U4;
+			case TypeCode.Int64:
+				return ElementType.I8;
+			case TypeCode.UInt64:
+				return ElementType.U8;
+			case TypeCode.Single:
+				return ElementType.R4;
+			case TypeCode.Double:
+				return ElementType.R8;
+			default:
+				throw new NotImplementedException ();
+			}
+		}
+
+		/*
+		 * Implementation of debugger commands
+		 */
+
+		internal VersionInfo VM_GetVersion () {
+			var res = SendReceive (CommandSet.VM, (int)CmdVM.VERSION, null);
+			VersionInfo info = new VersionInfo ();
+			info.VMVersion = res.ReadString ();
+			info.MajorVersion = res.ReadInt ();
+			info.MinorVersion = res.ReadInt ();
+			return info;
+		}
+
+		internal void VM_SetProtocolVersion (int major, int minor) {
+			SendReceive (CommandSet.VM, (int)CmdVM.SET_PROTOCOL_VERSION, new PacketWriter ().WriteInt (major).WriteInt (minor));
+		}
+
+		internal long[] VM_GetThreads () {
+			var res = SendReceive (CommandSet.VM, (int)CmdVM.ALL_THREADS, null);
+			int len = res.ReadInt ();
+			long[] arr = new long [len];
+			for (int i = 0; i < len; ++i)
+				arr [i] = res.ReadId ();
+			return arr;
+		}
+
+		internal void VM_Suspend () {
+			SendReceive (CommandSet.VM, (int)CmdVM.SUSPEND);
+		}
+
+		internal void VM_Resume () {
+			SendReceive (CommandSet.VM, (int)CmdVM.RESUME);
+		}
+
+		internal void VM_Exit (int exitCode) {
+			SendReceive (CommandSet.VM, (int)CmdVM.EXIT, new PacketWriter ().WriteInt (exitCode));
+		}
+
+		internal void VM_Dispose () {
+			SendReceive (CommandSet.VM, (int)CmdVM.DISPOSE);
+		}
+
+		internal ValueImpl VM_InvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, out ValueImpl exc) {
+			exc = null;
+			PacketReader r = SendReceive (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments));
+			if (r.ReadByte () == 0) {
+				exc = r.ReadValue ();
+				return null;
+			} else {
+				return r.ReadValue ();
+			}
+		}
+
+		internal delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ErrorCode error, object state);
+
+		internal int VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
+			return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments), delegate (PacketReader r) {
+					ValueImpl v, exc;
+
+					if (r.ErrorCode != 0) {
+						callback (null, null, (ErrorCode)r.ErrorCode, state);
+					} else {
+						if (r.ReadByte () == 0) {
+							exc = r.ReadValue ();
+							v = null;
+						} else {
+							v = r.ReadValue ();
+							exc = null;
+						}
+
+						callback (v, exc, 0, state);
+					}
+				}, 1);
+		}
+
+		internal int VM_BeginInvokeMethods (long thread, long[] methods, ValueImpl this_arg, List<ValueImpl[]> arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
+			// FIXME: Merge this with INVOKE_METHOD
+			var w = new PacketWriter ();
+			w.WriteId (thread);
+			w.WriteInt ((int)flags);
+			w.WriteInt (methods.Length);
+			for (int i = 0; i < methods.Length; ++i) {
+				w.WriteId (methods [i]);
+				w.WriteValue (this_arg);
+				w.WriteInt (arguments [i].Length);
+				w.WriteValues (arguments [i]);
+			}
+			return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHODS, w, delegate (PacketReader r) {
+					ValueImpl v, exc;
+
+					if (r.ErrorCode != 0) {
+						callback (null, null, (ErrorCode)r.ErrorCode, state);
+					} else {
+						if (r.ReadByte () == 0) {
+							exc = r.ReadValue ();
+							v = null;
+						} else {
+							v = r.ReadValue ();
+							exc = null;
+						}
+
+						callback (v, exc, 0, state);
+					}
+				}, methods.Length);
+		}
+
+		internal void VM_AbortInvoke (long thread, int id)
+		{
+			SendReceive (CommandSet.VM, (int)CmdVM.ABORT_INVOKE, new PacketWriter ().WriteId (thread).WriteInt (id));
+		}
+
+		internal void SetSocketTimeouts (int send_timeout, int receive_timeout, int keepalive_interval)
+		{
+			TransportSetTimeouts (send_timeout, receive_timeout);
+			SendReceive (CommandSet.VM, (int)CmdVM.SET_KEEPALIVE, new PacketWriter ().WriteId (keepalive_interval));
+		}
+
+		internal long[] VM_GetTypesForSourceFile (string fname, bool ignoreCase) {
+			var res = SendReceive (CommandSet.VM, (int)CmdVM.GET_TYPES_FOR_SOURCE_FILE, new PacketWriter ().WriteString (fname).WriteBool (ignoreCase));
+			int count = res.ReadInt ();
+			long[] types = new long [count];
+			for (int i = 0; i < count; ++i)
+				types [i] = res.ReadId ();
+			return types;
+		}
+
+		internal long[] VM_GetTypes (string name, bool ignoreCase) {
+			var res = SendReceive (CommandSet.VM, (int)CmdVM.GET_TYPES, new PacketWriter ().WriteString (name).WriteBool (ignoreCase));
+			int count = res.ReadInt ();
+			long[] types = new long [count];
+			for (int i = 0; i < count; ++i)
+				types [i] = res.ReadId ();
+			return types;
+		}
+
+		/*
+		 * DOMAIN
+		 */
+
+		internal long RootDomain {
+			get {
+				return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ROOT_DOMAIN, null).ReadId ();
+			}
+		}
+
+		internal string Domain_GetName (long id) {
+			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_FRIENDLY_NAME, new PacketWriter ().WriteId (id)).ReadString ();
+		}
+
+		internal long[] Domain_GetAssemblies (long id) {
+			var res = SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ASSEMBLIES, new PacketWriter ().WriteId (id));
+			int count = res.ReadInt ();
+			long[] assemblies = new long [count];
+			for (int i = 0; i < count; ++i)
+				assemblies [i] = res.ReadId ();
+			return assemblies;
+		}
+
+		internal long Domain_GetEntryAssembly (long id) {
+			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ENTRY_ASSEMBLY, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal long Domain_GetCorlib (long id) {
+			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_CORLIB, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal long Domain_CreateString (long id, string s) {
+			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.CREATE_STRING, new PacketWriter ().WriteId (id).WriteString (s)).ReadId ();
+		}
+
+		internal long Domain_CreateBoxedValue (long id, long type_id, ValueImpl v) {
+			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.CREATE_BOXED_VALUE, new PacketWriter ().WriteId (id).WriteId (type_id).WriteValue (v)).ReadId ();
+		}
+
+		/*
+		 * METHOD
+		 */
+
+		internal string Method_GetName (long id) {
+			return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
+		}
+
+		internal long Method_GetDeclaringType (long id) {
+			return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_DECLARING_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal DebugInfo Method_GetDebugInfo (long id) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_DEBUG_INFO, new PacketWriter ().WriteId (id));
+
+			DebugInfo info = new DebugInfo ();
+			info.max_il_offset = res.ReadInt ();
+
+			SourceInfo[] sources = null;
+			if (Version.AtLeast (2, 13)) {
+				int n = res.ReadInt ();
+				sources = new SourceInfo [n];
+				for (int i = 0; i < n; ++i) {
+					sources [i].source_file = res.ReadString ();
+					if (Version.AtLeast (2, 14)) {
+						sources [i].hash = new byte [16];
+						for (int j = 0; j < 16; ++j)
+							sources [i].hash [j] = (byte)res.ReadByte ();
+					}
+				}
+			} else {
+				sources = new SourceInfo [1];
+				sources [0].source_file = res.ReadString ();
+			}
+
+			int n_il_offsets = res.ReadInt ();
+			info.il_offsets = new int [n_il_offsets];
+			info.line_numbers = new int [n_il_offsets];
+			info.source_files = new SourceInfo [n_il_offsets];
+			info.column_numbers = new int [n_il_offsets];
+			for (int i = 0; i < n_il_offsets; ++i) {
+				info.il_offsets [i] = res.ReadInt ();
+				info.line_numbers [i] = res.ReadInt ();
+				if (Version.AtLeast (2, 12)) {
+					int idx = res.ReadInt ();
+					info.source_files [i] = idx >= 0 ? sources [idx] : default (SourceInfo);
+				} else {
+					info.source_files [i] = sources [0];
+				}
+				if (Version.AtLeast (2, 19))
+					info.column_numbers [i] = res.ReadInt ();
+				else
+					info.column_numbers [i] = 0;
+			}
+
+			return info;
+		}
+
+		internal ParamInfo Method_GetParamInfo (long id) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_PARAM_INFO, new PacketWriter ().WriteId (id));
+
+			ParamInfo info = new ParamInfo ();
+			info.call_conv = res.ReadInt ();
+			info.param_count = res.ReadInt ();
+			info.generic_param_count = res.ReadInt ();
+			info.ret_type = res.ReadId ();
+			info.param_types = new long [info.param_count];
+			for (int i = 0; i < info.param_count; ++i)
+				info.param_types [i] = res.ReadId ();
+			info.param_names = new string [info.param_count];			
+			for (int i = 0; i < info.param_count; ++i)
+				info.param_names [i] = res.ReadString ();
+
+			return info;
+		}
+
+		internal LocalsInfo Method_GetLocalsInfo (long id) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_LOCALS_INFO, new PacketWriter ().WriteId (id));
+
+			LocalsInfo info = new LocalsInfo ();
+			int nlocals = res.ReadInt ();
+			info.types = new long [nlocals];
+			for (int i = 0; i < nlocals; ++i)
+				info.types [i] = res.ReadId ();
+			info.names = new string [nlocals];
+			for (int i = 0; i < nlocals; ++i)
+				info.names [i] = res.ReadString ();
+			info.live_range_start = new int [nlocals];
+			info.live_range_end = new int [nlocals];
+			for (int i = 0; i < nlocals; ++i) {
+				info.live_range_start [i] = res.ReadInt ();
+				info.live_range_end [i] = res.ReadInt ();
+			}
+
+			return info;
+		}
+
+		internal MethodInfo Method_GetInfo (long id) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_INFO, new PacketWriter ().WriteId (id));
+
+			MethodInfo info = new MethodInfo ();
+			info.attributes = res.ReadInt ();
+			info.iattributes = res.ReadInt ();
+			info.token = res.ReadInt ();
+			if (Version.AtLeast (2, 12)) {
+				int attrs = res.ReadByte ();
+				if ((attrs & (1 << 0)) != 0)
+					info.is_gmd = true;
+				if ((attrs & (1 << 1)) != 0)
+					info.is_generic_method = true;
+				info.gmd = res.ReadId ();
+				if (Version.AtLeast (2, 15)) {
+					if (info.is_generic_method) {
+						int n = res.ReadInt ();
+						info.type_args = res.ReadIds (n);
+					}
+				}
+			}
+			return info;
+		}
+
+		internal MethodBodyInfo Method_GetBody (long id) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_BODY, new PacketWriter ().WriteId (id));
+
+			MethodBodyInfo info = new MethodBodyInfo ();
+			info.il = new byte [res.ReadInt ()];
+			for (int i = 0; i < info.il.Length; ++i)
+				info.il [i] = (byte)res.ReadByte ();
+
+			if (Version.AtLeast (2, 18)) {
+				info.clauses = new ExceptionClauseInfo [res.ReadInt ()];
+
+				for (int i = 0; i < info.clauses.Length; ++i) {
+					var clause = new ExceptionClauseInfo {
+						flags = (ExceptionClauseFlags) res.ReadInt (),
+						try_offset = res.ReadInt (),
+						try_length = res.ReadInt (),
+						handler_offset = res.ReadInt (),
+						handler_length = res.ReadInt (),
+					};
+
+					if (clause.flags == ExceptionClauseFlags.None)
+						clause.catch_type_id = res.ReadId ();
+					else if (clause.flags == ExceptionClauseFlags.Filter)
+						clause.filter_offset = res.ReadInt ();
+
+					info.clauses [i] = clause;
+				}
+			} else
+				info.clauses = new ExceptionClauseInfo [0];
+
+			return info;
+		}
+
+		internal ResolvedToken Method_ResolveToken (long id, int token) {
+			var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.RESOLVE_TOKEN, new PacketWriter ().WriteId (id).WriteInt (token));
+
+			TokenType type = (TokenType)res.ReadByte ();
+			switch (type) {
+			case TokenType.STRING:
+				return new ResolvedToken () { Type = type, Str = res.ReadString () };
+			case TokenType.TYPE:
+			case TokenType.METHOD:
+			case TokenType.FIELD:
+				return new ResolvedToken () { Type = type, Id = res.ReadId () };
+			case TokenType.UNKNOWN:
+				return new ResolvedToken () { Type = type };
+			default:
+				throw new NotImplementedException ();
+			}
+		}
+
+		internal CattrInfo[] Method_GetCustomAttributes (long id, long attr_type_id, bool inherit) {
+			PacketReader r = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_CATTRS, new PacketWriter ().WriteId (id).WriteId (attr_type_id));
+			return ReadCattrs (r);
+		}
+
+		internal long Method_MakeGenericMethod (long id, long[] args) {
+			PacketReader r = SendReceive (CommandSet.METHOD, (int)CmdMethod.MAKE_GENERIC_METHOD, new PacketWriter ().WriteId (id).WriteInt (args.Length).WriteIds (args));
+			return r.ReadId ();
+		}
+
+		/*
+		 * THREAD
+		 */
+
+		internal string Thread_GetName (long id) {
+			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
+		}
+
+		internal FrameInfo[] Thread_GetFrameInfo (long id, int start_frame, int length) {
+			var res = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length));
+			int count = res.ReadInt ();
+
+			var frames = new FrameInfo [count];
+			for (int i = 0; i < count; ++i) {
+				var f = new FrameInfo ();
+				f.id = res.ReadInt ();
+				f.method = res.ReadId ();
+				f.il_offset = res.ReadInt ();
+				f.flags = (StackFrameFlags)res.ReadByte ();
+				frames [i] = f;
+			}
+
+			return frames;
+		}
+
+		internal int Thread_GetState (long id) {
+			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_STATE, new PacketWriter ().WriteId (id)).ReadInt ();
+		}
+
+		internal ThreadInfo Thread_GetInfo (long id) {
+			PacketReader r = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_INFO, new PacketWriter ().WriteId (id));
+
+			ThreadInfo res = new ThreadInfo () { is_thread_pool = r.ReadByte () > 0 ? true : false };
+
+			return res;
+		}
+
+		internal long Thread_GetId (long id) {
+			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_ID, new PacketWriter ().WriteId (id)).ReadLong ();
+		}
+
+		internal long Thread_GetTID (long id) {
+			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_TID, new PacketWriter ().WriteId (id)).ReadLong ();
+		}
+
+		/*
+		 * MODULE
+		 */
+
+		internal ModuleInfo Module_GetInfo (long id) {
+			PacketReader r = SendReceive (CommandSet.MODULE, (int)CmdModule.GET_INFO, new PacketWriter ().WriteId (id));
+			ModuleInfo info = new ModuleInfo { Name = r.ReadString (), ScopeName = r.ReadString (), FQName = r.ReadString (), Guid = r.ReadString (), Assembly = r.ReadId () };
+			return info;
+		}
+
+		/*
+		 * ASSEMBLY
+		 */
+
+		internal string Assembly_GetLocation (long id) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_LOCATION, new PacketWriter ().WriteId (id)).ReadString ();
+		}
+
+		internal long Assembly_GetEntryPoint (long id) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_ENTRY_POINT, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal long Assembly_GetManifestModule (long id) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_MANIFEST_MODULE, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal long Assembly_GetObject (long id) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal long Assembly_GetType (long id, string name, bool ignoreCase) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_TYPE, new PacketWriter ().WriteId (id).WriteString (name).WriteBool (ignoreCase)).ReadId ();
+		}
+
+		internal string Assembly_GetName (long id) {
+			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
+		}
+
+		/*
+		 * TYPE
+		 */
+
+		internal TypeInfo Type_GetInfo (long id) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INFO, new PacketWriter ().WriteId (id));
+			TypeInfo res = new TypeInfo ();
+
+			res.ns = r.ReadString ();
+			res.name = r.ReadString ();
+			res.full_name = r.ReadString ();
+			res.assembly = r.ReadId ();
+			res.module = r.ReadId ();
+			res.base_type = r.ReadId ();
+			res.element_type = r.ReadId ();
+			res.token = r.ReadInt ();
+			res.rank = r.ReadByte ();
+			res.attributes = r.ReadInt ();
+			int b = r.ReadByte ();
+			res.is_byref = (b & 1) != 0;
+			res.is_pointer = (b & 2) != 0;
+			res.is_primitive = (b & 4) != 0;
+			res.is_valuetype = (b & 8) != 0;
+			res.is_enum = (b & 16) != 0;
+			res.is_gtd = (b & 32) != 0;
+			res.is_generic_type = (b & 64) != 0;
+
+			int nested_len = r.ReadInt ();
+			res.nested = new long [nested_len];
+			for (int i = 0; i < nested_len; ++i)
+				res.nested [i] = r.ReadId ();
+
+			if (Version.AtLeast (2, 12))
+				res.gtd = r.ReadId ();
+			if (Version.AtLeast (2, 15) && res.is_generic_type) {
+				int n = r.ReadInt ();
+				res.type_args = r.ReadIds (n);
+			}
+
+			return res;
+		}
+
+		internal long[] Type_GetMethods (long id) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_METHODS, new PacketWriter ().WriteId (id));
+
+			int n = r.ReadInt ();
+			long[] res = new long [n];
+			for (int i = 0; i < n; ++i)
+				res [i] = r.ReadId ();
+			return res;
+		}
+
+		internal long[] Type_GetFields (long id, out string[] names, out long[] types, out int[] attrs) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_FIELDS, new PacketWriter ().WriteId (id));
+
+			int n = r.ReadInt ();
+			long[] res = new long [n];
+			names = new string [n];
+			types = new long [n];
+			attrs = new int [n];
+			for (int i = 0; i < n; ++i) {
+				res [i] = r.ReadId ();
+				names [i] = r.ReadString ();
+				types [i] = r.ReadId ();
+				attrs [i] = r.ReadInt ();
+			}
+			return res;
+		}
+
+		internal PropInfo[] Type_GetProperties (long id) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_PROPERTIES, new PacketWriter ().WriteId (id));
+
+			int n = r.ReadInt ();
+			PropInfo[] res = new PropInfo [n];
+			for (int i = 0; i < n; ++i) {
+				res [i] = new PropInfo ();
+				res [i].id = r.ReadId ();
+				res [i].name = r.ReadString ();
+				res [i].get_method = r.ReadId ();
+				res [i].set_method = r.ReadId ();
+				res [i].attrs = r.ReadInt ();
+			}
+
+			return res;
+		}
+
+		internal long Type_GetObject (long id) {
+			return SendReceive (CommandSet.TYPE, (int)CmdType.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
+		}
+
+		internal ValueImpl[] Type_GetValues (long id, long[] fields, long thread_id) {
+			int len = fields.Length;
+			PacketReader r;
+			if (thread_id != 0)
+				r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES_2, new PacketWriter ().WriteId (id).WriteId (thread_id).WriteInt (len).WriteIds (fields));
+			else
+				r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
+
+			ValueImpl[] res = new ValueImpl [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadValue ();
+			return res;
+		}			
+
+		internal void Type_SetValues (long id, long[] fields, ValueImpl[] values) {
+			SendReceive (CommandSet.TYPE, (int)CmdType.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (fields.Length).WriteIds (fields).WriteValues (values));
+		}
+
+		internal string[] Type_GetSourceFiles (long id, bool return_full_paths) {
+			var r = SendReceive (CommandSet.TYPE, return_full_paths ? (int)CmdType.GET_SOURCE_FILES_2 : (int)CmdType.GET_SOURCE_FILES, new PacketWriter ().WriteId (id));
+			int len = r.ReadInt ();
+			string[] res = new string [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadString ();
+			return res;
+		}
+
+		internal bool Type_IsAssignableFrom (long id, long c_id) {
+			return SendReceive (CommandSet.TYPE, (int)CmdType.IS_ASSIGNABLE_FROM, new PacketWriter ().WriteId (id).WriteId (c_id)).ReadByte () > 0;
+		}
+
+		internal CattrInfo[] Type_GetCustomAttributes (long id, long attr_type_id, bool inherit) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_CATTRS, new PacketWriter ().WriteId (id).WriteId (attr_type_id));
+			return ReadCattrs (r);
+		}
+
+		internal CattrInfo[] Type_GetFieldCustomAttributes (long id, long field_id, long attr_type_id, bool inherit) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_FIELD_CATTRS, new PacketWriter ().WriteId (id).WriteId (field_id).WriteId (attr_type_id));
+			return ReadCattrs (r);
+		}
+
+		internal CattrInfo[] Type_GetPropertyCustomAttributes (long id, long field_id, long attr_type_id, bool inherit) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_PROPERTY_CATTRS, new PacketWriter ().WriteId (id).WriteId (field_id).WriteId (attr_type_id));
+			return ReadCattrs (r);
+		}
+
+		public long[] Type_GetMethodsByNameFlags (long id, string name, int flags, bool ignoreCase) {
+			flags |= ignoreCase ? (int)BindingFlagsExtensions.BINDING_FLAGS_IGNORE_CASE : 0;
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.CMD_TYPE_GET_METHODS_BY_NAME_FLAGS, new PacketWriter ().WriteId (id).WriteString (name).WriteInt (flags));
+			int len = r.ReadInt ();
+			long[] res = new long [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadId ();
+			return res;
+		}
+
+		internal long[] Type_GetInterfaces (long id) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INTERFACES, new PacketWriter ().WriteId (id));
+			int len = r.ReadInt ();
+			return r.ReadIds (len);
+		}
+
+		internal IfaceMapInfo[] Type_GetInterfaceMap (long id, long[] ids) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INTERFACE_MAP, new PacketWriter ().WriteId (id).WriteInt (ids.Length).WriteIds (ids));
+			var res = new IfaceMapInfo [ids.Length];
+			for (int i = 0; i < ids.Length; ++i) {
+				int n = r.ReadInt ();
+
+				res [i].iface_id = ids [i];
+				res [i].iface_methods = r.ReadIds (n);
+				res [i].target_methods = r.ReadIds (n);
+			}
+
+			return res;
+		}
+
+		internal bool Type_IsInitialized (long id) {
+			PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.IS_INITIALIZED, new PacketWriter ().WriteId (id));
+			return r.ReadInt () == 1;
+		}
+
+		/*
+		 * EVENTS
+		 */
+
+		internal int EnableEvent (EventType etype, SuspendPolicy suspend_policy, List<Modifier> mods) {
+			var w = new PacketWriter ().WriteByte ((byte)etype).WriteByte ((byte)suspend_policy);
+			if (mods != null) {
+				if (mods.Count > 255)
+					throw new NotImplementedException ();
+				w.WriteByte ((byte)mods.Count);
+				foreach (Modifier mod in mods) {
+					if (mod is CountModifier) {
+						w.WriteByte ((byte)ModifierKind.COUNT);
+						w.WriteInt ((mod as CountModifier).Count);
+					} else if (mod is LocationModifier) {
+						w.WriteByte ((byte)ModifierKind.LOCATION_ONLY);
+						w.WriteId ((mod as LocationModifier).Method);
+						w.WriteLong ((mod as LocationModifier).Location);
+					} else if (mod is StepModifier) {
+						w.WriteByte ((byte)ModifierKind.STEP);
+						w.WriteId ((mod as StepModifier).Thread);
+						w.WriteInt ((mod as StepModifier).Size);
+						w.WriteInt ((mod as StepModifier).Depth);
+						if (Version.AtLeast (2, 16))
+							w.WriteInt ((mod as StepModifier).Filter);
+					} else if (mod is ThreadModifier) {
+						w.WriteByte ((byte)ModifierKind.THREAD_ONLY);
+						w.WriteId ((mod as ThreadModifier).Thread);
+					} else if (mod is ExceptionModifier) {
+						var em = mod as ExceptionModifier;
+						w.WriteByte ((byte)ModifierKind.EXCEPTION_ONLY);
+						w.WriteId (em.Type);
+						if (Version.MajorVersion > 2 || Version.MinorVersion > 0) {
+							/* This is only supported in protocol version 2.1 */
+							w.WriteBool (em.Caught);
+							w.WriteBool (em.Uncaught);
+						} else if (!em.Caught || !em.Uncaught) {
+							throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
+						}
+						if (Version.MajorVersion > 2 || Version.MinorVersion > 24) {
+							w.WriteBool (em.Subclasses);
+						} else if (!em.Subclasses) {
+							throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
+						}
+					} else if (mod is AssemblyModifier) {
+						w.WriteByte ((byte)ModifierKind.ASSEMBLY_ONLY);
+						var amod = (mod as AssemblyModifier);
+						w.WriteInt (amod.Assemblies.Length);
+						foreach (var id in amod.Assemblies)
+							w.WriteId (id);
+					} else if (mod is SourceFileModifier) {
+						w.WriteByte ((byte)ModifierKind.SOURCE_FILE_ONLY);
+						var smod = (mod as SourceFileModifier);
+						w.WriteInt (smod.SourceFiles.Length);
+						foreach (var s in smod.SourceFiles)
+							w.WriteString (s);
+					} else if (mod is TypeNameModifier) {
+						w.WriteByte ((byte)ModifierKind.TYPE_NAME_ONLY);
+						var tmod = (mod as TypeNameModifier);
+						w.WriteInt (tmod.TypeNames.Length);
+						foreach (var s in tmod.TypeNames)
+							w.WriteString (s);
+					} else {
+						throw new NotImplementedException ();
+					}
+				}
+			} else {
+				w.WriteByte (0);
+			}
+			return SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.SET, w).ReadInt ();
+		}
+
+		internal void ClearEventRequest (EventType etype, int req_id) {
+			SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR, new PacketWriter ().WriteByte ((byte)etype).WriteInt (req_id));
+		}			
+
+		internal void ClearAllBreakpoints () {
+			SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR_ALL_BREAKPOINTS, new PacketWriter ());
+		}
+			
+		/*
+		 * STACK FRAME
+		 */
+		internal ValueImpl StackFrame_GetThis (long thread_id, long id) {
+			PacketReader r = SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.GET_THIS, new PacketWriter ().WriteId (thread_id).WriteId (id));
+			return r.ReadValue ();
+		}
+
+		internal ValueImpl[] StackFrame_GetValues (long thread_id, long id, int[] pos) {
+			/* pos < 0 -> argument at pos (-pos) - 1 */
+			/* pos >= 0 -> local at pos */
+			int len = pos.Length;
+			PacketReader r = SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.GET_VALUES, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteInt (len).WriteInts (pos));
+
+			ValueImpl[] res = new ValueImpl [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadValue ();
+			return res;
+		}
+
+		internal void StackFrame_SetValues (long thread_id, long id, int[] pos, ValueImpl[] values) {
+			/* pos < 0 -> argument at pos (-pos) - 1 */
+			/* pos >= 0 -> local at pos */
+			int len = pos.Length;
+			SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.SET_VALUES, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteInt (len).WriteInts (pos).WriteValues (values));
+		}
+
+		/*
+		 * ARRAYS
+		 */
+		internal int[] Array_GetLength (long id, out int rank, out int[] lower_bounds) {
+			var r = SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.GET_LENGTH, new PacketWriter ().WriteId (id));
+			rank = r.ReadInt ();
+			int[] res = new int [rank];
+			lower_bounds = new int [rank];
+			for (int i = 0; i < rank; ++i) {
+				res [i] = r.ReadInt ();
+				lower_bounds [i] = r.ReadInt ();
+			}
+			return res;
+		}
+
+		internal ValueImpl[] Array_GetValues (long id, int index, int len) {
+			var r = SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (index).WriteInt (len));
+			ValueImpl[] res = new ValueImpl [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadValue ();
+			return res;
+		}
+
+		internal void Array_SetValues (long id, int index, ValueImpl[] values) {
+			SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (index).WriteInt (values.Length).WriteValues (values));
+		}
+
+		/*
+		 * STRINGS
+		 */
+		internal string String_GetValue (long id) {
+			return SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_VALUE, new PacketWriter ().WriteId (id)).ReadString ();
+		}			
+
+		internal int String_GetLength (long id) {
+			return (int)SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_LENGTH, new PacketWriter ().WriteId (id)).ReadLong ();
+		}			
+
+		internal char[] String_GetChars (long id, int index, int length) {
+			var r = SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_CHARS, new PacketWriter ().WriteId (id).WriteLong (index).WriteLong (length));
+			var res = new char [length];
+			for (int i = 0; i < length; ++i)
+				res [i] = (char)r.ReadShort ();
+			return res;
+		}			
+
+		/*
+		 * OBJECTS
+		 */
+		internal long Object_GetType (long id) {
+			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
+		}			
+
+		internal long Object_GetDomain (long id) {
+			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_DOMAIN, new PacketWriter ().WriteId (id)).ReadId ();
+		}			
+
+		internal ValueImpl[] Object_GetValues (long id, long[] fields) {
+			int len = fields.Length;
+			PacketReader r = SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
+
+			ValueImpl[] res = new ValueImpl [len];
+			for (int i = 0; i < len; ++i)
+				res [i] = r.ReadValue ();
+			return res;
+		}
+
+		internal void Object_SetValues (long id, long[] fields, ValueImpl[] values) {
+			SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (fields.Length).WriteIds (fields).WriteValues (values));
+		}
+
+		internal bool Object_IsCollected (long id) {
+			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.IS_COLLECTED, new PacketWriter ().WriteId (id)).ReadInt () == 1;
+		}			
+
+		internal long Object_GetAddress (long id) {
+			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_ADDRESS, new PacketWriter ().WriteId (id)).ReadLong ();
+		}			
+
+		internal ObjectRefInfo Object_GetInfo (long id) {
+			ObjectRefInfo res = new ObjectRefInfo ();
+			PacketReader r = SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_INFO, new PacketWriter ().WriteId (id));
+
+			res.type_id = r.ReadId ();
+			res.domain_id = r.ReadId ();
+			return res;
+		}
+
+		public void ForceDisconnect ()
+		{
+			closed = true;
+			disconnected = true;
+			TransportClose ();
+		}
+	}
+	
+	class TcpConnection : Connection
+	{
+		Socket socket;
+		
+		internal TcpConnection (Socket socket)
+		{
+			this.socket = socket;
+			//socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.NoDelay, 1);
+		}
+		
+		internal EndPoint EndPoint {
+			get {
+				return socket.RemoteEndPoint;
+			}
+		}
+		
+		protected override int TransportSend (byte[] buf, int buf_offset, int len)
+		{
+			return socket.Send (buf, buf_offset, len, SocketFlags.None);
+		}
+		
+		protected override int TransportReceive (byte[] buf, int buf_offset, int len)
+		{
+			return socket.Receive (buf, buf_offset, len, SocketFlags.None);
+		}
+		
+		protected override void TransportSetTimeouts (int send_timeout, int receive_timeout)
+		{
+			socket.SendTimeout = send_timeout;
+			socket.ReceiveTimeout = receive_timeout;
+		}
+		
+		protected override void TransportClose ()
+		{
+			socket.Close ();
+		}
+	}
+
+	/* This is the interface exposed by the debugger towards the debugger agent */
+	interface IEventHandler
+	{
+		void Events (SuspendPolicy suspend_policy, EventInfo[] events);
+
+		void VMDisconnect (int req_id, long thread_id, string vm_uri);
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeDataMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeDataMirror.cs
new file mode 100644
index 0000000..8003473
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeDataMirror.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Reflection;
+using System.Text;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft {
+
+	public sealed class CustomAttributeDataMirror {
+		MethodMirror ctorInfo;
+		IList<CustomAttributeTypedArgumentMirror> ctorArgs;
+		IList<CustomAttributeNamedArgumentMirror> namedArgs;
+
+		internal CustomAttributeDataMirror (MethodMirror ctorInfo, object [] ctorArgs, object [] namedArgs)
+		{
+			this.ctorInfo = ctorInfo;
+			
+			this.ctorArgs = Array.AsReadOnly<CustomAttributeTypedArgumentMirror> 
+				(ctorArgs != null ? UnboxValues<CustomAttributeTypedArgumentMirror> (ctorArgs) : new CustomAttributeTypedArgumentMirror [0]);
+			
+			this.namedArgs = Array.AsReadOnly<CustomAttributeNamedArgumentMirror> 
+				(namedArgs != null ? UnboxValues<CustomAttributeNamedArgumentMirror> (namedArgs) : new CustomAttributeNamedArgumentMirror [0]);
+		}
+
+		[ComVisible (true)]
+		public MethodMirror Constructor {
+			get {
+				return ctorInfo;
+			}
+		}
+
+		[ComVisible (true)]
+		public IList<CustomAttributeTypedArgumentMirror> ConstructorArguments {
+			get {
+				return ctorArgs;
+			}
+		}
+
+		public IList<CustomAttributeNamedArgumentMirror> NamedArguments {
+			get {
+				return namedArgs;
+			}
+		}
+
+		public override string ToString ()
+		{
+			StringBuilder sb = new StringBuilder ();
+
+			sb.Append ("[" + ctorInfo.DeclaringType.FullName + "(");
+			if (ctorArgs != null) {
+				for (int i = 0; i < ctorArgs.Count; i++) {
+					sb.Append (ctorArgs [i].ToString ());
+					if (i + 1 < ctorArgs.Count)
+						sb.Append (", ");
+				}
+			}
+
+			if (namedArgs != null) {
+				if (namedArgs.Count > 0)
+					sb.Append (", ");
+			
+				for (int j = 0; j < namedArgs.Count; j++) {
+					sb.Append (namedArgs [j].ToString ());
+					if (j + 1 < namedArgs.Count)
+						sb.Append (", ");
+				}
+			}
+			sb.AppendFormat (")]");
+
+			return sb.ToString ();
+		}
+
+		static T [] UnboxValues<T> (object [] values)
+		{
+			T [] retval = new T [values.Length];
+			for (int i = 0; i < values.Length; i++)
+				retval [i] = (T) values [i];
+
+			return retval;
+		}
+
+		/* 
+		 * Construct a normal object from the value, so accessing the cattr doesn't 
+		 * require remoting calls.
+		 */
+		static CustomAttributeTypedArgumentMirror CreateArg (VirtualMachine vm, ValueImpl vi) {
+			object val;
+
+			/* Instead of receiving a mirror of the Type object, we receive the id of the type */
+			if (vi.Type == (ElementType)ValueTypeId.VALUE_TYPE_ID_TYPE)
+				val = vm.GetType (vi.Id);
+			else {
+				Value v = vm.DecodeValue (vi);
+				if (v is PrimitiveValue)
+					val = (v as PrimitiveValue).Value;
+				else if (v is StringMirror)
+					val = (v as StringMirror).Value;
+				else
+					// FIXME:
+					val = v;
+			}
+			return new CustomAttributeTypedArgumentMirror (null, val);
+		}
+
+		internal static CustomAttributeDataMirror[] Create (VirtualMachine vm, CattrInfo[] info) {
+			var res = new CustomAttributeDataMirror [info.Length];
+			for (int i = 0; i < info.Length; ++i) {
+				CattrInfo attr = info [i];
+				MethodMirror ctor = vm.GetMethod (attr.ctor_id);
+				var ctor_args = new object [attr.ctor_args.Length];
+				for (int j = 0; j < ctor_args.Length; ++j)
+					ctor_args [j] = CreateArg (vm, attr.ctor_args [j]);
+				var named_args = new object [attr.named_args.Length];
+				for (int j = 0; j < named_args.Length; ++j) {
+					CattrNamedArgInfo arg = attr.named_args [j];
+					CustomAttributeTypedArgumentMirror val;
+
+					val = CreateArg (vm, arg.value);
+
+					TypeMirror t = ctor.DeclaringType;
+					while (named_args [j] == null && t != null) {
+						if (arg.is_property) {
+							foreach (var prop in t.GetProperties ()) {
+								if (prop.Id == arg.id)
+									named_args [j] = new CustomAttributeNamedArgumentMirror (prop, null, val);
+							}
+						} else {
+							foreach (var field in t.GetFields ()) {
+								if (field.Id == arg.id)
+									named_args [j] = new CustomAttributeNamedArgumentMirror (null, field, val);
+							}
+						}
+						t = t.BaseType;
+					}
+					if (named_args [j] == null)
+						throw new NotImplementedException ();
+				}
+				res [i] = new CustomAttributeDataMirror (ctor, ctor_args, named_args);
+			}
+
+			return res;
+		}
+	}
+
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs
new file mode 100644
index 0000000..0f90449
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+namespace Mono.Debugger.Soft {
+
+	public struct CustomAttributeNamedArgumentMirror {
+		CustomAttributeTypedArgumentMirror arg;
+		PropertyInfoMirror prop;
+		FieldInfoMirror field;
+
+		internal CustomAttributeNamedArgumentMirror (PropertyInfoMirror prop, FieldInfoMirror field, CustomAttributeTypedArgumentMirror arg)
+		{
+			this.arg = arg;
+			this.prop = prop;
+			this.field = field;
+		}
+
+		public PropertyInfoMirror Property {
+			get {
+				return prop;
+			}
+		}
+
+		public FieldInfoMirror Field {
+			get {
+				return field;
+			}
+		}
+
+		public CustomAttributeTypedArgumentMirror TypedValue {
+			get {
+				return arg;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs
new file mode 100644
index 0000000..8096d20
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.ObjectModel;
+using System.Reflection;
+
+namespace Mono.Debugger.Soft {
+
+	public struct CustomAttributeTypedArgumentMirror {
+		Type type;
+		object value;
+
+		internal CustomAttributeTypedArgumentMirror (Type type, object value)
+		{
+			this.type = type;
+			this.value = value;
+
+			if (value != null)
+				this.type = value.GetType ();
+			else
+				this.type = typeof (void);
+
+			// MS seems to convert arrays into a ReadOnlyCollection
+			if (value is Array) {
+				Array a = (Array)value;
+
+				Type etype = a.GetType ().GetElementType ();
+				CustomAttributeTypedArgumentMirror[] new_value = new CustomAttributeTypedArgumentMirror [a.GetLength (0)];
+				for (int i = 0; i < new_value.Length; ++i)
+					new_value [i] = new CustomAttributeTypedArgumentMirror (etype, a.GetValue (i));
+				this.value = new ReadOnlyCollection <CustomAttributeTypedArgumentMirror> (new_value);
+			}
+		}
+
+		public Type ArgumentType {
+			get {
+				return type;
+			}
+		}
+
+		public object Value {
+			get {
+				return value;
+			}
+		}
+
+		public override string ToString ()
+		{
+			string val = value != null ? value.ToString () : String.Empty;
+			if (ArgumentType == typeof (string))
+				return "\"" + val + "\"";
+			if (ArgumentType == typeof (Type)) 
+				return "typeof (" + val + ")";
+			if (ArgumentType.IsEnum)
+				return "(" + ArgumentType.Name + ")" + val;
+
+			return val;
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/DataConverter.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/DataConverter.cs
new file mode 100644
index 0000000..d0bf047
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/DataConverter.cs
@@ -0,0 +1,1836 @@
+//
+// Authors:
+//   Miguel de Icaza (miguel at novell.com)
+//
+// See the following url for documentation:
+//     http://www.mono-project.com/Mono_DataConvert
+//
+// Compilation Options:
+//     MONO_DATACONVERTER_PUBLIC:
+//         Makes the class public instead of the default internal.
+//
+//     MONO_DATACONVERTER_STATIC_METHODS:     
+//         Exposes the public static methods.
+//
+// TODO:
+//   Support for "DoubleWordsAreSwapped" for ARM devices
+//
+// Copyright (C) 2006 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.Text;
+
+#pragma warning disable 3021
+
+namespace Mono {
+
+#if MONO_DATACONVERTER_PUBLIC
+	unsafe public abstract class DataConverter {
+#else
+	unsafe internal abstract class DataConverter {
+
+// Disables the warning: CLS compliance checking will not be performed on
+//  `XXXX' because it is not visible from outside this assembly
+#pragma warning disable  3019
+#endif
+		static DataConverter SwapConv = new SwapConverter ();
+		static DataConverter CopyConv = new CopyConverter ();
+
+		public static readonly bool IsLittleEndian = BitConverter.IsLittleEndian;
+			
+		public abstract double GetDouble (byte [] data, int index);
+		public abstract float  GetFloat  (byte [] data, int index);
+		public abstract long   GetInt64  (byte [] data, int index);
+		public abstract int    GetInt32  (byte [] data, int index);
+
+		public abstract short  GetInt16  (byte [] data, int index);
+
+                [CLSCompliant (false)]
+		public abstract uint   GetUInt32 (byte [] data, int index);
+                [CLSCompliant (false)]
+		public abstract ushort GetUInt16 (byte [] data, int index);
+                [CLSCompliant (false)]
+		public abstract ulong  GetUInt64 (byte [] data, int index);
+		
+		public abstract void PutBytes (byte [] dest, int destIdx, double value);
+		public abstract void PutBytes (byte [] dest, int destIdx, float value);
+		public abstract void PutBytes (byte [] dest, int destIdx, int value);
+		public abstract void PutBytes (byte [] dest, int destIdx, long value);
+		public abstract void PutBytes (byte [] dest, int destIdx, short value);
+
+                [CLSCompliant (false)]
+		public abstract void PutBytes (byte [] dest, int destIdx, ushort value);
+                [CLSCompliant (false)]
+		public abstract void PutBytes (byte [] dest, int destIdx, uint value);
+                [CLSCompliant (false)]
+		public abstract void PutBytes (byte [] dest, int destIdx, ulong value);
+
+		public byte[] GetBytes (double value)
+		{
+			byte [] ret = new byte [8];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+		public byte[] GetBytes (float value)
+		{
+			byte [] ret = new byte [4];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+		public byte[] GetBytes (int value)
+		{
+			byte [] ret = new byte [4];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+		public byte[] GetBytes (long value)
+		{
+			byte [] ret = new byte [8];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+		public byte[] GetBytes (short value)
+		{
+			byte [] ret = new byte [2];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+
+                [CLSCompliant (false)]
+		public byte[] GetBytes (ushort value)
+		{
+			byte [] ret = new byte [2];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+                [CLSCompliant (false)]
+		public byte[] GetBytes (uint value)
+		{
+			byte [] ret = new byte [4];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+                [CLSCompliant (false)]
+		public byte[] GetBytes (ulong value)
+		{
+			byte [] ret = new byte [8];
+			PutBytes (ret, 0, value);
+			return ret;
+		}
+		
+		static public DataConverter LittleEndian {
+			get {
+				return BitConverter.IsLittleEndian ? CopyConv : SwapConv;
+			}
+		}
+
+		static public DataConverter BigEndian {
+			get {
+				return BitConverter.IsLittleEndian ? SwapConv : CopyConv;
+			}
+		}
+
+		static public DataConverter Native {
+			get {
+				return CopyConv;
+			}
+		}
+
+		static int Align (int current, int align)
+		{
+			return ((current + align - 1) / align) * align;
+		}
+			
+		class PackContext {
+			// Buffer
+			public byte [] buffer;
+			int next;
+
+			public string description;
+			public int i; // position in the description
+			public DataConverter conv;
+			public int repeat;
+			
+			//
+			// if align == -1, auto align to the size of the byte array
+			// if align == 0, do not do alignment
+			// Any other values aligns to that particular size
+			//
+			public int align;
+
+			public void Add (byte [] group)
+			{
+				//Console.WriteLine ("Adding {0} bytes to {1} (next={2}", group.Length,
+				// buffer == null ? "null" : buffer.Length.ToString (), next);
+				
+				if (buffer == null){
+					buffer = group;
+					next = group.Length;
+					return;
+				}
+				if (align != 0){
+					if (align == -1)
+						next = Align (next, group.Length);
+					else
+						next = Align (next, align);
+					align = 0;
+				}
+
+				if (next + group.Length > buffer.Length){
+					byte [] nb = new byte [System.Math.Max (next, 16) * 2 + group.Length];
+					Array.Copy (buffer, nb, buffer.Length);
+					Array.Copy (group, 0, nb, next, group.Length);
+					next = next + group.Length;
+					buffer = nb;
+				} else {
+					Array.Copy (group, 0, buffer, next, group.Length);
+					next += group.Length;
+				}
+			}
+
+			public byte [] Get ()
+			{
+				if (buffer == null)
+					return new byte [0];
+				
+				if (buffer.Length != next){
+					byte [] b = new byte [next];
+					Array.Copy (buffer, b, next);
+					return b;
+				}
+				return buffer;
+			}
+		}
+
+		//
+		// Format includes:
+		// Control:
+		//   ^    Switch to big endian encoding
+		//   _    Switch to little endian encoding
+		//   %    Switch to host (native) encoding
+		//   !    aligns the next data type to its natural boundary (for strings this is 4).
+		//
+		// Types:
+		//   s    Int16
+		//   S    UInt16
+		//   i    Int32
+		//   I    UInt32
+		//   l    Int64
+		//   L    UInt64
+		//   f    float
+		//   d    double
+		//   b    byte
+                //   c    1-byte signed character
+                //   C    1-byte unsigned character
+		//   z8   string encoded as UTF8 with 1-byte null terminator
+		//   z6   string encoded as UTF16 with 2-byte null terminator
+		//   z7   string encoded as UTF7 with 1-byte null terminator
+		//   zb   string encoded as BigEndianUnicode with 2-byte null terminator
+		//   z3   string encoded as UTF32 with 4-byte null terminator
+		//   z4   string encoded as UTF32 big endian with 4-byte null terminator
+		//   $8   string encoded as UTF8
+		//   $6   string encoded as UTF16
+		//   $7   string encoded as UTF7
+		//   $b   string encoded as BigEndianUnicode
+		//   $3   string encoded as UTF32
+		//   $4   string encoded as UTF-32 big endian encoding
+		//   x    null byte
+		//
+		// Repeats, these are prefixes:
+		//   N    a number between 1 and 9, indicates a repeat count (process N items
+		//        with the following datatype
+		//   [N]  For numbers larger than 9, use brackets, for example [20]
+		//   *    Repeat the next data type until the arguments are exhausted
+		//
+		static public byte [] Pack (string description, params object [] args)
+		{
+			int argn = 0;
+			PackContext b = new PackContext ();
+			b.conv = CopyConv;
+			b.description = description;
+
+			for (b.i = 0; b.i < description.Length; ){
+				object oarg;
+
+				if (argn < args.Length)
+					oarg = args [argn];
+				else {
+					if (b.repeat != 0)
+						break;
+					
+					oarg = null;
+				}
+
+				int save = b.i;
+				
+				if (PackOne (b, oarg)){
+					argn++;
+					if (b.repeat > 0){
+						if (--b.repeat > 0)
+							b.i = save;
+						else
+							b.i++;
+					} else
+						b.i++;
+				} else
+					b.i++;
+			}
+			return b.Get ();
+		}
+
+		static public byte [] PackEnumerable (string description, IEnumerable args)
+		{
+			PackContext b = new PackContext ();
+			b.conv = CopyConv;
+			b.description = description;
+			
+			IEnumerator enumerator = args.GetEnumerator ();
+			bool ok = enumerator.MoveNext ();
+
+			for (b.i = 0; b.i < description.Length; ){
+				object oarg;
+
+				if (ok)
+					oarg = enumerator.Current;
+				else {
+					if (b.repeat != 0)
+						break;
+					oarg = null;
+				}
+						
+				int save = b.i;
+				
+				if (PackOne (b, oarg)){
+					ok = enumerator.MoveNext ();
+					if (b.repeat > 0){
+						if (--b.repeat > 0)
+							b.i = save;
+						else
+							b.i++;
+					} else
+						b.i++;
+				} else
+					b.i++;
+			}
+			return b.Get ();
+		}
+			
+		//
+		// Packs one datum `oarg' into the buffer `b', using the string format
+		// in `description' at position `i'
+		//
+		// Returns: true if we must pick the next object from the list
+		//
+		static bool PackOne (PackContext b, object oarg)
+		{
+			int n;
+			
+			switch (b.description [b.i]){
+			case '^':
+				b.conv = BigEndian;
+				return false;
+			case '_':
+				b.conv = LittleEndian;
+				return false;
+			case '%':
+				b.conv = Native;
+				return false;
+
+			case '!':
+				b.align = -1;
+				return false;
+				
+			case 'x':
+				b.Add (new byte [] { 0 });
+				return false;
+				
+				// Type Conversions
+			case 'i':
+				b.Add (b.conv.GetBytes (Convert.ToInt32 (oarg)));
+				break;
+				
+			case 'I':
+				b.Add (b.conv.GetBytes (Convert.ToUInt32 (oarg)));
+				break;
+				
+			case 's':
+				b.Add (b.conv.GetBytes (Convert.ToInt16 (oarg)));
+				break;
+				
+			case 'S':
+				b.Add (b.conv.GetBytes (Convert.ToUInt16 (oarg)));
+				break;
+				
+			case 'l':
+				b.Add (b.conv.GetBytes (Convert.ToInt64 (oarg)));
+				break;
+				
+			case 'L':
+				b.Add (b.conv.GetBytes (Convert.ToUInt64 (oarg)));
+				break;
+				
+			case 'f':
+				b.Add (b.conv.GetBytes (Convert.ToSingle (oarg)));
+				break;
+				
+			case 'd':
+				b.Add (b.conv.GetBytes (Convert.ToDouble (oarg)));
+				break;
+				
+			case 'b':
+				b.Add (new byte [] { Convert.ToByte (oarg) });
+				break;
+
+			case 'c':
+				b.Add (new byte [] { (byte) (Convert.ToSByte (oarg)) });
+				break;
+
+			case 'C':
+				b.Add (new byte [] { Convert.ToByte (oarg) });
+				break;
+
+				// Repeat acount;
+			case '1': case '2': case '3': case '4': case '5':
+			case '6': case '7': case '8': case '9':
+				b.repeat = ((short) b.description [b.i]) - ((short) '0');
+				return false;
+
+			case '*':
+				b.repeat = Int32.MaxValue;
+				return false;
+				
+			case '[':
+				int count = -1, j;
+				
+				for (j = b.i+1; j < b.description.Length; j++){
+					if (b.description [j] == ']')
+						break;
+					n = ((short) b.description [j]) - ((short) '0');
+					if (n >= 0 && n <= 9){
+						if (count == -1)
+							count = n;
+						else
+							count = count * 10 + n;
+					}
+				}
+				if (count == -1)
+					throw new ArgumentException ("invalid size specification");
+				b.i = j;
+				b.repeat = count;
+				return false;
+				
+			case '$': case 'z':
+				bool add_null = b.description [b.i] == 'z';
+				b.i++;
+				if (b.i >= b.description.Length)
+					throw new ArgumentException ("$ description needs a type specified", "description");
+				char d = b.description [b.i];
+				Encoding e;
+				
+				switch (d){
+				case '8':
+					e = Encoding.UTF8;
+					n = 1;
+					break;
+				case '6':
+					e = Encoding.Unicode;
+					n = 2;
+					break;
+				case '7':
+					e = Encoding.UTF7;
+					n = 1;
+					break;
+				case 'b':
+					e = Encoding.BigEndianUnicode;
+					n = 2;
+					break;
+				case '3':
+					e = Encoding.GetEncoding (12000);
+					n = 4;
+					break;
+				case '4':
+					e = Encoding.GetEncoding (12001);
+					n = 4;
+					break;
+					
+				default:
+					throw new ArgumentException ("Invalid format for $ specifier", "description");
+				}
+				if (b.align == -1)
+					b.align = 4;
+				b.Add (e.GetBytes (Convert.ToString (oarg)));
+				if (add_null)
+					b.Add (new byte [n]);
+				break;
+			default:
+				throw new ArgumentException (String.Format ("invalid format specified `{0}'",
+									    b.description [b.i]));
+			}
+			return true;
+		}
+
+		static bool Prepare (byte [] buffer, ref int idx, int size, ref bool align)
+		{
+			if (align){
+				idx = Align (idx, size);
+				align = false;
+			}
+			if (idx + size > buffer.Length){
+				idx = buffer.Length;
+				return false;
+			}
+			return true;
+		}
+		
+		static public IList Unpack (string description, byte [] buffer, int startIndex)
+		{
+			DataConverter conv = CopyConv;
+			ArrayList result = new ArrayList ();
+			int idx = startIndex;
+			bool align = false;
+			int repeat = 0, n;
+			
+			for (int i = 0; i < description.Length && idx < buffer.Length; ){
+				int save = i;
+				
+				switch (description [i]){
+				case '^':
+					conv = BigEndian;
+					break;
+				case '_':
+					conv = LittleEndian;
+					break;
+				case '%':
+					conv = Native;
+					break;
+				case 'x':
+					idx++;
+					break;
+
+				case '!':
+					align = true;
+					break;
+
+					// Type Conversions
+				case 'i':
+					if (Prepare (buffer, ref idx, 4, ref align)){
+						result.Add (conv.GetInt32 (buffer, idx));
+						idx += 4;
+					} 
+					break;
+				
+				case 'I':
+					if (Prepare (buffer, ref idx, 4, ref align)){
+						result.Add (conv.GetUInt32 (buffer, idx));
+						idx += 4;
+					}
+					break;
+				
+				case 's':
+					if (Prepare (buffer, ref idx, 2, ref align)){
+						result.Add (conv.GetInt16 (buffer, idx));
+						idx += 2;
+					}
+					break;
+				
+				case 'S':
+					if (Prepare (buffer, ref idx, 2, ref align)){
+						result.Add (conv.GetUInt16 (buffer, idx));
+						idx += 2;
+					}
+					break;
+				
+				case 'l':
+					if (Prepare (buffer, ref idx, 8, ref align)){
+						result.Add (conv.GetInt64 (buffer, idx));
+						idx += 8;
+					}
+					break;
+				
+				case 'L':
+					if (Prepare (buffer, ref idx, 8, ref align)){
+						result.Add (conv.GetUInt64 (buffer, idx));
+						idx += 8;
+					}
+					break;
+				
+				case 'f':
+					if (Prepare (buffer, ref idx, 4, ref align)){
+						result.Add (conv.GetDouble (buffer, idx));
+						idx += 4;
+					}
+					break;
+				
+				case 'd':
+					if (Prepare (buffer, ref idx, 8, ref align)){
+						result.Add (conv.GetDouble (buffer, idx));
+						idx += 8;
+					}
+					break;
+				
+				case 'b':
+					if (Prepare (buffer, ref idx, 1, ref align)){
+						result.Add (buffer [idx]);
+						idx++;
+					}
+					break;
+
+				case 'c': case 'C':
+					if (Prepare (buffer, ref idx, 1, ref align)){
+						char c;
+						
+						if (description [i] == 'c')
+							c = ((char) ((sbyte)buffer [idx]));
+						else
+							c = ((char) ((byte)buffer [idx]));
+						
+						result.Add (c);
+						idx++;
+					}
+					break;
+					
+					// Repeat acount;
+				case '1': case '2': case '3': case '4': case '5':
+				case '6': case '7': case '8': case '9':
+					repeat = ((short) description [i]) - ((short) '0');
+					save = i + 1;
+					break;
+
+				case '*':
+					repeat = Int32.MaxValue;
+					break;
+				
+				case '[':
+					int count = -1, j;
+				
+					for (j = i+1; j < description.Length; j++){
+						if (description [j] == ']')
+							break;
+						n = ((short) description [j]) - ((short) '0');
+						if (n >= 0 && n <= 9){
+							if (count == -1)
+								count = n;
+							else
+								count = count * 10 + n;
+						}
+					}
+					if (count == -1)
+						throw new ArgumentException ("invalid size specification");
+					i = j;
+					repeat = count;
+					break;
+				
+				case '$': case 'z':
+					// bool with_null = description [i] == 'z';
+					i++;
+					if (i >= description.Length)
+						throw new ArgumentException ("$ description needs a type specified", "description");
+					char d = description [i];
+					Encoding e;
+					if (align){
+						idx = Align (idx, 4);
+						align = false;
+					}
+					if (idx >= buffer.Length)
+						break;
+				
+					switch (d){
+					case '8':
+						e = Encoding.UTF8;
+						n = 1;
+						break;
+					case '6':
+						e = Encoding.Unicode;
+						n = 2;
+						break;
+					case '7':
+						e = Encoding.UTF7;
+						n = 1;
+						break;
+					case 'b':
+						e = Encoding.BigEndianUnicode;
+						n = 2;
+						break;
+					case '3':
+						e = Encoding.GetEncoding (12000);
+						n = 4;
+						break;
+					case '4':
+						e = Encoding.GetEncoding (12001);
+						n = 4;
+						break;
+					
+					default:
+						throw new ArgumentException ("Invalid format for $ specifier", "description");
+					}
+					int k = idx;
+					switch (n){
+					case 1:
+						for (; k < buffer.Length && buffer [k] != 0; k++)
+							;
+						result.Add (e.GetChars (buffer, idx, k-idx));
+						if (k == buffer.Length)
+							idx = k;
+						else
+							idx = k+1;
+						break;
+						
+					case 2:
+						for (; k < buffer.Length; k++){
+							if (k+1 == buffer.Length){
+								k++;
+								break;
+							}
+							if (buffer [k] == 0 && buffer [k+1] == 0)
+								break;
+						}
+						result.Add (e.GetChars (buffer, idx, k-idx));
+						if (k == buffer.Length)
+							idx = k;
+						else
+							idx = k+2;
+						break;
+						
+					case 4:
+						for (; k < buffer.Length; k++){
+							if (k+3 >= buffer.Length){
+								k = buffer.Length;
+								break;
+							}
+							if (buffer[k]==0 && buffer[k+1] == 0 && buffer[k+2] == 0 && buffer[k+3]== 0)
+								break;
+						}
+						result.Add (e.GetChars (buffer, idx, k-idx));
+						if (k == buffer.Length)
+							idx = k;
+						else
+							idx = k+4;
+						break;
+					}
+					break;
+				default:
+					throw new ArgumentException (String.Format ("invalid format specified `{0}'",
+										    description [i]));
+				}
+
+				if (repeat > 0){
+					if (--repeat > 0)
+						i = save;
+				} else
+					i++;
+			}
+			return result;
+		}
+
+		internal void Check (byte [] dest, int destIdx, int size)
+		{
+			if (dest == null)
+				throw new ArgumentNullException ("dest");
+			if (destIdx < 0 || destIdx > dest.Length - size)
+				throw new ArgumentException ("destIdx");
+		}
+		
+		class CopyConverter : DataConverter {
+			public override double GetDouble (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+				double ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+
+			public override ulong GetUInt64 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				ulong ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+
+			public override long GetInt64 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				long ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override float GetFloat  (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				float ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override int GetInt32  (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				int ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override uint GetUInt32 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				uint ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override short GetInt16 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 2)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				short ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 2; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override ushort GetUInt16 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 2)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				ushort ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 2; i++)
+					b [i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, double value)
+			{
+				Check (dest, destIdx, 8);
+				fixed (byte *target = &dest [destIdx]){
+					long *source = (long *) &value;
+
+					*((long *)target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, float value)
+			{
+				Check (dest, destIdx, 4);
+				fixed (byte *target = &dest [destIdx]){
+					uint *source = (uint *) &value;
+
+					*((uint *)target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, int value)
+			{
+				Check (dest, destIdx, 4);
+				fixed (byte *target = &dest [destIdx]){
+					uint *source = (uint *) &value;
+
+					*((uint *)target) = *source;
+				}
+			}
+
+			public override void PutBytes (byte [] dest, int destIdx, uint value)
+			{
+				Check (dest, destIdx, 4);
+				fixed (byte *target = &dest [destIdx]){
+					uint *source = (uint *) &value;
+
+					*((uint *)target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, long value)
+			{
+				Check (dest, destIdx, 8);
+				fixed (byte *target = &dest [destIdx]){
+					long *source = (long *) &value;
+
+					*((long*)target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, ulong value)
+			{
+				Check (dest, destIdx, 8);
+				fixed (byte *target = &dest [destIdx]){
+					ulong *source = (ulong *) &value;
+
+					*((ulong *) target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, short value)
+			{
+				Check (dest, destIdx, 2);
+				fixed (byte *target = &dest [destIdx]){
+					ushort *source = (ushort *) &value;
+
+					*((ushort *)target) = *source;
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, ushort value)
+			{
+				Check (dest, destIdx, 2);
+				fixed (byte *target = &dest [destIdx]){
+					ushort *source = (ushort *) &value;
+
+					*((ushort *)target) = *source;
+				}
+			}
+		}
+
+		class SwapConverter : DataConverter {
+			public override double GetDouble (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				double ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [7-i] = data [index+i];
+
+				return ret;
+			}
+
+			public override ulong GetUInt64 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				ulong ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [7-i] = data [index+i];
+
+				return ret;
+			}
+
+			public override long GetInt64 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 8)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				long ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 8; i++)
+					b [7-i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override float GetFloat  (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				float ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [3-i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override int GetInt32  (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				int ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [3-i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override uint GetUInt32 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 4)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				uint ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 4; i++)
+					b [3-i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override short GetInt16 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 2)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				short ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 2; i++)
+					b [1-i] = data [index+i];
+
+				return ret;
+			}
+			
+			public override ushort GetUInt16 (byte [] data, int index)
+			{
+				if (data == null)
+					throw new ArgumentNullException ("data");
+				if (data.Length - index < 2)
+					throw new ArgumentException ("index");
+				if (index < 0)
+					throw new ArgumentException ("index");
+
+				ushort ret;
+				byte *b = (byte *)&ret;
+
+				for (int i = 0; i < 2; i++)
+					b [1-i] = data [index+i];
+
+				return ret;
+			}
+
+			public override void PutBytes (byte [] dest, int destIdx, double value)
+			{
+				Check (dest, destIdx, 8);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 8; i++)
+						target [i] = source [7-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, float value)
+			{
+				Check (dest, destIdx, 4);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 4; i++)
+						target [i] = source [3-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, int value)
+			{
+				Check (dest, destIdx, 4);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 4; i++)
+						target [i] = source [3-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, uint value)
+			{
+				Check (dest, destIdx, 4);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 4; i++)
+						target [i] = source [3-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, long value)
+			{
+				Check (dest, destIdx, 8);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 8; i++)
+						target [i] = source [7-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, ulong value)
+			{
+				Check (dest, destIdx, 8);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 4; i++)
+						target [i] = source [7-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, short value)
+			{
+				Check (dest, destIdx, 2);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 2; i++)
+						target [i] = source [1-i];
+				}
+			}
+			
+			public override void PutBytes (byte [] dest, int destIdx, ushort value)
+			{
+				Check (dest, destIdx, 2);
+
+				fixed (byte *target = &dest [destIdx]){
+					byte *source = (byte *) &value;
+
+					for (int i = 0; i < 2; i++)
+						target [i] = source [1-i];
+				}
+			}
+		}
+		
+#if MONO_DATACONVERTER_STATIC_METHODS
+		static unsafe void PutBytesLE (byte *dest, byte *src, int count)
+		{
+			int i = 0;
+			
+			if (BitConverter.IsLittleEndian){
+				for (; i < count; i++)
+					*dest++ = *src++;
+			} else {
+				dest += count;
+				for (; i < count; i++)
+					*(--dest) = *src++;
+			}
+		}
+
+		static unsafe void PutBytesBE (byte *dest, byte *src, int count)
+		{
+			int i = 0;
+			
+			if (BitConverter.IsLittleEndian){
+				dest += count;
+				for (; i < count; i++)
+					*(--dest) = *src++;
+			} else {
+				for (; i < count; i++)
+					*dest++ = *src++;
+			}
+		}
+
+		static unsafe void PutBytesNative (byte *dest, byte *src, int count)
+		{
+			int i = 0;
+			
+			for (; i < count; i++)
+				dest [i-count] = *src++;
+		}
+		
+		static public unsafe double DoubleFromLE (byte[] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			double ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe float FloatFromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			float ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe long Int64FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			long ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+		
+		static public unsafe ulong UInt64FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ulong ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe int Int32FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			int ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+		
+		static public unsafe uint UInt32FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			uint ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe short Int16FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+
+			short ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+		
+		static public unsafe ushort UInt16FromLE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ushort ret;
+			fixed (byte *src = &data[index]){
+				PutBytesLE ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+
+		static public unsafe double DoubleFromBE (byte[] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			double ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe float FloatFromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			float ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe long Int64FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			long ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+		
+		static public unsafe ulong UInt64FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ulong ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe int Int32FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			int ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+		
+		static public unsafe uint UInt32FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			uint ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe short Int16FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+
+			short ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+		
+		static public unsafe ushort UInt16FromBE (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ushort ret;
+			fixed (byte *src = &data[index]){
+				PutBytesBE ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+
+		static public unsafe double DoubleFromNative (byte[] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			double ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe float FloatFromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			float ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe long Int64FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			long ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+		
+		static public unsafe ulong UInt64FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 8)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ulong ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 8);
+			}
+			return ret;
+		}
+
+		static public unsafe int Int32FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			int ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+		
+		static public unsafe uint UInt32FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 4)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			uint ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 4);
+			}
+			return ret;
+		}
+
+		static public unsafe short Int16FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+
+			short ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+		
+		static public unsafe ushort UInt16FromNative (byte [] data, int index)
+		{
+			if (data == null)
+				throw new ArgumentNullException ("data");
+			if (data.Length - index < 2)
+				throw new ArgumentException ("index");
+			if (index < 0)
+				throw new ArgumentException ("index");
+			
+			ushort ret;
+			fixed (byte *src = &data[index]){
+				PutBytesNative ((byte *) &ret, src, 2);
+			}
+			return ret;
+		}
+
+                unsafe static byte[] GetBytesPtr (byte *ptr, int count)
+                {
+                        byte [] ret = new byte [count];
+
+                        for (int i = 0; i < count; i++) {
+                                ret [i] = ptr [i];
+                        }
+
+                        return ret;
+                }
+
+                unsafe static byte[] GetBytesSwap (bool swap, byte *ptr, int count)
+                {
+                        byte [] ret = new byte [count];
+
+			if (swap){
+				int t = count-1;
+				for (int i = 0; i < count; i++) {
+					ret [t-i] = ptr [i];
+				}
+			} else {
+				for (int i = 0; i < count; i++) {
+					ret [i] = ptr [i];
+				}
+			}
+                        return ret;
+                }
+		
+                unsafe public static byte[] GetBytesNative (bool value)
+                {
+                        return GetBytesPtr ((byte *) &value, 1);
+                }
+
+                unsafe public static byte[] GetBytesNative (char value)
+                {
+                        return GetBytesPtr ((byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesNative (short value)
+                {
+                        return GetBytesPtr ((byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesNative (int value)
+                {
+                        return GetBytesPtr ((byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesNative (long value)
+                {
+                        return GetBytesPtr ((byte *) &value, 8);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesNative (ushort value)
+                {
+                        return GetBytesPtr ((byte *) &value, 2);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesNative (uint value)
+                {
+                        return GetBytesPtr ((byte *) &value, 4);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesNative (ulong value)
+                {
+                        return GetBytesPtr ((byte *) &value, 8);
+                }
+
+                unsafe public static byte[] GetBytesNative (float value)
+                {
+                        return GetBytesPtr ((byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesNative (double value)
+                {
+			return GetBytesPtr ((byte *) &value, 8);
+                }
+
+                unsafe public static byte[] GetBytesLE (bool value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 1);
+                }
+
+                unsafe public static byte[] GetBytesLE (char value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesLE (short value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesLE (int value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesLE (long value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesLE (ushort value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesLE (uint value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesLE (ulong value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+
+                unsafe public static byte[] GetBytesLE (float value)
+                {
+                        return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesLE (double value)
+                {
+			return GetBytesSwap (!BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+		
+                unsafe public static byte[] GetBytesBE (bool value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 1);
+                }
+
+                unsafe public static byte[] GetBytesBE (char value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesBE (short value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                unsafe public static byte[] GetBytesBE (int value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesBE (long value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesBE (ushort value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 2);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesBE (uint value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                [CLSCompliant (false)]
+                unsafe public static byte[] GetBytesBE (ulong value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+
+                unsafe public static byte[] GetBytesBE (float value)
+                {
+                        return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 4);
+                }
+
+                unsafe public static byte[] GetBytesBE (double value)
+                {
+			return GetBytesSwap (BitConverter.IsLittleEndian, (byte *) &value, 8);
+                }
+#endif
+		
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/EnumMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/EnumMirror.cs
new file mode 100644
index 0000000..5131b2a
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/EnumMirror.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * Represents an enum value in the debuggee
+	 */
+	public class EnumMirror : StructMirror {
+	
+		internal EnumMirror (VirtualMachine vm, TypeMirror type, Value[] fields) : base (vm, type, fields) {
+		}
+
+		internal EnumMirror (VirtualMachine vm, TypeMirror type, PrimitiveValue value) : base (vm, type, new Value[] { value }) {
+			if (type == null)
+				throw new ArgumentNullException ("type");
+			if (value == null)
+				throw new ArgumentNullException ("value");
+			if (!type.IsEnum)
+				throw new ArgumentException ("type must be an enum type", "type");
+			TypeMirror t = type.EnumUnderlyingType;
+			if (value.Value == null || !value.Value.GetType ().IsPrimitive || t != vm.RootDomain.GetCorrespondingType (value.Value.GetType ()))
+				throw new ArgumentException ("Value '" + value.Value + "' does not match the type of the enum.");
+		}
+
+		public object Value {
+			get {
+				return ((PrimitiveValue)Fields [0]).Value;
+			}
+			set {
+				SetField (0, vm.CreateValue (value));
+			}
+		}
+
+		public string StringValue {
+			get {
+				foreach (FieldInfoMirror f in Type.GetFields ()) {
+					if (f.IsStatic) {
+						object v = (Type.GetValue (f) as EnumMirror).Value;
+						if (f.IsStatic && v.Equals (Value))
+							return f.Name;
+					}
+				}
+				return Value.ToString ();
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/Event.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/Event.cs
new file mode 100644
index 0000000..6a09dea
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/Event.cs
@@ -0,0 +1,50 @@
+
+namespace Mono.Debugger.Soft
+{
+	public abstract class Event {
+		protected VirtualMachine vm;
+		EventType evtype;
+		ThreadMirror thread;
+		int req_id;
+		long thread_id;
+
+		internal Event (EventType evtype, VirtualMachine vm, int req_id, long thread_id) {
+			this.evtype = evtype;
+			this.vm = vm;
+			this.req_id = req_id;
+			this.thread_id = thread_id;
+		}
+
+		internal Event (EventType evtype, VirtualMachine vm) {
+			this.evtype = evtype;
+			this.vm = vm;
+			this.thread_id = -1;
+		}
+
+		public EventType EventType {
+			get {
+				return evtype;
+			}
+		}
+
+		public override string ToString () {
+			return evtype.ToString ();
+		}
+
+		public ThreadMirror Thread {
+			get {
+				if (thread_id == -1)
+					return null;
+				if (thread == null)
+					thread = vm.GetThread (thread_id);
+				return thread;
+			}
+	    }
+
+		public EventRequest Request {
+			get {
+				return vm.GetRequest (req_id);
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/EventQueueImpl.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventQueueImpl.cs
new file mode 100644
index 0000000..08826fe
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventQueueImpl.cs
@@ -0,0 +1,133 @@
+#if FALSE
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using Mono.Debugger;
+using Mono.Debugger.Requests;
+using Mono.Debugger.Events;
+
+namespace Mono.Debugger.Soft
+{
+	class EventQueueImpl : MirrorImpl, EventQueue
+	{
+		bool disconnected;
+		Dictionary<int, byte[]> reply_packets;
+		Thread receiver_thread;
+		Queue queue;
+		object queue_monitor;
+		object reply_packets_monitor;
+
+		public EventQueueImpl (VirtualMachineImpl vm) : base (vm) {
+			reply_packets = new Dictionary<int, byte[]> ();
+			reply_packets_monitor = new Object ();
+
+			queue = new Queue ();
+			queue_monitor = new Object ();
+			receiver_thread = new Thread (new ThreadStart (receiver_thread_main));
+			receiver_thread.Start ();
+		}
+
+		public EventSet Remove () {
+			if (disconnected)
+				// FIXME: VMDisconnectedException
+				throw new IOException ();
+
+			lock (queue_monitor) {
+				if (queue.Count == 0)
+					Monitor.Wait (queue_monitor);
+				return (EventSet)queue.Dequeue ();
+			}
+		}
+
+		public EventSet Remove (int timeout) {
+			throw new NotImplementedException ();
+		}
+
+		Event DecodeEventInfo (WireProtocol.EventInfo info) {
+			EventRequest req = FindRequest (info.requestId);
+			if (info.eventKind == WireProtocol.EVENT_VM_START) {
+				WireProtocol.VMStartEventInfo einfo = (WireProtocol.VMStartEventInfo)info;
+				return new VMStartEventImpl (vm, req, new ThreadReferenceImpl (vm, einfo.thread), new AppDomainMirrorImpl (vm, einfo.domain));
+			} else if (info.eventKind == WireProtocol.EVENT_VM_DEATH) {
+				return new VMDeathEventImpl (vm, req);
+			} else if (info.eventKind == WireProtocol.EVENT_THREAD_START) {
+				WireProtocol.ThreadStartEventInfo einfo = (WireProtocol.ThreadStartEventInfo)info;
+				return new ThreadStartEventImpl (vm, req, new ThreadReferenceImpl (vm, einfo.thread));
+			} else if (info.eventKind == WireProtocol.EVENT_THREAD_DEATH) {
+				WireProtocol.ThreadDeathEventInfo einfo = (WireProtocol.ThreadDeathEventInfo)info;
+				return new ThreadDeathEventImpl (vm, req, new ThreadReferenceImpl (vm, einfo.thread));
+			} else {
+				throw new NotImplementedException ();
+			}
+		}
+
+		EventRequest FindRequest (int requestId) {
+			if (requestId == 0)
+				return null;
+			else
+				return ((EventRequestManagerImpl)vm.EventRequestManager).FindRequest (requestId);
+		}
+
+		// Wait for the reply for a command packet
+		public byte[] WaitForReply (int packetId) {
+			while (true) {
+				lock (reply_packets_monitor) {
+					if (reply_packets.ContainsKey (packetId)) {
+						byte[] reply = reply_packets [packetId];
+						reply_packets.Remove (packetId);
+						return reply;
+					} else {
+						Monitor.Wait (reply_packets_monitor);
+					}
+				}
+			}
+		}
+
+		void add_event_set (EventSet set) {
+			lock (queue_monitor) {
+				queue.Enqueue (set);
+				Monitor.Pulse (queue_monitor);
+			}
+		}
+
+		void receiver_thread_main () {
+
+			Connection conn = vm.Connection;
+
+			while (true) {
+				byte[] packet = conn.ReadPacket ();
+
+				if (packet.Length == 0) {
+					disconnected = true;
+				
+					VMDisconnectEventImpl ev = new VMDisconnectEventImpl (vm, null);
+					add_event_set (new EventSetImpl (vm, new Event [] { ev }, SuspendPolicy.SuspendNone));
+					break;
+				}
+
+				if (WireProtocol.IsReplyPacket (packet)) {
+					/* Reply packet */
+					int id = WireProtocol.GetPacketId (packet);
+					lock (reply_packets_monitor) {
+						reply_packets [id] = packet;
+						Monitor.PulseAll (reply_packets_monitor);
+					}
+				} else {
+					WireProtocol.Packet decoded = WireProtocol.DecodePacket (packet);
+					if (decoded is WireProtocol.Event.CompositePacket) {
+						WireProtocol.Event.CompositePacket p = (WireProtocol.Event.CompositePacket)decoded;
+						Event[] events = new Event [p.events.Length];
+						for (int i = 0; i < p.events.Length; ++i) {
+							events [i] = DecodeEventInfo (p.events [i]);
+						}
+
+						add_event_set (new EventSetImpl (vm, events, p.suspendPolicy));
+					}
+				}
+			}
+		}
+    }
+}
+#endif
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/EventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventRequest.cs
new file mode 100644
index 0000000..69f35f4
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventRequest.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Debugger.Soft
+{
+	public abstract class EventRequest {
+		protected int id;
+		protected EventType etype;
+		protected bool enabled;
+		protected VirtualMachine vm;
+		protected SuspendPolicy suspend;
+		protected int count;
+		protected ThreadMirror thread;
+		protected IList<AssemblyMirror> assembly_filter;
+
+		internal EventRequest (VirtualMachine vm, EventType etype) {
+			this.vm = vm;
+			this.etype = etype;
+			this.suspend = SuspendPolicy.All;
+		}
+
+		internal EventRequest (EventType etype, int id) {
+			this.id = id;
+			this.etype = etype;
+		}
+
+		internal int Id {
+			get {
+				return id;
+			}
+			set {
+				id = value;
+			}
+		}
+
+		public EventType EventType {
+			get {
+				return etype;
+			}
+		}
+
+		public bool Enabled {
+			get {
+				return enabled;
+			}
+			set {
+				if (value != enabled) {
+					if (value)
+						Enable ();
+					else
+						Disable ();
+				}
+			}
+		}
+
+		public int Count {
+			get {
+				return count;
+			}
+			set {
+				CheckDisabled ();
+				count = value;
+			}
+		}
+
+		public ThreadMirror Thread {
+			get {
+				return thread;
+			}
+			set {
+				CheckDisabled ();
+				if (value != null && value.VirtualMachine != vm)
+					throw new VMMismatchException ();
+				thread = value;
+			}
+		}
+
+		public IList<AssemblyMirror> AssemblyFilter {
+			get {
+				return assembly_filter;
+			}
+			set {
+				CheckDisabled ();
+				if (value != null) {
+					foreach (var ass in value)
+						if (ass == null)
+							throw new ArgumentException ("one of the elements of the array is null.");
+				}
+				assembly_filter = value;
+			}
+		}
+
+		/*
+		 * Every time an EventRequest object is enabled, a new JDWP event request
+		 * is created, and the event request's id changes.
+		 */
+		internal void SendReq (List<Modifier> mods) {
+			if (!enabled) {
+				if (Count > 0)
+					mods.Add (new CountModifier () { Count = Count });
+				if (Thread != null)
+					mods.Add (new ThreadModifier () { Thread = Thread.Id });
+				if (AssemblyFilter != null)
+					mods.Add (new AssemblyModifier () { Assemblies = AssemblyFilter.Select (x => x.Id ).ToArray () });
+				id = vm.conn.EnableEvent (EventType, suspend, mods);
+				SetEnabled (id);
+			}
+		}
+				
+		public virtual void Enable () {
+			SendReq (new List<Modifier> ());
+		}
+
+		public void Disable () {
+			if (enabled) {
+				vm.conn.ClearEventRequest (etype, id);
+				enabled = false;
+				// FIXME: This causes problems because Events can still reference
+				// the old id
+				//vm.RemoveRequest (this, id);
+				id = -1;
+			}
+		}
+
+		protected void SetEnabled (int id) {
+			this.id = id;
+			enabled = true;
+			vm.AddRequest (this, id);
+		}
+
+		protected void CheckDisabled () {
+			if (Enabled)
+				throw new InvalidOperationException ("Request objects can only be modified while they are disabled.");
+		}
+
+		protected void CheckMirror (VirtualMachine vm, Mirror m) {
+			if (vm != m.VirtualMachine)
+				throw new VMMismatchException ();
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs
new file mode 100644
index 0000000..cc83be5
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class EventSet {
+		protected VirtualMachine vm;
+		SuspendPolicy suspend_policy;
+		Event[] events;
+
+		internal EventSet (VirtualMachine vm, SuspendPolicy suspend_policy, Event[] events) {
+			this.vm = vm;
+			this.suspend_policy = suspend_policy;
+			this.events = events;
+		}
+
+		public SuspendPolicy SuspendPolicy {
+			get {
+				return suspend_policy;
+			}
+		}
+
+		public Event[] Events {
+			get {
+				return events;
+			}
+		}
+
+		public Event this [int index] {
+			get {
+				return Events [index];
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/EventType.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventType.cs
new file mode 100644
index 0000000..802a4ad
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/EventType.cs
@@ -0,0 +1,32 @@
+
+namespace Mono.Debugger.Soft
+{
+	// Keep it in sync with debugger-agent.h
+	public enum EventType {
+		VMStart = 0,
+		VMDeath = 1,
+		ThreadStart = 2,
+		ThreadDeath = 3,
+		AppDomainCreate = 4,
+		AppDomainUnload = 5,
+		MethodEntry = 6,
+		MethodExit = 7,
+		AssemblyLoad = 8,
+		AssemblyUnload = 9,
+		Breakpoint = 10,
+		Step = 11,
+		TypeLoad = 12,
+		Exception = 13,
+		KeepAlive = 14,
+		//
+		// System.Diagnostics.Debugger.Break ()
+		//
+		UserBreak = 15,
+		//
+		// System.Diagnostics.Debugger.Log ()
+		//
+		UserLog = 16,
+		// Not part of the wire protocol
+		VMDisconnect = 99
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEvent.cs
new file mode 100644
index 0000000..4b2c606
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class ExceptionEvent : Event {
+		ObjectMirror exc;
+		long exc_id;
+
+		internal ExceptionEvent (VirtualMachine vm, int req_id, long thread_id, long exc_id, long loc) : base (EventType.Exception, vm, req_id, thread_id) {
+			this.exc_id = exc_id;
+		}
+
+		public ObjectMirror Exception {
+			get {
+				if (exc == null)
+					exc = vm.GetObject (exc_id);
+				return exc;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs
new file mode 100644
index 0000000..906b43f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class ExceptionEventRequest : EventRequest {
+
+		TypeMirror exc_type;
+		bool caught, uncaught, subclasses;
+		
+		internal ExceptionEventRequest (VirtualMachine vm, TypeMirror exc_type, bool caught, bool uncaught) : base (vm, EventType.Exception) {
+			if (exc_type != null) {
+				CheckMirror (vm, exc_type);
+				TypeMirror exception_type = vm.RootDomain.Corlib.GetType ("System.Exception", false, false);
+				if (!exception_type.IsAssignableFrom (exc_type))
+					throw new ArgumentException ("The exception type does not inherit from System.Exception", "exc_type");
+			}
+			this.exc_type = exc_type;
+			this.caught = caught;
+			this.uncaught = uncaught;
+			this.subclasses = true;
+		}
+
+		public TypeMirror ExceptionType {
+			get {
+				return exc_type;
+			}
+		}
+
+		// Defaults to true
+		// Supported since protocol version 2.25
+		public bool IncludeSubclasses {
+			get {
+				return subclasses;
+			}
+			set {
+				vm.CheckProtocolVersion (2, 25);
+				subclasses = value;
+			}
+		}
+
+		public override void Enable () {
+			var mods = new List <Modifier> ();
+			mods.Add (new ExceptionModifier () { Type = exc_type != null ? exc_type.Id : 0, Caught = caught, Uncaught = uncaught, Subclasses = subclasses });
+			SendReq (mods);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/FieldInfoMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/FieldInfoMirror.cs
new file mode 100644
index 0000000..bb71ee3
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/FieldInfoMirror.cs
@@ -0,0 +1,181 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class FieldInfoMirror : Mirror {
+
+		TypeMirror parent;
+		string name;
+		TypeMirror type;
+		FieldAttributes attrs;
+		CustomAttributeDataMirror[] cattrs;
+		C.FieldDefinition meta;
+
+		public FieldInfoMirror (TypeMirror parent, long id, string name, TypeMirror type, FieldAttributes attrs) : base (parent.VirtualMachine, id) {
+			this.parent = parent;
+			this.name = name;
+			this.type = type;
+			this.attrs = attrs;
+		}
+
+		public TypeMirror DeclaringType {
+			get {
+				return parent;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+
+		public TypeMirror FieldType {
+			get {
+				return type;
+			}
+		}
+
+		public FieldAttributes Attributes {
+			get {
+				return attrs;
+			}
+		}
+
+		public bool IsLiteral
+		{
+			get {return (Attributes & FieldAttributes.Literal) != 0;}
+		} 
+
+		public bool IsStatic
+		{
+			get {return (Attributes & FieldAttributes.Static) != 0;}
+		} 
+
+		public bool IsInitOnly
+		{
+			get {return (Attributes & FieldAttributes.InitOnly) != 0;}
+		}
+ 
+		public Boolean IsPublic
+		{ 
+			get
+			{
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public;
+			}
+		}
+
+		public Boolean IsPrivate
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private;
+			}
+		}
+
+		public Boolean IsFamily
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family;
+			}
+		}
+
+		public Boolean IsAssembly
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly;
+			}
+		}
+
+		public Boolean IsFamilyAndAssembly
+		{
+			get {
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem;
+			}
+		}
+
+		public Boolean IsFamilyOrAssembly
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem;
+			}
+		}
+
+		public Boolean IsPinvokeImpl
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.PinvokeImpl) == FieldAttributes.PinvokeImpl;
+			}
+		}
+
+		public Boolean IsSpecialName
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.SpecialName) == FieldAttributes.SpecialName;
+			}
+		}
+
+		public Boolean IsNotSerialized
+		{
+			get
+			{
+				return (Attributes & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized;
+			}
+		}
+
+		public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
+			return GetCAttrs (null, inherit);
+		}
+
+		public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
+			if (attributeType == null)
+				throw new ArgumentNullException ("attributeType");
+			return GetCAttrs (attributeType, inherit);
+		}
+
+		public C.FieldDefinition Metadata {		
+			get {
+				if (parent.Metadata == null)
+					return null;
+				// FIXME: Speed this up
+				foreach (var fd in parent.Metadata.Fields) {
+					if (fd.Name == Name) {
+						meta = fd;
+						break;
+					}
+				}
+				if (meta == null)
+					/* Shouldn't happen */
+					throw new NotImplementedException ();
+				return meta;
+			}
+		}
+
+		CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+			if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
+				cattrs = new CustomAttributeDataMirror [0];
+
+			// FIXME: Handle inherit
+			if (cattrs == null) {
+				CattrInfo[] info = vm.conn.Type_GetFieldCustomAttributes (DeclaringType.Id, id, 0, false);
+				cattrs = CustomAttributeDataMirror.Create (vm, info);
+			}
+			var res = new List<CustomAttributeDataMirror> ();
+			foreach (var attr in cattrs)
+				if (type == null || attr.Constructor.DeclaringType == type)
+					res.Add (attr);
+			return res.ToArray ();
+		}
+	}
+}
+
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/IInvokeAsyncResult.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/IInvokeAsyncResult.cs
new file mode 100644
index 0000000..19b0ae7
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/IInvokeAsyncResult.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public interface IInvokeAsyncResult : IAsyncResult
+	{
+		void Abort ();
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ILExceptionHandler.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ILExceptionHandler.cs
new file mode 100644
index 0000000..927949d
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ILExceptionHandler.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+
+namespace Mono.Debugger.Soft
+{
+	public enum ILExceptionHandlerType
+	{
+		Catch = ExceptionClauseFlags.None,
+		Filter = ExceptionClauseFlags.Filter,
+		Finally = ExceptionClauseFlags.Finally,
+		Fault = ExceptionClauseFlags.Fault,
+	}
+
+	public class ILExceptionHandler
+	{
+		public int TryOffset { get; internal set; }
+		public int TryLength { get; internal set; }
+		public ILExceptionHandlerType HandlerType { get; internal set; }
+		public int HandlerOffset { get; internal set; }
+		public int HandlerLength { get; internal set;}
+		public int FilterOffset { get; internal set; }
+		public TypeMirror CatchType { get; internal set; }
+
+		internal ILExceptionHandler (int try_offset, int try_length, ILExceptionHandlerType handler_type, int handler_offset, int handler_length)
+		{
+			TryOffset = try_offset;
+			TryLength = try_length;
+			HandlerType = handler_type;
+			HandlerOffset = handler_offset;
+			HandlerLength = handler_length;
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ILInstruction.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ILInstruction.cs
new file mode 100644
index 0000000..6c2c7d1
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ILInstruction.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Metadata;
+using System.IO;
+using System.Reflection;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * This is similar to the Instruction class in Cecil, we can't use that
+	 * as its constructor is internal.
+	 */
+	public class ILInstruction
+	{
+		int offset;
+		OpCode opcode;
+		object operand;
+		ILInstruction prev, next;
+
+		internal ILInstruction (int offset, OpCode opcode, object operand) {
+			this.offset = offset;
+			this.opcode = opcode;
+			this.operand = operand;
+		}
+
+		public int Offset {
+			get {
+				return offset;
+			}
+		}
+
+		public OpCode OpCode {
+			get {
+				return opcode;
+			}
+		}
+
+		public Object Operand {
+			get {
+				return operand;
+			}
+			set {
+				operand = value;
+			}
+		}
+
+		public ILInstruction Next {
+			get {
+				return next;
+			}
+			set {
+				next = value;
+			}
+		}
+
+		public ILInstruction Previous {
+			get {
+				return prev;
+			}
+			set {
+				prev = value;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs
new file mode 100644
index 0000000..61c364e
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * A Mirror represents a runtime object in the remote virtual machine. Calling
+	 * methods/properties of mirror objects potentially involves a remoting call, 
+	 * which
+	 * has some overhead, and may also fail. Values of properties which are 
+	 * constant (like Type.Name) are cached locally, so only the first call is 
+	 * affected.
+	 * FIXME: Thread safety in the api ? 
+	 */
+	public interface IMirror
+	{
+		VirtualMachine VirtualMachine {
+			get;
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ITargetProcess.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ITargetProcess.cs
new file mode 100644
index 0000000..3a29e35
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ITargetProcess.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Mono.Debugger.Soft
+{
+	public interface ITargetProcess
+	{
+		event System.EventHandler Exited;
+		StreamReader StandardOutput { get; }
+		StreamReader StandardError { get; }
+		bool HasExited { get; }
+		void Kill ();
+		int Id { get; }
+		string ProcessName { get; }
+	}
+	
+	internal class ProcessWrapper: ITargetProcess
+	{
+		Process process;
+
+		public ProcessWrapper (Process process)
+		{
+			this.process = process;
+		}
+		
+		public Process Process {
+			get { return process; }
+		}
+		
+		public event System.EventHandler Exited {
+			add { process.Exited += value; }
+			remove { process.Exited -= value; }
+		}
+		
+		public StreamReader StandardOutput {
+			get {
+				return process.StandardOutput;
+			}
+		}
+		
+		public StreamReader StandardError {
+			get {
+				return process.StandardError;
+			}
+		}
+		
+		public bool HasExited {
+			get {
+				return process.HasExited;
+			}
+		}
+		
+		public void Kill ()
+		{
+			process.Kill ();
+		}
+
+		public int Id {
+			get {
+				return process.Id;
+			}
+		}
+		
+		public string ProcessName {
+			get {
+				return process.ProcessName;
+			}
+		}
+		
+		
+		
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/InterfaceMappingMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/InterfaceMappingMirror.cs
new file mode 100644
index 0000000..a4ccfbb
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/InterfaceMappingMirror.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class InterfaceMappingMirror : Mirror {
+
+		internal InterfaceMappingMirror (VirtualMachine vm, TypeMirror target, TypeMirror iface, MethodMirror[] iface_methods, MethodMirror[] target_methods) : base (vm, 0) {
+			TargetType = target;
+			InterfaceType = iface;
+			InterfaceMethods = iface_methods;
+			TargetMethods = target_methods;
+		}
+
+		public MethodMirror[] InterfaceMethods;
+
+		public TypeMirror InterfaceType;
+
+		public MethodMirror[] TargetMethods;
+
+		public TypeMirror TargetType;
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/InvalidStackFrameException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvalidStackFrameException.cs
new file mode 100644
index 0000000..751df40
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvalidStackFrameException.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class InvalidStackFrameException : Exception {
+		
+		public InvalidStackFrameException () : base ("The requested operation cannot be completed because the specified stack frame is no longer valid.") {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/InvocationException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvocationException.cs
new file mode 100644
index 0000000..d8ae2e6
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvocationException.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public class InvocationException : Exception {
+
+		ObjectMirror exception;
+
+		public InvocationException (ObjectMirror exception) {
+			this.exception = exception;
+		}
+
+		public ObjectMirror Exception {
+			get {
+				return exception;
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs
new file mode 100644
index 0000000..bc06479
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	[Flags]
+	public enum InvokeOptions {
+		None = 0,
+		/*
+		 * Disable breakpoints on the thread doing the invoke
+		 */
+		DisableBreakpoints = 1,
+		/*
+		 * Only resume the target thread during the invoke
+		 */
+		SingleThreaded = 2
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalVariable.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalVariable.cs
new file mode 100644
index 0000000..6003ae2
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalVariable.cs
@@ -0,0 +1,79 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class LocalVariable : Mirror {
+
+		MethodMirror method;
+		string name;
+		int index;
+		long type_id;
+		TypeMirror t;
+		bool is_arg;
+		int live_range_start, live_range_end;
+
+	    internal LocalVariable (VirtualMachine vm, MethodMirror method, int index, long type_id, string name, int live_range_start, int live_range_end, bool is_arg) : base (vm, 0) {
+			this.method = method;
+			this.index = index;
+			this.name = name;
+			this.type_id = type_id;
+			this.is_arg = is_arg;
+			this.live_range_start = live_range_start;
+			this.live_range_end = live_range_end;
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+
+		public int Index {
+			get {
+				return index;
+			}
+		}
+
+		public TypeMirror Type {
+			get {
+				if (t == null)
+					t = vm.GetType (type_id);
+				return t;
+			}
+		}
+
+		public bool IsArg {
+			get {
+				return is_arg;
+			}
+		}
+
+		public MethodMirror Method {
+			get {
+				return method;
+			}
+		}
+
+		internal int LiveRangeStart {
+			get {
+				return live_range_start;
+			}
+		}
+
+		internal int LiveRangeEnd {
+			get {
+				return live_range_end;
+			}
+		}
+
+		internal int GetValueIndex {
+			get {
+				if (IsArg)
+					return (-Index) - 1;
+				else
+					return Index;
+			}
+		}
+	}
+}
+
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/Location.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/Location.cs
new file mode 100644
index 0000000..0624095
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/Location.cs
@@ -0,0 +1,68 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class Location : Mirror
+	{
+		MethodMirror method;
+		//long native_addr;
+		int il_offset;
+		string source_file;
+		int line_number;
+		byte[] hash;
+		int column_number;
+		
+		internal Location (VirtualMachine vm, MethodMirror method, long native_addr, int il_offset, string source_file, int line_number, int column_number, byte[] hash) : base (vm, 0) {
+			this.method = method;
+			//this.native_addr = native_addr;
+			this.il_offset = il_offset;
+			this.source_file = source_file;
+			this.line_number = line_number;
+			this.hash = hash;
+			this.column_number = column_number;
+		}
+
+		public MethodMirror Method {
+			get {
+				return method;
+			}
+		}
+
+		public int ILOffset {
+			get {
+				return il_offset;
+			}
+		}
+
+		public string SourceFile {
+			get {
+				return source_file;
+			}
+	    }
+
+		public int LineNumber {
+			get {
+				return line_number;
+			}
+	    }
+
+		// Since protocol version 2.19, 0 in earlier protocol versions
+		public int ColumnNumber {
+			get {
+				return column_number;
+			}
+	    }
+
+		// MD5 hash of source file
+		// Since protocol version 2.14, null in earlier protocol versions
+		public byte[] SourceFileHash {
+			get {
+				return hash;
+			}
+		}
+
+		public override string ToString () {
+			return String.Format ("{0}+0x{1:x} at {2}:{3}", Method.FullName, ILOffset, SourceFile, LineNumber);
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs
new file mode 100644
index 0000000..481bf9a
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Text;
+using Mono.Cecil.Cil;
+using Mono.Cecil.Metadata;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Mono.Debugger.Soft
+{
+	public class MethodBodyMirror : Mirror
+	{
+		MethodMirror method;
+		MethodBodyInfo info;
+
+		internal MethodBodyMirror (VirtualMachine vm, MethodMirror method, MethodBodyInfo info) : base (vm, 0) {
+			this.method = method;
+			this.info = info;
+		}
+
+		public MethodMirror Method {
+			get {
+				return method;
+			}
+		}
+
+		public List<ILExceptionHandler> ExceptionHandlers {
+			get {
+				vm.CheckProtocolVersion (2, 18);
+				return info.clauses.Select (c =>
+				{
+					var handler = new ILExceptionHandler (c.try_offset, c.try_length, (ILExceptionHandlerType) c.flags, c.handler_offset, c.handler_length);
+					if (c.flags == ExceptionClauseFlags.None)
+						handler.CatchType = vm.GetType (c.catch_type_id);
+					else if (c.flags == ExceptionClauseFlags.Filter)
+						handler.FilterOffset = c.filter_offset;
+
+					return handler;
+				}).ToList ();
+			}
+		}
+
+		public byte[] GetILAsByteArray () {
+			return info.il;
+		}
+
+		public List<ILInstruction> Instructions {
+			get {
+				return ReadCilBody (new BinaryReader (new MemoryStream (info.il)), info.il.Length);
+			}
+		}
+
+		static bool opcodes_inited;
+
+		static OpCode [] OneByteOpCode = new OpCode [0xe0 + 1];
+		static OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1];
+
+		// Adapted from Cecil
+		List<ILInstruction> ReadCilBody (BinaryReader br, int code_size)
+		{
+			long start = br.BaseStream.Position;
+			ILInstruction last = null;
+			//GenericContext context = new GenericContext (body.Method);
+			List<ILInstruction> code = new List<ILInstruction> ();
+
+			var by_offset = new Dictionary<int, ILInstruction> ();
+
+			if (!opcodes_inited) {
+				foreach (FieldInfo fi in typeof (OpCodes).GetFields (BindingFlags.Static|BindingFlags.Public)) {
+					var val = (OpCode)fi.GetValue (null);
+
+					if (val.Op1 == 0xff)
+						OneByteOpCode [val.Op2] = val;
+					else
+						TwoBytesOpCode [val.Op2] = val;
+				}
+				opcodes_inited = true;
+			}
+
+			while (br.BaseStream.Position < start + code_size) {
+				OpCode op;
+				long offset = br.BaseStream.Position - start;
+				int cursor = br.ReadByte ();
+				int token;
+				ResolvedToken t;
+
+				if (cursor == 0xfe)
+					op = TwoBytesOpCode [br.ReadByte ()];
+				else
+					op = OneByteOpCode [cursor];
+
+				ILInstruction instr = new ILInstruction ((int)offset, op, null);
+
+				by_offset [instr.Offset] = instr;
+
+				switch (op.OperandType) {
+				case OperandType.InlineNone :
+					break;
+				case OperandType.InlineSwitch :
+					uint length = br.ReadUInt32 ();
+					int [] branches = new int [length];
+					int [] buf = new int [length];
+					for (int i = 0; i < length; i++)
+						buf [i] = br.ReadInt32 ();
+					for (int i = 0; i < length; i++)
+						branches [i] = Convert.ToInt32 (br.BaseStream.Position - start + buf [i]);
+					instr.Operand = branches;
+					break;
+				case OperandType.ShortInlineBrTarget :
+					sbyte sbrtgt = br.ReadSByte ();
+					instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + sbrtgt);
+					break;
+				case OperandType.InlineBrTarget :
+					int brtgt = br.ReadInt32 ();
+					instr.Operand = Convert.ToInt32 (br.BaseStream.Position - start + brtgt);
+					break;
+				case OperandType.ShortInlineI :
+					if (op == OpCodes.Ldc_I4_S)
+						instr.Operand = br.ReadSByte ();
+					else
+						instr.Operand = br.ReadByte ();
+					break;
+				case OperandType.ShortInlineVar :
+					instr.Operand = br.ReadByte ();
+					break;
+				case OperandType.ShortInlineArg :
+					instr.Operand = br.ReadByte ();
+					break;
+				case OperandType.InlineSig :
+					br.ReadInt32 ();
+					//instr.Operand = GetCallSiteAt (br.ReadInt32 (), context);
+					break;
+				case OperandType.InlineI :
+					instr.Operand = br.ReadInt32 ();
+					break;
+				case OperandType.InlineVar :
+					instr.Operand = br.ReadInt16 ();
+					break;
+				case OperandType.InlineArg :
+					instr.Operand = br.ReadInt16 ();
+					break;
+				case OperandType.InlineI8 :
+					instr.Operand = br.ReadInt64 ();
+					break;
+				case OperandType.ShortInlineR :
+					instr.Operand = br.ReadSingle ();
+					break;
+				case OperandType.InlineR :
+					instr.Operand = br.ReadDouble ();
+					break;
+				case OperandType.InlineString :
+					token = br.ReadInt32 ();
+					t = vm.conn.Method_ResolveToken (Method.Id, token);
+					if (t.Type == TokenType.STRING)
+						instr.Operand = t.Str;
+					break;
+				case OperandType.InlineField :
+				case OperandType.InlineMethod :
+				case OperandType.InlineType :
+				case OperandType.InlineTok :
+					token = br.ReadInt32 ();
+
+					t = vm.conn.Method_ResolveToken (Method.Id, token);
+
+					switch (t.Type) {
+					case TokenType.TYPE:
+						instr.Operand = vm.GetType (t.Id);
+						break;
+					case TokenType.FIELD:
+						// FIXME: No vm.GetField ()
+						//instr.Operand = vm.GetField (t.Id);
+						break;
+					case TokenType.METHOD:
+						instr.Operand = vm.GetMethod (t.Id);
+						break;
+					case TokenType.UNKNOWN:
+						break;
+					default:
+						throw new NotImplementedException ("Unknown token type: " + t.Type);
+					}
+					break;
+				}
+
+				if (last != null) {
+					last.Next = instr;
+					instr.Previous = last;
+				}
+
+				last = instr;
+
+				code.Add (instr);
+			}
+
+			// resolve branches
+			foreach (ILInstruction i in code) {
+				switch (i.OpCode.OperandType) {
+				case OperandType.ShortInlineBrTarget:
+				case OperandType.InlineBrTarget:
+					i.Operand = by_offset [(int)i.Operand];
+					break;
+				case OperandType.InlineSwitch:
+					int [] lbls = (int []) i.Operand;
+					ILInstruction [] instrs = new ILInstruction [lbls.Length];
+					for (int j = 0; j < lbls.Length; j++)
+						instrs [j] = by_offset [lbls [j]];
+					i.Operand = instrs;
+					break;
+				}
+			}
+
+			return code;
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEvent.cs
new file mode 100644
index 0000000..d21f60c
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class MethodEntryEvent : Event {
+		MethodMirror method;
+		long id;
+
+		internal MethodEntryEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.MethodEntry, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public MethodMirror Method {
+			get {
+				if (method == null)
+					method = vm.GetMethod (id);
+				return method;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEventRequest.cs
new file mode 100644
index 0000000..e54cb73
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEventRequest.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class MethodEntryEventRequest : EventRequest {
+
+		internal MethodEntryEventRequest (VirtualMachine vm) : base (vm, EventType.MethodEntry) {
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEvent.cs
new file mode 100644
index 0000000..55cd4b7
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class MethodExitEvent : Event {
+		MethodMirror method;
+		long id;
+
+		internal MethodExitEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.MethodExit, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public MethodMirror Method {
+			get {
+				if (method == null)
+					method = vm.GetMethod (id);
+				return method;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEventRequest.cs
new file mode 100644
index 0000000..be89dcd
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodExitEventRequest.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class MethodExitEventRequest : EventRequest {
+
+		internal MethodExitEventRequest (VirtualMachine vm) : base (vm, EventType.MethodExit) {
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs
new file mode 100644
index 0000000..04717c6
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs
@@ -0,0 +1,411 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class MethodMirror : Mirror
+	{
+		string name;
+		MethodInfo info;
+		TypeMirror declaring_type;
+		DebugInfo debug_info;
+		C.MethodDefinition meta;
+		CustomAttributeDataMirror[] cattrs;
+		ParameterInfoMirror[] param_info;
+		ParameterInfoMirror ret_param;
+		LocalVariable[] locals;
+		IList<Location> locations;
+		MethodBodyMirror body;
+		MethodMirror gmd;
+		TypeMirror[] type_args;
+
+		internal MethodMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		public string Name {
+			get {
+				if (name == null)
+					name = vm.conn.Method_GetName (id);
+				return name;
+			}
+		}
+
+		public TypeMirror DeclaringType {
+			get {
+				if (declaring_type == null)
+					declaring_type = vm.GetType (vm.conn.Method_GetDeclaringType (id));
+				return declaring_type;
+			}
+		}
+
+		public TypeMirror ReturnType {
+			get {
+				return ReturnParameter.ParameterType;
+			}
+		}
+
+		// FIXME:
+		public string FullName {
+			get {
+				string type_namespace = DeclaringType.Namespace;
+				string type_name = DeclaringType.Name;
+				StringBuilder sb = new StringBuilder ();
+				sb.Append (ReturnType.Name);
+				sb.Append (' ');
+				if (type_namespace != String.Empty)
+					sb.Append (type_namespace + ".");
+				sb.Append(type_name);
+				sb.Append(":");
+				sb.Append(Name);
+				sb.Append(" ");
+				sb.Append("(");
+				for (var i = 0; i < param_info.Length; i++) {
+					sb.Append(param_info[i].ParameterType.Name);
+					if (i != param_info.Length - 1)
+						sb.Append(", ");
+				}
+				sb.Append(")");
+				return sb.ToString ();
+			}
+		}
+
+		/*
+		 * Creating the custom attributes themselves could modify the behavior of the
+		 * debuggee, so we return objects similar to the CustomAttributeData objects
+		 * used by the reflection-only functionality on .net.
+		 * Since protocol version 2.21
+		 */
+		public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
+			return GetCAttrs (null, inherit);
+		}
+
+		/* Since protocol version 2.21 */
+		public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
+			if (attributeType == null)
+				throw new ArgumentNullException ("attributeType");
+			return GetCAttrs (attributeType, inherit);
+		}
+
+		CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+			if (cattrs == null && meta != null && !Metadata.HasCustomAttributes)
+				cattrs = new CustomAttributeDataMirror [0];
+
+			// FIXME: Handle inherit
+			if (cattrs == null) {
+				CattrInfo[] info = vm.conn.Method_GetCustomAttributes (id, 0, false);
+				cattrs = CustomAttributeDataMirror.Create (vm, info);
+			}
+			var res = new List<CustomAttributeDataMirror> ();
+			foreach (var attr in cattrs)
+				if (type == null || attr.Constructor.DeclaringType == type)
+					res.Add (attr);
+			return res.ToArray ();
+		}
+
+		MethodInfo GetInfo () {
+			if (info == null)
+				info = vm.conn.Method_GetInfo (id);
+			
+			return info;
+		}
+
+		public int MetadataToken {
+			get {
+				return GetInfo ().token;
+			}
+		}
+
+		public MethodAttributes Attributes {
+			get {
+				return (MethodAttributes) GetInfo ().attributes;
+			}
+		}
+
+		public bool IsPublic { 
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
+			}
+		}
+		public bool IsPrivate {
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
+			}
+		}
+		public bool IsFamily {
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family;
+			}
+		}
+		public bool IsAssembly {
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly;
+			}
+		}
+		public bool IsFamilyAndAssembly {
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
+			}
+		}
+		public bool IsFamilyOrAssembly {
+			get {
+				return (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
+			}
+		}
+		public bool IsStatic {
+			get {
+				return (Attributes & MethodAttributes.Static) != 0;
+			}
+		}
+		public bool IsFinal {
+			get {
+				return (Attributes & MethodAttributes.Final) != 0;
+			}
+		}
+		public bool IsVirtual {
+			get {
+				return (Attributes & MethodAttributes.Virtual) != 0;
+			}
+		}
+		public bool IsHideBySig {
+			get {
+				return (Attributes & MethodAttributes.HideBySig) != 0;
+			}
+		}
+		public bool IsAbstract {
+			get {
+				return (Attributes & MethodAttributes.Abstract) != 0;
+			}
+		}
+		public bool IsSpecialName {
+			get {
+				return (Attributes & MethodAttributes.SpecialName) != 0;
+			}
+		}
+
+		public bool IsConstructor {
+			get {
+				int attr = (int)Attributes;
+				return ((attr & (int)MethodAttributes.RTSpecialName) != 0
+					&& (Name == ".ctor"));
+			}
+		}
+
+		// Since protocol version 2.12
+		public bool IsGenericMethodDefinition {
+			get {
+				vm.CheckProtocolVersion (2, 12);
+				return GetInfo ().is_gmd;
+			}
+		}
+
+		// Since protocol version 2.12
+		public bool IsGenericMethod {
+			get {
+				vm.CheckProtocolVersion (2, 12);
+				return GetInfo ().is_generic_method;
+			}
+		}
+
+		public MethodImplAttributes GetMethodImplementationFlags() {
+			return (MethodImplAttributes)GetInfo ().iattributes;
+		}
+
+		public ParameterInfoMirror[] GetParameters () {
+			if (param_info == null) {
+				var pi = vm.conn.Method_GetParamInfo (id);
+				param_info = new ParameterInfoMirror [pi.param_count];
+				// Return
+				ret_param = new ParameterInfoMirror (this, -1, vm.GetType (pi.ret_type), null, ParameterAttributes.Retval);
+				// FIXME: this
+				// FIXME: Attributes
+				for (int i = 0; i < pi.param_count; ++i) {
+					param_info [i] = new ParameterInfoMirror (this, i, vm.GetType (pi.param_types [i]), pi.param_names [i], 0);
+				}
+			}
+
+			return param_info;
+		}
+
+		public ParameterInfoMirror ReturnParameter {
+			get {
+				if (ret_param == null)
+					GetParameters ();
+				return ret_param;
+			}
+		}
+
+		public LocalVariable[] GetLocals () {
+			if (locals == null) {
+				LocalsInfo li = new LocalsInfo ();
+				try {
+					li = vm.conn.Method_GetLocalsInfo (id);
+				} catch (CommandException) {
+					throw new AbsentInformationException ();
+				}
+
+				// Add the arguments as well
+				var pi = vm.conn.Method_GetParamInfo (id);
+
+				locals = new LocalVariable [pi.param_count + li.names.Length];
+
+				for (int i = 0; i < pi.param_count; ++i)
+					locals [i] = new LocalVariable (vm, this, i, pi.param_types [i], pi.param_names [i], -1, -1, true);
+
+				for (int i = 0; i < li.names.Length; ++i)
+					locals [i + pi.param_count] = new LocalVariable (vm, this, i, li.types [i], li.names [i], li.live_range_start [i], li.live_range_end [i], false);
+			}
+			return locals;
+		}
+
+		public LocalVariable GetLocal (string name) {
+			if (name == null)
+				throw new ArgumentNullException ("name");
+
+			GetLocals ();
+
+			LocalVariable res = null;
+			for (int i = 0; i < locals.Length; ++i) {
+				if (locals [i].Name == name) {
+					if (res != null)
+						throw new AmbiguousMatchException ("More that one local has the name '" + name + "'.");
+					res = locals [i];
+				}
+			}
+
+			return res;
+		}
+
+		public MethodBodyMirror GetMethodBody () {
+			if (body == null) {
+				MethodBodyInfo info = vm.conn.Method_GetBody (id);
+
+				body = new MethodBodyMirror (vm, this, info);
+			}
+			return body;
+		}
+
+		public MethodMirror GetGenericMethodDefinition () {
+			vm.CheckProtocolVersion (2, 12);
+			if (gmd == null) {
+				if (info.gmd == 0)
+					throw new InvalidOperationException ();
+				gmd = vm.GetMethod (info.gmd);
+			}
+			return gmd;
+		}
+
+		// Since protocol version 2.15
+		public TypeMirror[] GetGenericArguments () {
+			vm.CheckProtocolVersion (2, 15);
+			if (type_args == null)
+				type_args = vm.GetTypes (GetInfo ().type_args);
+			return type_args;
+		}
+
+		// Since protocol version 2.24
+		public MethodMirror MakeGenericMethod (TypeMirror[] args) {
+			if (args == null)
+				throw new ArgumentNullException ("args");
+			foreach (var a in args)
+				if (a == null)
+					throw new ArgumentNullException ("args");
+
+			if (!IsGenericMethodDefinition)
+				throw new InvalidOperationException ("not a generic method definition");
+
+			if (GetGenericArguments ().Length != args.Length)
+				throw new ArgumentException ("Incorrect length");
+
+			vm.CheckProtocolVersion (2, 24);
+			long id = -1;
+			try {
+				id = vm.conn.Method_MakeGenericMethod (Id, args.Select (t => t.Id).ToArray ());
+			} catch (CommandException) {
+				throw new InvalidOperationException ();
+			}
+			return vm.GetMethod (id);
+		}
+
+		public IList<int> ILOffsets {
+			get {
+				if (debug_info == null)
+					debug_info = vm.conn.Method_GetDebugInfo (id);
+				return Array.AsReadOnly (debug_info.il_offsets);
+			}
+		}
+
+		public IList<int> LineNumbers {
+			get {
+				if (debug_info == null)
+					debug_info = vm.conn.Method_GetDebugInfo (id);
+				return Array.AsReadOnly (debug_info.line_numbers);
+			}
+		}
+
+		public string SourceFile {
+			get {
+				if (debug_info == null)
+					debug_info = vm.conn.Method_GetDebugInfo (id);
+				return debug_info.source_files.Length > 0 ? debug_info.source_files [0].source_file : null;
+			}
+		}
+
+		public IList<Location> Locations {
+			get {
+				if (locations == null) {
+					var il_offsets = ILOffsets;
+					var line_numbers = LineNumbers;
+					IList<Location> res = new Location [ILOffsets.Count];
+					for (int i = 0; i < il_offsets.Count; ++i)
+						res [i] = new Location (vm, this, -1, il_offsets [i], debug_info.source_files [i].source_file, line_numbers [i], debug_info.column_numbers [i], debug_info.source_files [i].hash);
+					locations = res;
+				}
+				return locations;
+			}
+		}				
+
+		internal int il_offset_to_line_number (int il_offset, out string src_file, out byte[] src_hash, out int column_number) {
+			if (debug_info == null)
+				debug_info = vm.conn.Method_GetDebugInfo (id);
+
+			// FIXME: Optimize this
+			src_file = null;
+			src_hash = null;
+			column_number = 0;
+			for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
+				if (debug_info.il_offsets [i] <= il_offset) {
+					src_file = debug_info.source_files [i].source_file;
+					src_hash = debug_info.source_files [i].hash;
+					column_number = debug_info.column_numbers [i];
+					return debug_info.line_numbers [i];
+				}
+			}
+			return -1;
+		}
+
+		public Location LocationAtILOffset (int il_offset) {
+			IList<Location> locs = Locations;
+
+			// FIXME: Optimize this
+			for (int i = locs.Count - 1; i >= 0; --i) {
+				if (locs [i].ILOffset <= il_offset)
+					return locs [i];
+			}
+
+			return null;
+		}
+
+		public C.MethodDefinition Metadata {
+			get {
+				if (meta == null)
+					meta = (C.MethodDefinition)DeclaringType.Assembly.Metadata.MainModule.LookupToken (MetadataToken);
+				return meta;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs
new file mode 100644
index 0000000..699706c
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public abstract class Mirror : IMirror
+	{
+		protected VirtualMachine vm;
+		protected long id; // The id used in the protocol
+
+		internal Mirror (VirtualMachine vm, long id) {
+			this.vm = vm;
+			this.id = id;
+		}
+
+		internal Mirror () {
+		}
+
+		public VirtualMachine VirtualMachine {
+			get {
+				return vm;
+			}
+		}
+
+		internal long Id {
+			get {
+				return id;
+			}
+		}
+
+		protected void SetVirtualMachine (VirtualMachine vm) {
+			this.vm = vm;
+		}
+
+		protected void CheckMirror (Mirror m) {
+			if (vm != m.VirtualMachine)
+				throw new VMMismatchException ();
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ModuleMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ModuleMirror.cs
new file mode 100644
index 0000000..fb94436
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ModuleMirror.cs
@@ -0,0 +1,66 @@
+using System;
+using Mono.Debugger;
+using Mono.Cecil;
+
+namespace Mono.Debugger.Soft
+{
+	public class ModuleMirror : Mirror
+	{
+		ModuleInfo info;
+		Guid guid;
+		AssemblyMirror assembly;
+
+		internal ModuleMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		void ReadInfo () {
+			if (info == null)
+				info = vm.conn.Module_GetInfo (id);
+		}
+
+		public string Name {
+			get {
+				ReadInfo ();
+				return info.Name;
+			}
+		}
+
+		public string ScopeName {
+			get {
+				ReadInfo ();
+				return info.ScopeName;
+			}
+		}
+
+		public string FullyQualifiedName {
+			get {
+				ReadInfo ();
+				return info.FQName;
+			}
+		}
+
+		public Guid ModuleVersionId {
+			get {
+				if (guid == Guid.Empty) {
+					ReadInfo ();
+					guid = new Guid (info.Guid);
+				}
+				return guid;
+			}
+		}
+
+		public AssemblyMirror Assembly {
+			get {
+				if (assembly == null) {
+					ReadInfo ();
+					if (info.Assembly == 0)
+						return null;
+					assembly = vm.GetAssembly (info.Assembly);
+				}
+				return assembly;
+			}
+		}
+
+		// FIXME: Add function to query the guid, check in Metadata
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectCollectedException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectCollectedException.cs
new file mode 100644
index 0000000..f89177c
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectCollectedException.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class ObjectCollectedException : Exception {
+		
+		public ObjectCollectedException () : base ("The requested operation cannot be completed because the object has been garbage collected.") {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs
new file mode 100644
index 0000000..18611ba
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs
@@ -0,0 +1,380 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.Remoting.Messaging;
+using System.Threading;
+
+namespace Mono.Debugger.Soft
+{
+	public class ObjectMirror : Value {
+		TypeMirror type;
+		AppDomainMirror domain;
+	
+		internal ObjectMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+	
+		internal ObjectMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id) {
+			this.type = type;
+			this.domain = domain;
+		}
+
+		void GetInfo () {
+			var info = vm.conn.Object_GetInfo (id);
+			type = vm.GetType (info.type_id);
+			domain = vm.GetDomain (info.domain_id);
+		}
+
+		public TypeMirror Type {
+			get {
+				if (type == null) {
+					if (vm.conn.Version.AtLeast (2, 5))
+						GetInfo ();
+					else
+				 		type = vm.GetType (vm.conn.Object_GetType (id));
+				}
+				return type;
+			}
+		}
+
+		public AppDomainMirror Domain {
+			get {
+				if (domain == null) {
+					if (vm.conn.Version.AtLeast (2, 5))
+						GetInfo ();
+					else
+						domain = vm.GetDomain (vm.conn.Object_GetDomain (id));
+				}
+				return domain;
+			}
+		}
+
+		public bool IsCollected {
+			get {
+				return vm.conn.Object_IsCollected (id);
+			}
+		}
+
+		public Value GetValue (FieldInfoMirror field) {
+			return GetValues (new FieldInfoMirror [] { field }) [0];
+		}
+
+		public Value[] GetValues (IList<FieldInfoMirror> fields) {
+			if (fields == null)
+				throw new ArgumentNullException ("fields");
+			foreach (FieldInfoMirror f in fields) {
+				if (f == null)
+					throw new ArgumentNullException ("field");
+				CheckMirror (f);
+			}
+			long[] ids = new long [fields.Count];
+			for (int i = 0; i < fields.Count; ++i)
+				ids [i] = fields [i].Id;
+			try {
+				return vm.DecodeValues (vm.conn.Object_GetValues (id, ids));
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
+					throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
+				else
+					throw;
+			}
+		}
+
+		public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
+			if (fields == null)
+				throw new ArgumentNullException ("fields");
+			if (values == null)
+				throw new ArgumentNullException ("values");
+			foreach (FieldInfoMirror f in fields) {
+				if (f == null)
+					throw new ArgumentNullException ("field");
+				CheckMirror (f);
+			}
+			foreach (Value v in values) {
+				if (v == null)
+					throw new ArgumentNullException ("values");
+				CheckMirror (v);
+			}
+			long[] ids = new long [fields.Count];
+			for (int i = 0; i < fields.Count; ++i)
+				ids [i] = fields [i].Id;
+			try {
+				vm.conn.Object_SetValues (id, ids, vm.EncodeValues (values));
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
+					throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
+				else if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
+					throw new ArgumentException ("One of the values is not valid for its field.", "values");
+				else
+					throw;
+			}
+		}
+
+		public void SetValue (FieldInfoMirror field, Value value) {
+			SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
+		}
+
+		/*
+		 * The current address of the object. It can change during garbage 
+		 * collections. Use a long since the debuggee might have a different 
+		 * pointer size. 
+		 */
+		public long Address {
+			get {
+				return vm.conn.Object_GetAddress (id);
+			}
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
+			return InvokeMethod (vm, thread, method, this, arguments, InvokeOptions.None);
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
+			return InvokeMethod (vm, thread, method, this, arguments, options);
+		}
+
+		[Obsolete ("Use the overload without the 'vm' argument")]
+		public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
+		}
+
+		public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
+		}
+
+		public Value EndInvokeMethod (IAsyncResult asyncResult) {
+			return EndInvokeMethodInternal (asyncResult);
+		}
+
+		//
+		// Invoke the members of METHODS one-by-one, calling CALLBACK after each invoke was finished. The IAsyncResult will be marked as completed after all invokes have
+		// finished. The callback will be called with a different IAsyncResult that represents one method invocation.
+		// From protocol version 2.22.
+		//
+		public IAsyncResult BeginInvokeMultiple (ThreadMirror thread, MethodMirror[] methods, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return BeginInvokeMultiple (vm, thread, methods, this, arguments, options, callback, state);
+		}
+
+		public void EndInvokeMultiple (IAsyncResult asyncResult) {
+			EndInvokeMultipleInternal (asyncResult);
+		}
+
+		/*
+		 * Common implementation for invokes
+		 */
+
+		class InvokeAsyncResult : IInvokeAsyncResult {
+
+			public object AsyncState {
+				get; set;
+			}
+
+			public WaitHandle AsyncWaitHandle {
+				get; set;
+			}
+
+			public bool CompletedSynchronously {
+				get {
+					return false;
+				}
+			}
+
+			public bool IsCompleted {
+				get; set;
+			}
+
+			public AsyncCallback Callback {
+				get; set;
+			}
+
+			public ErrorCode ErrorCode {
+				get; set;
+			}
+
+			public VirtualMachine VM {
+				get; set;
+			}
+
+			public ThreadMirror Thread {
+				get; set;
+			}
+
+			public ValueImpl Value {
+				get; set;
+			}
+
+			public ValueImpl Exception {
+				get; set;
+			}
+
+			public int ID {
+				get; set;
+			}
+
+			public bool IsMultiple {
+				get; set;
+			}
+			   
+			public int NumPending;
+
+			public void Abort ()
+			{
+				if (ID == 0) // Ooops
+					return;
+
+				ObjectMirror.AbortInvoke (VM, Thread, ID);
+			}
+		}
+
+		internal static IInvokeAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, Value this_obj, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			if (thread == null)
+				throw new ArgumentNullException ("thread");
+			if (method == null)
+				throw new ArgumentNullException ("method");
+			if (arguments == null)
+				arguments = new Value [0];
+
+			InvokeFlags f = InvokeFlags.NONE;
+
+			if ((options & InvokeOptions.DisableBreakpoints) != 0)
+				f |= InvokeFlags.DISABLE_BREAKPOINTS;
+			if ((options & InvokeOptions.SingleThreaded) != 0)
+				f |= InvokeFlags.SINGLE_THREADED;
+
+			InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback };
+
+			r.ID = vm.conn.VM_BeginInvokeMethod (thread.Id, method.Id, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), vm.EncodeValues (arguments), f, InvokeCB, r);
+
+			return r;
+		}
+
+		// This is called when the result of an invoke is received
+		static void InvokeCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
+			InvokeAsyncResult r = (InvokeAsyncResult)state;
+
+			if (error != 0) {
+				r.ErrorCode = error;
+			} else {
+				r.Value = v;
+				r.Exception = exc;
+			}
+
+			r.IsCompleted = true;
+			((ManualResetEvent)r.AsyncWaitHandle).Set ();
+
+			if (r.Callback != null)
+				r.Callback.BeginInvoke (r, null, null);
+		}
+
+	    internal static Value EndInvokeMethodInternal (IAsyncResult asyncResult) {
+			if (asyncResult == null)
+				throw new ArgumentNullException ("asyncResult");
+
+			InvokeAsyncResult r = (InvokeAsyncResult)asyncResult;
+
+			if (!r.IsCompleted)
+				r.AsyncWaitHandle.WaitOne ();
+
+			if (r.ErrorCode != 0) {
+				try {
+					r.VM.ErrorHandler (null, new ErrorHandlerEventArgs () { ErrorCode = r.ErrorCode });
+				} catch (CommandException ex) {
+					if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
+						throw new ArgumentException ("Incorrect number or types of arguments", "arguments");
+					else
+						throw;
+				}
+				throw new NotImplementedException ();
+			} else {
+				if (r.Exception != null)
+					throw new InvocationException ((ObjectMirror)r.VM.DecodeValue (r.Exception));
+				else
+					return r.VM.DecodeValue (r.Value);
+			}
+		}
+
+	    internal static void EndInvokeMultipleInternal (IAsyncResult asyncResult) {
+			if (asyncResult == null)
+				throw new ArgumentNullException ("asyncResult");
+
+			InvokeAsyncResult r = (InvokeAsyncResult)asyncResult;
+
+			if (!r.IsCompleted)
+				r.AsyncWaitHandle.WaitOne ();
+		}
+
+		internal static Value InvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, Value this_obj, IList<Value> arguments, InvokeOptions options) {
+			return EndInvokeMethodInternal (BeginInvokeMethod (vm, thread, method, this_obj, arguments, options, null, null));
+		}
+
+		internal static void AbortInvoke (VirtualMachine vm, ThreadMirror thread, int id)
+		{
+			vm.conn.VM_AbortInvoke (thread.Id, id);
+		}
+
+		//
+		// Implementation of InvokeMultiple
+		//
+
+		internal static IInvokeAsyncResult BeginInvokeMultiple (VirtualMachine vm, ThreadMirror thread, MethodMirror[] methods, Value this_obj, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			if (thread == null)
+				throw new ArgumentNullException ("thread");
+			if (methods == null)
+				throw new ArgumentNullException ("methods");
+			foreach (var m in methods)
+				if (m == null)
+					throw new ArgumentNullException ("method");
+			if (arguments == null) {
+				arguments = new List<IList<Value>> ();
+				for (int i = 0; i < methods.Length; ++i)
+					arguments.Add (new Value [0]);
+			} else {
+				// FIXME: Not needed for property evaluation
+				throw new NotImplementedException ();
+			}
+			if (callback == null)
+				throw new ArgumentException ("A callback argument is required for this method.", "callback");
+
+			InvokeFlags f = InvokeFlags.NONE;
+
+			if ((options & InvokeOptions.DisableBreakpoints) != 0)
+				f |= InvokeFlags.DISABLE_BREAKPOINTS;
+			if ((options & InvokeOptions.SingleThreaded) != 0)
+				f |= InvokeFlags.SINGLE_THREADED;
+
+			InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback, NumPending = methods.Length, IsMultiple = true };
+
+			var mids = new long [methods.Length];
+			for (int i = 0; i < methods.Length; ++i)
+				mids [i] = methods [i].Id;
+			var args = new List<ValueImpl[]> ();
+			for (int i = 0; i < methods.Length; ++i)
+				args.Add (vm.EncodeValues (arguments [i]));
+			r.ID = vm.conn.VM_BeginInvokeMethods (thread.Id, mids, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), args, f, InvokeMultipleCB, r);
+
+			return r;
+		}
+
+		// This is called when the result of an invoke is received
+		static void InvokeMultipleCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) {
+			var r = (InvokeAsyncResult)state;
+
+			Interlocked.Decrement (ref r.NumPending);
+
+			if (r.NumPending == 0) {
+				r.IsCompleted = true;
+				((ManualResetEvent)r.AsyncWaitHandle).Set ();
+			}
+
+			// Have to pass another asyncresult to the callback since multiple threads can execute it concurrently with results of multiple invocations
+			var r2 = new InvokeAsyncResult { AsyncState = r.AsyncState, AsyncWaitHandle = null, VM = r.VM, Thread = r.Thread, Callback = r.Callback, IsCompleted = true };
+
+			if (error != 0) {
+				r2.ErrorCode = error;
+			} else {
+				r2.Value = v;
+				r2.Exception = exc;
+			}
+
+			r.Callback.BeginInvoke (r2, null, null);
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ParameterInfoMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ParameterInfoMirror.cs
new file mode 100644
index 0000000..32fb621
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ParameterInfoMirror.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+
+namespace Mono.Debugger.Soft
+{
+	public class ParameterInfoMirror : Mirror {
+
+		MethodMirror method;
+		TypeMirror type;
+		string name;
+		int pos;
+		ParameterAttributes attrs;
+
+		internal ParameterInfoMirror (MethodMirror method, int pos, TypeMirror type, string name, ParameterAttributes attrs) : base (method.VirtualMachine, 0) {
+			this.method = method;
+			this.pos = pos;
+			this.type = type;
+			this.name = name;
+			this.attrs = attrs;
+		}
+
+		public TypeMirror ParameterType {
+			get {
+				return type;
+			}
+		}
+
+		public MethodMirror Method {
+			get {
+				return method;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+
+		public int Position {
+			get {
+				return pos;
+			}
+		}
+
+		public ParameterAttributes Attributes {
+			get {
+				return attrs;
+			}
+		}
+
+		public bool IsRetval {
+			get {
+				return (Attributes & ParameterAttributes.Retval) != 0;
+			}
+		}
+
+		public override string ToString () {
+			return String.Format ("ParameterInfo ({0})", Name);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs
new file mode 100644
index 0000000..3fa359f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs
@@ -0,0 +1,65 @@
+// 
+// PointerValue.cs
+//  
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2012 Xamarin Inc.
+// 
+// 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;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * Represents a value of a pointer type in the debuggee
+	 */
+	public class PointerValue : Value {
+		TypeMirror type;
+		long addr;
+
+		public PointerValue (VirtualMachine vm, TypeMirror type, long addr) : base (vm, 0) {
+			this.type = type;
+			this.addr = addr;
+		}
+
+		public long Address {
+			get { return addr; }
+		}
+
+		public TypeMirror Type {
+			get { return type; }
+		}
+
+		public override bool Equals (object obj) {
+			if (obj != null && obj is PointerValue)
+				return addr == (obj as PointerValue).addr;
+			return base.Equals (obj);
+		}
+
+		public override int GetHashCode () {
+			return base.GetHashCode ();
+		}
+
+		public override string ToString () {
+			return string.Format ("PointerValue<({0}) 0x{1:x}>", type.CSharpName, addr);
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/PrimitiveValue.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/PrimitiveValue.cs
new file mode 100644
index 0000000..696f649
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/PrimitiveValue.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * Represents a value of a primitive type in the debuggee
+	 */
+	public class PrimitiveValue : Value {
+		object value;
+
+		public PrimitiveValue (VirtualMachine vm, object value) : base (vm, 0) {
+			this.value = value;
+		}
+
+		public object Value {
+			get {
+				return value;
+			}
+		}
+
+		public override bool Equals (object obj) {
+			if (value == obj)
+				return true;
+			if (obj != null && obj is PrimitiveValue)
+				return value == (obj as PrimitiveValue).Value;
+			return base.Equals (obj);
+		}
+
+		public override int GetHashCode () {
+			return base.GetHashCode ();
+		}
+
+		public override string ToString () {
+			object v = Value;
+
+			return "PrimitiveValue<" + (v != null ? v.ToString () : "(null)") + ">";
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, this, arguments, InvokeOptions.None);
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, this, arguments, options);
+		}
+
+		public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return ObjectMirror.BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
+		}
+
+		public Value EndInvokeMethod (IAsyncResult asyncResult) {
+			return ObjectMirror.EndInvokeMethodInternal (asyncResult);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/PropertyInfoMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/PropertyInfoMirror.cs
new file mode 100644
index 0000000..32f87d1
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/PropertyInfoMirror.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class PropertyInfoMirror : Mirror {
+
+		TypeMirror parent;
+		string name;
+		PropertyAttributes attrs;
+		MethodMirror get_method, set_method;
+		CustomAttributeDataMirror[] cattrs;
+		C.PropertyDefinition meta;
+
+		public PropertyInfoMirror (TypeMirror parent, long id, string name, MethodMirror get_method, MethodMirror set_method, PropertyAttributes attrs) : base (parent.VirtualMachine, id) {
+			this.parent = parent;
+			this.name = name;
+			this.attrs = attrs;
+			this.get_method = get_method;
+			this.set_method = set_method;
+		}
+
+		public TypeMirror DeclaringType {
+			get {
+				return parent;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+
+		public TypeMirror PropertyType {
+			get {
+				if (get_method != null)
+					return get_method.ReturnType;
+				else {
+					ParameterInfoMirror[] parameters = set_method.GetParameters ();
+					
+					return parameters [parameters.Length - 1].ParameterType;
+				}
+			}
+		}
+
+		public PropertyAttributes Attributes {
+			get {
+				return attrs;
+			}
+		}
+
+		public bool IsSpecialName {
+			get {return (Attributes & PropertyAttributes.SpecialName) != 0;}
+		}
+
+		public MethodMirror GetGetMethod ()
+		{
+			return GetGetMethod (false);
+		}
+
+		public MethodMirror GetGetMethod (bool nonPublic)
+		{
+			if (get_method != null && (nonPublic || get_method.IsPublic))
+				return get_method;
+			else
+				return null;
+		}
+
+		public MethodMirror GetSetMethod ()
+		{
+			return GetSetMethod (false);
+		}
+
+		public MethodMirror GetSetMethod (bool nonPublic)
+		{
+			if (set_method != null && (nonPublic || set_method.IsPublic))
+				return set_method;
+			else
+				return null;
+		}
+
+		public ParameterInfoMirror[] GetIndexParameters()
+		{
+			if (get_method != null)
+				return get_method.GetParameters ();
+			return new ParameterInfoMirror [0];
+		}
+
+		public C.PropertyDefinition Metadata {		
+			get {
+				if (parent.Metadata == null)
+					return null;
+				// FIXME: Speed this up
+				foreach (var def in parent.Metadata.Properties) {
+					if (def.Name == Name) {
+						meta = def;
+						break;
+					}
+				}
+				if (meta == null)
+					/* Shouldn't happen */
+					throw new NotImplementedException ();
+				return meta;
+			}
+		}
+
+		public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
+			return GetCAttrs (null, inherit);
+		}
+
+		public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
+			if (attributeType == null)
+				throw new ArgumentNullException ("attributeType");
+			return GetCAttrs (attributeType, inherit);
+		}
+
+		CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+			if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
+				cattrs = new CustomAttributeDataMirror [0];
+
+			// FIXME: Handle inherit
+			if (cattrs == null) {
+				CattrInfo[] info = vm.conn.Type_GetPropertyCustomAttributes (DeclaringType.Id, id, 0, false);
+				cattrs = CustomAttributeDataMirror.Create (vm, info);
+			}
+			var res = new List<CustomAttributeDataMirror> ();
+			foreach (var attr in cattrs)
+				if (type == null || attr.Constructor.DeclaringType == type)
+					res.Add (attr);
+			return res.ToArray ();
+		}
+	}
+}
+
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/StackFrame.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/StackFrame.cs
new file mode 100644
index 0000000..c0b4c7b
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/StackFrame.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Debugger.Soft
+{
+	public class StackFrame : Mirror
+	{
+		ThreadMirror thread;
+		MethodMirror method;
+		int il_offset;
+		Location location;
+		StackFrameFlags flags;
+
+		/*
+		 * FIXME: Decide on the way to request/handle debugging information:
+		 * - request the info in bulk for all frames/on demand for individual frames
+		 * - request the info from the runtime/request only the il offset, and compute
+		 *   everything else based on this info using the method debug info.
+		 */
+
+		internal StackFrame (VirtualMachine vm, long id, ThreadMirror thread, MethodMirror method, int il_offset, StackFrameFlags flags) : base (vm, id) {
+			this.thread = thread;
+			this.method = method;
+			this.il_offset = il_offset;
+			this.flags = flags;
+		}
+
+		public ThreadMirror Thread {
+			get {
+				return thread;
+			}
+		}
+
+		public MethodMirror Method {
+			get {
+				return method;
+			}
+		}
+
+		public Location Location {
+			get {
+				if (location == null) {
+					int line_number;
+					string src_file = null;
+					byte[] hash = null;
+					int column_number = 0;
+
+					if (il_offset == -1)
+						line_number = -1;
+					else
+						line_number = method.il_offset_to_line_number (il_offset, out src_file, out hash, out column_number);
+
+					location = new Location (vm, Method, 0, il_offset, src_file != null ? src_file : method.SourceFile, line_number, column_number, hash);
+				}
+				return location;
+			}
+		}
+
+		public string FileName {
+			get {
+				return Location.SourceFile;
+			}
+		}
+
+		public int ILOffset {
+			get {
+				return Location.ILOffset;
+			}
+		}
+
+		public int LineNumber {
+			get {
+				return Location.LineNumber;
+			}
+		}
+
+		public int ColumnNumber {
+			get {
+				return Location.ColumnNumber;
+			}
+		}
+
+		public bool IsDebuggerInvoke {
+			get {
+				return (flags & StackFrameFlags.DEBUGGER_INVOKE) != 0;
+			}
+		}
+
+		/*
+		 * Whenever this frame transitions to native code. The method associated
+		 * with the frame is either an InternalCall or a pinvoke method.
+		 */
+		public bool IsNativeTransition {
+			get {
+				return (flags & StackFrameFlags.NATIVE_TRANSITION) != 0;
+			}
+		}
+
+		public Value GetValue (ParameterInfoMirror param) {
+			if (param == null)
+				throw new ArgumentNullException ("param");
+			if (param.Method != Method)
+				throw new ArgumentException ("Parameter doesn't belong to this frame's method.");
+			if (param.IsRetval)
+				throw new ArgumentException ("Parameter represents the method return value.");
+
+			// FIXME: Liveness
+			// FIXME: Allow returning the frame return value if possible
+			return vm.DecodeValue (vm.conn.StackFrame_GetValues (thread.Id, Id, new int [] { (- param.Position) - 1 })[0]);
+		}
+
+		public Value GetValue (LocalVariable var) {
+			if (var == null)
+				throw new ArgumentNullException ("var");
+			if (var.Method != Method)
+				throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
+
+			// FIXME: Liveness
+			// FIXME: Check for return value
+			// FIXME: Allow returning the frame return value if possible
+			return vm.DecodeValue (vm.conn.StackFrame_GetValues (thread.Id, Id, new int [] { var.GetValueIndex } )[0]);
+		}
+
+		public Value[] GetValues (LocalVariable[] vars) {
+			if (vars == null)
+				throw new ArgumentNullException ("vars");
+			for (int i = 0; i < vars.Length; ++i) {
+				if (vars [i] == null)
+					throw new ArgumentNullException ("vars");
+				if (vars [i].Method != Method)
+					throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
+			}
+			int[] pos = new int [vars.Length];
+			for (int i = 0; i < vars.Length; ++i)
+				pos [i] = vars [i].GetValueIndex;
+			return vm.DecodeValues (vm.conn.StackFrame_GetValues (thread.Id, Id, pos));
+		}
+
+		public Value GetArgument (int pos) {
+			return GetValue (Method.GetParameters () [pos]);
+		}
+
+		public Value GetThis () {
+			return vm.DecodeValue (vm.conn.StackFrame_GetThis (thread.Id, Id));
+		}
+
+		public void SetValue (LocalVariable var, Value value) {
+			if (var == null)
+				throw new ArgumentNullException ("var");
+			if (var.Method != Method)
+				throw new ArgumentException ("Local variable doesn't belong to this frame's method.");
+			if (value == null)
+				throw new ArgumentNullException ("value");
+			CheckMirror (value);
+			// FIXME: Liveness
+			// FIXME: Check for return value
+			try {
+				vm.conn.StackFrame_SetValues (thread.Id, Id, new int [] { var.GetValueIndex }, new ValueImpl [] { vm.EncodeValue (value) });
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
+					throw new ArgumentException ("Value does not match the type of the local variable.");
+				else
+					throw;
+			}
+		}
+
+		public void SetValue (ParameterInfoMirror param, Value value) {
+			if (param == null)
+				throw new ArgumentNullException ("param");
+			if (param.Method != Method)
+				throw new ArgumentException ("Parameter doesn't belong to this frame's method.");
+			if (param.IsRetval)
+				throw new ArgumentException ("Parameter represents the method return value.");
+			if (value == null)
+				throw new ArgumentNullException ("value");
+			CheckMirror (value);
+
+			// FIXME: Liveness
+			// FIXME: Allow setting the frame return value if possible
+			try {
+				vm.conn.StackFrame_SetValues (thread.Id, Id, new int [] { (- param.Position) - 1 }, new ValueImpl [] { vm.EncodeValue (value) });
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
+					throw new ArgumentException ("Value does not match the type of the variable.");
+				else
+					throw;
+			}
+		}
+
+		public IList<LocalVariable> GetVisibleVariables () {
+			if (Location.ILOffset == -1)
+				throw new AbsentInformationException ();
+
+			return Method.GetLocals ().Where (l => l.LiveRangeStart <= location.ILOffset && l.LiveRangeEnd >= location.ILOffset).ToList ();
+		}
+
+		public LocalVariable GetVisibleVariableByName (string name) {
+			if (name == null)
+				throw new ArgumentNullException ("name");
+
+			if (Location.ILOffset == -1)
+				throw new AbsentInformationException ();
+
+			return Method.GetLocals ().Where (l => l.LiveRangeStart <= location.ILOffset && l.LiveRangeEnd >= location.ILOffset && l.Name == name).FirstOrDefault ();
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs
new file mode 100644
index 0000000..5fe3c8b
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs
@@ -0,0 +1,27 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class StepEvent : Event {
+		MethodMirror method;
+		long id, loc;
+
+		internal StepEvent (VirtualMachine vm, int req_id, long thread_id, long id, long loc) : base (EventType.Step, vm, req_id, thread_id) {
+			this.id = id;
+			this.loc = loc;
+		}
+
+		public MethodMirror Method {
+			get {
+				if (method == null)
+					method = vm.GetMethod (id);
+				return method;
+			}
+		}
+
+		public long Location {
+			get {
+				return loc;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs
new file mode 100644
index 0000000..035fbce
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public enum StepDepth {
+		Into = 0,
+		Over = 1,
+		Out = 2
+	}
+
+	public enum StepSize {
+		Min = 0,
+		Line = 1
+	}
+
+	/*
+	 * Filter which kinds of methods to skip during single stepping
+	 */
+	[Flags]
+	public enum StepFilter {
+		None = 0,
+		StaticCtor = 1,
+		/* Since protocol version 2.20 */
+		/* Methods which have the [DebuggerHidden] attribute */
+		/* Before protocol version 2.26, this includes [DebuggerStepThrough] as well */
+		DebuggerHidden = 2,
+		/* Since protocol version 2.26 */
+		/* Methods which have the [DebuggerStepThrough] attribute */
+		DebuggerStepThrough = 4,
+	}
+
+	public sealed class StepEventRequest : EventRequest {
+
+		ThreadMirror step_thread;
+		StepDepth depth;
+		StepSize size;
+		StepFilter filter;
+		
+		internal StepEventRequest (VirtualMachine vm, ThreadMirror thread) : base (vm, EventType.Step) {
+			if (thread == null)
+				throw new ArgumentNullException ("thread");
+			CheckMirror (vm, thread);
+			this.step_thread = thread;
+			Depth = StepDepth.Into;
+			Size = StepSize.Min;
+		}
+
+		public override void Enable () {
+			var mods = new List <Modifier> ();
+			mods.Add (new StepModifier () { Thread = step_thread.Id, Depth = (int)Depth, Size = (int)Size, Filter = (int)Filter });
+			SendReq (mods);
+		}
+
+		public new ThreadMirror Thread {
+			get {
+				return step_thread;
+			}
+		}
+
+		public StepDepth Depth {
+			get {
+				return depth;
+			}
+			set {
+				CheckDisabled ();
+				depth = value;
+			}
+		}
+
+		public StepSize Size {
+			get {
+				return size;
+			}
+			set {
+				CheckDisabled ();
+				size = value;
+			}
+		}
+
+		public StepFilter Filter {
+			get {
+				return filter;
+			}
+			set {
+				CheckDisabled ();
+				filter = value;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/StringMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/StringMirror.cs
new file mode 100644
index 0000000..dea12b5
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/StringMirror.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections;
+
+namespace Mono.Debugger.Soft
+{
+	public class StringMirror : ObjectMirror {
+
+		int length;
+
+		internal StringMirror (VirtualMachine vm, long id) : base (vm, id) {
+			length = -1;
+		}
+
+		internal StringMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id, type, domain) {
+			length = -1;
+		}
+
+		public string Value {
+			get {
+				return vm.conn.String_GetValue (id);
+			}
+		}
+
+		// Since protocol version 2.10
+		public int Length {
+			get {
+				if (length == -1)
+					length = vm.conn.String_GetLength (id);
+				return length;
+			}
+		}
+
+		// Since protocol version 2.10
+		public char[] GetChars (int index, int length) {
+			// re-ordered to avoid possible integer overflow
+			if (index > Length - length)
+				throw new ArgumentException (Locale.GetText (
+					"index and length do not specify a valid range in string."));
+
+			return vm.conn.String_GetChars (id, index, length);
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs
new file mode 100644
index 0000000..1db6037
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * Represents a valuetype value in the debuggee
+	 */
+	public class StructMirror : Value {
+	
+		TypeMirror type;
+		Value[] fields;
+
+		internal StructMirror (VirtualMachine vm, TypeMirror type, Value[] fields) : base (vm, 0) {
+			this.type = type;
+			this.fields = fields;
+		}
+
+		public TypeMirror Type {
+			get {
+				return type;
+			}
+		}
+
+		public Value[] Fields {
+			get {
+				return fields;
+			}
+		}
+
+		public Value this [String field] {
+			get {
+				FieldInfoMirror[] field_info = Type.GetFields ();
+				int nf = 0;
+				for (int i = 0; i < field_info.Length; ++i) {
+					if (!field_info [i].IsStatic) {
+						if (field_info [i].Name == field)
+							return Fields [nf];
+						nf++;
+					}
+				}
+				throw new ArgumentException ("Unknown struct field '" + field + "'.", "field");
+			}
+		}
+
+		internal void SetField (int index, Value value) {
+			fields [index] = value;
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, this, arguments, InvokeOptions.None);
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, this, arguments, options);
+		}
+
+		[Obsolete ("Use the overload without the 'vm' argument")]
+		public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return ObjectMirror.BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
+		}
+
+		public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return ObjectMirror.BeginInvokeMethod (vm, thread, method, this, arguments, options, callback, state);
+		}
+
+		public Value EndInvokeMethod (IAsyncResult asyncResult) {
+			return ObjectMirror.EndInvokeMethodInternal (asyncResult);
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/SuspendPolicy.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/SuspendPolicy.cs
new file mode 100644
index 0000000..b490ee7
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/SuspendPolicy.cs
@@ -0,0 +1,10 @@
+
+namespace Mono.Debugger.Soft
+{
+	// Keep it in sync with debugger-agent.h
+	public enum SuspendPolicy {
+		None = 0,
+		EventThread = 1,
+		All = 2
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadDeathEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadDeathEvent.cs
new file mode 100644
index 0000000..cf2c8ca
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadDeathEvent.cs
@@ -0,0 +1,8 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class ThreadDeathEvent : Event {
+		internal ThreadDeathEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadDeath, vm, req_id, id) {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadMirror.cs
new file mode 100644
index 0000000..1acab89
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadMirror.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public class ThreadMirror : ObjectMirror
+	{
+		string name;
+
+		internal ThreadMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		internal ThreadMirror (VirtualMachine vm, long id, TypeMirror type, AppDomainMirror domain) : base (vm, id, type, domain) {
+		}
+
+		// FIXME: Cache, invalidate when the thread/runtime is resumed
+		public StackFrame[] GetFrames () {
+			FrameInfo[] frame_info = vm.conn.Thread_GetFrameInfo (id, 0, -1);
+
+			var frames = new List<StackFrame> ();
+
+			for (int i = 0; i < frame_info.Length; ++i) {
+				FrameInfo info = (FrameInfo)frame_info [i];
+				MethodMirror method = vm.GetMethod (info.method);
+				var f = new StackFrame (vm, info.id, this, method, info.il_offset, info.flags);
+				if (!(f.IsNativeTransition && !NativeTransitions))
+					frames.Add (f);
+			}
+
+			return frames.ToArray ();
+	    }
+
+		public string Name {
+			get {
+				if (name == null)
+					name = vm.conn.Thread_GetName (id);
+				return name;
+			}
+	    }
+
+		public new long Id {
+			get {
+				return id;
+			}
+		}
+
+		public ThreadState ThreadState {
+			get {
+				return (ThreadState)vm.conn.Thread_GetState (id);
+			}
+		}
+
+		public bool IsThreadPoolThread {
+			get {
+				ThreadInfo info = vm.conn.Thread_GetInfo (id);
+
+				return info.is_thread_pool;
+			}
+		}
+
+		long? thread_id;
+		/*
+		 * Return a unique identifier for this thread, multiple ThreadMirror objects
+		 * may have the same ThreadId because of appdomains.
+		 */
+		public long ThreadId {
+			get {
+				if (thread_id == null)
+				 	thread_id = vm.conn.Thread_GetId (id);
+				return (long)thread_id;
+			}
+		}
+
+		/*
+		 * Return the system thread id (TID) for this thread, this id is not unique since
+		 * a newly started thread might reuse a dead thread's id.
+		 */
+		public long TID {
+			get {
+				return vm.conn.Thread_GetTID (id);
+			}
+		}
+
+		/*
+		 * Get/set whenever GetFrames () should return frames for managed-to-native
+		 * transitions, i.e frames whose IsNativeTransition property is set.
+		 * This is needed because some clients might not be able to deal with those
+		 * frames.
+		 */
+		public static bool NativeTransitions {
+			get; set;
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadStartEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadStartEvent.cs
new file mode 100644
index 0000000..92a1cef
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/ThreadStartEvent.cs
@@ -0,0 +1,8 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class ThreadStartEvent : Event {
+		internal ThreadStartEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadStart, vm, req_id, id) {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEvent.cs
new file mode 100644
index 0000000..cd2886f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEvent.cs
@@ -0,0 +1,20 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class TypeLoadEvent : Event {
+		TypeMirror type;
+		long id;
+
+		internal TypeLoadEvent (VirtualMachine vm, int req_id, long thread_id, long id) : base (EventType.TypeLoad, vm, req_id, thread_id) {
+			this.id = id;
+		}
+
+		public TypeMirror Type {
+			get {
+				if (type == null)
+					type = vm.GetType (id);
+				return type;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEventRequest.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEventRequest.cs
new file mode 100644
index 0000000..130742b
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEventRequest.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Mono.Debugger.Soft
+{
+	public sealed class TypeLoadEventRequest : EventRequest {
+		string[] sourceFiles;
+		string[] typeNames;
+
+		internal TypeLoadEventRequest (VirtualMachine vm) : base (vm, EventType.TypeLoad) {
+		}
+
+		public string[] SourceFileFilter {
+			get {
+				return sourceFiles;
+			}
+			set {
+				CheckDisabled ();
+				sourceFiles = value;
+			}
+		}
+
+		public string[] TypeNameFilter {
+			get {
+				return typeNames;
+			}
+			set {
+				CheckDisabled ();
+				typeNames = value;
+			}
+		}
+
+		public override void Enable () {
+			var mods = new List <Modifier> ();
+			if (SourceFileFilter != null && SourceFileFilter.Length != 0)
+				mods.Add (new SourceFileModifier () { SourceFiles = SourceFileFilter });
+			if (TypeNameFilter != null && TypeNameFilter.Length != 0)
+				mods.Add (new TypeNameModifier () { TypeNames = TypeNameFilter });
+			SendReq (mods);
+		}
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
new file mode 100644
index 0000000..125d780
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
@@ -0,0 +1,868 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using C = Mono.Cecil;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	/*
+	 * Represents a type in the remote virtual machine.
+	 * It might be better to make this a subclass of Type, but that could be
+	 * difficult as some of our methods like GetMethods () return Mirror objects.
+	 */
+	public class TypeMirror : Mirror
+	{
+		MethodMirror[] methods;
+		AssemblyMirror ass;
+		ModuleMirror module;
+		C.TypeDefinition meta;
+		FieldInfoMirror[] fields;
+		PropertyInfoMirror[] properties;
+		TypeInfo info;
+		TypeMirror base_type, element_type, gtd;
+		TypeMirror[] nested;
+		CustomAttributeDataMirror[] cattrs;
+		TypeMirror[] ifaces;
+		Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
+		TypeMirror[] type_args;
+		bool cached_base_type;
+		bool inited;
+
+		internal const BindingFlags DefaultBindingFlags =
+		BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
+
+		internal TypeMirror (VirtualMachine vm, long id) : base (vm, id) {
+		}
+
+		public string Name {
+			get {
+				return GetInfo ().name;
+			}
+		}
+
+		public string Namespace {
+			get {
+				return GetInfo ().ns;
+			}
+		}
+
+		public AssemblyMirror Assembly {
+			get {
+				if (ass == null) {
+					ass = vm.GetAssembly (GetInfo ().assembly);
+				}
+				return ass;
+			}
+		}
+
+		public ModuleMirror Module {
+			get {
+				if (module == null) {
+					module = vm.GetModule (GetInfo ().module);
+				}										   
+				return module;
+			}
+		}
+
+		public int MetadataToken {
+			get {
+				return GetInfo ().token;
+			}
+		}
+
+		public TypeAttributes Attributes {
+			get {
+				return (TypeAttributes)GetInfo ().attributes;
+			}
+		}
+
+		public TypeMirror BaseType {
+			get {
+				if (!cached_base_type) {
+					base_type = vm.GetType (GetInfo ().base_type);
+					cached_base_type = true;
+				}
+				return base_type;
+			}
+		}
+
+		public int GetArrayRank () {
+			GetInfo ();
+			if (info.rank == 0)
+				throw new ArgumentException ("Type must be an array type.");
+			return info.rank;
+		}
+
+
+		public bool IsAbstract {
+			get {
+				return (Attributes & TypeAttributes.Abstract) != 0;
+			}
+		}
+
+		public bool IsAnsiClass {
+			get {
+				return (Attributes & TypeAttributes.StringFormatMask)
+				== TypeAttributes.AnsiClass;
+			}
+		}
+
+		public bool IsArray {
+			get {
+				return IsArrayImpl ();
+			}
+		}
+
+		public bool IsAutoClass {
+			get {
+				return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass;
+			}
+		}
+
+		public bool IsAutoLayout {
+			get {
+				return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout;
+			}
+		}
+
+		public bool IsByRef {
+			get {
+				return IsByRefImpl ();
+			}
+		}
+
+		public bool IsClass {
+			get {
+				if (IsInterface)
+					return false;
+
+				return !IsValueType;
+			}
+		}
+
+		public bool IsCOMObject {
+			get {
+				return IsCOMObjectImpl ();
+			}
+		}
+
+		public bool IsContextful {
+			get {
+				return IsContextfulImpl ();
+			}
+		}
+
+		public bool IsEnum {
+			get {
+				return GetInfo ().is_enum;
+			}
+		}
+
+		public bool IsExplicitLayout {
+			get {
+				return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout;
+			}
+		}
+
+		public bool IsImport {
+			get {
+				return (Attributes & TypeAttributes.Import) != 0;
+			}
+		}
+
+		public bool IsInterface {
+			get {
+				return (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
+			}
+		}
+
+		public bool IsLayoutSequential {
+			get {
+				return (Attributes & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout;
+			}
+		}
+
+		public bool IsMarshalByRef {
+			get {
+				return IsMarshalByRefImpl ();
+			}
+		}
+
+		public bool IsNestedAssembly {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
+			}
+		}
+
+		public bool IsNestedFamANDAssem {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
+			}
+		}
+
+		public bool IsNestedFamily {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
+			}
+		}
+
+		public bool IsNestedFamORAssem {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem;
+			}
+		}
+
+		public bool IsNestedPrivate {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate;
+			}
+		}
+
+		public bool IsNestedPublic {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic;
+			}
+		}
+
+		public bool IsNotPublic {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic;
+			}
+		}
+
+		public bool IsPointer {
+			get {
+				return IsPointerImpl ();
+			}
+		}
+
+		public bool IsPrimitive {
+			get {
+				return IsPrimitiveImpl ();
+			}
+		}
+
+		public bool IsPublic {
+			get {
+				return (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public;
+			}
+		}
+
+		public bool IsSealed {
+			get {
+				return (Attributes & TypeAttributes.Sealed) != 0;
+			}
+		}
+
+		public bool IsSerializable {
+			get {
+				if ((Attributes & TypeAttributes.Serializable) != 0)
+					return true;
+
+				// FIXME:
+				return false;
+			}
+		}
+
+		public bool IsSpecialName {
+			get {
+				return (Attributes & TypeAttributes.SpecialName) != 0;
+			}
+		}
+
+		public bool IsUnicodeClass {
+			get {
+				return (Attributes & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass;
+			}
+		}
+
+		public bool IsValueType {
+			get {
+				return IsValueTypeImpl ();
+			}
+		}
+
+		public bool HasElementType {
+			get {
+				return HasElementTypeImpl ();
+			}
+		}
+
+		// Since protocol version 2.12
+		public bool IsGenericTypeDefinition {
+			get {
+				vm.CheckProtocolVersion (2, 12);
+				GetInfo ();
+				return info.is_gtd;
+			}
+		}
+
+		public bool IsGenericType {
+			get {
+				if (vm.Version.AtLeast (2, 12)) {
+					return GetInfo ().is_generic_type;
+				} else {
+					return Name.IndexOf ('`') != -1;
+				}
+			}
+		}
+
+		public TypeMirror GetElementType () {
+			GetInfo ();
+			if (element_type == null && info.element_type != 0)
+				element_type = vm.GetType (info.element_type);
+			return element_type;
+		}
+
+		public TypeMirror GetGenericTypeDefinition () {
+			vm.CheckProtocolVersion (2, 12);
+			GetInfo ();
+			if (gtd == null) {
+				if (info.gtd == 0)
+					throw new InvalidOperationException ();
+				gtd = vm.GetType (info.gtd);
+			}
+			return gtd;
+		}
+
+		// Since protocol version 2.15
+		public TypeMirror[] GetGenericArguments () {
+			vm.CheckProtocolVersion (2, 15);
+			if (type_args == null)
+				type_args = vm.GetTypes (GetInfo ().type_args);
+			return type_args;
+		}
+
+		public string FullName {
+			get {
+				return GetInfo ().full_name;
+			}
+		}
+
+		public string CSharpName {
+			get {
+				if (IsArray) {
+					if (GetArrayRank () == 1)
+						return GetElementType ().CSharpName + "[]";
+					else {
+						string ranks = "";
+						for (int i = 0; i < GetArrayRank (); ++i)
+							ranks += ',';
+						return GetElementType ().CSharpName + "[" + ranks + "]";
+					}
+				}
+				if (IsPrimitive) {
+					switch (Name) {
+					case "Byte":
+						return "byte";
+					case "Sbyte":
+						return "sbyte";
+					case "Char":
+						return "char";
+					case "UInt16":
+						return "ushort";
+					case "Int16":
+						return "short";
+					case "UInt32":
+						return "uint";
+					case "Int32":
+						return "int";
+					case "UInt64":
+						return "ulong";
+					case "Int64":
+						return "long";
+					case "Single":
+						return "float";
+					case "Double":
+						return "double";
+					case "Boolean":
+						return "bool";
+					default:
+						return FullName;
+					}
+				}
+				// FIXME: Only do this for real corlib types
+				if (Namespace == "System") {
+					string s = Name;
+					switch (s) {
+					case "Decimal":
+						return "decimal";
+					case "Object":
+						return "object";
+					case "String":
+						return "string";
+					default:
+						return FullName;
+					}
+				} else {
+					return FullName;
+				}
+			}
+		}
+
+		public MethodMirror[] GetMethods () {
+			if (methods == null) {
+				long[] ids = vm.conn.Type_GetMethods (id);
+				MethodMirror[] m = new MethodMirror [ids.Length];
+				for (int i = 0; i < ids.Length; ++i) {
+					m [i] = vm.GetMethod (ids [i]);
+				}
+				methods = m;
+			}
+			return methods;
+		}
+
+		// FIXME: Sync this with Type
+		public MethodMirror GetMethod (string name) {
+			foreach (var m in GetMethods ())
+				if (m.Name == name)
+					return m;
+			return null;
+		}
+
+		public FieldInfoMirror[] GetFields () {
+			if (fields != null)
+				return fields;
+
+			string[] names;
+			long[] types;
+			int[] attrs;
+			long[] ids = vm.conn.Type_GetFields (id, out names, out types, out attrs);
+
+			FieldInfoMirror[] res = new FieldInfoMirror [ids.Length];
+			for (int i = 0; i < res.Length; ++i)
+				res [i] = new FieldInfoMirror (this, ids [i], names [i], vm.GetType (types [i]), (FieldAttributes)attrs [i]);
+
+			fields = res;
+			return fields;
+		}
+
+		public FieldInfoMirror GetField (string name) {
+			if (name == null)
+				throw new ArgumentNullException ("name");
+			foreach (var f in GetFields ())
+				if (f.Name == name)
+					return f;
+			return null;
+		}
+
+		public TypeMirror[] GetNestedTypes ()
+		{
+			return GetNestedTypes (DefaultBindingFlags);
+		}
+
+		public TypeMirror[] GetNestedTypes (BindingFlags bindingAttr) {
+			if (nested != null)
+				return nested;
+
+			// FIXME: bindingAttr
+			GetInfo ();
+			var arr = new TypeMirror [info.nested.Length];
+			for (int i = 0; i < arr.Length; ++i)
+				arr [i] = vm.GetType (info.nested [i]);
+			nested = arr;
+
+			return nested;
+		}
+
+		public PropertyInfoMirror[] GetProperties () {
+			return GetProperties (DefaultBindingFlags);
+		}
+
+		public PropertyInfoMirror[] GetProperties (BindingFlags bindingAttr) {
+			if (properties != null)
+				return properties;
+
+			PropInfo[] info = vm.conn.Type_GetProperties (id);
+
+			PropertyInfoMirror[] res = new PropertyInfoMirror [info.Length];
+			for (int i = 0; i < res.Length; ++i)
+				res [i] = new PropertyInfoMirror (this, info [i].id, info [i].name, vm.GetMethod (info [i].get_method), vm.GetMethod (info [i].set_method), (PropertyAttributes)info [i].attrs);
+
+			properties = res;
+			return properties;
+		}
+
+		public PropertyInfoMirror GetProperty (string name) {
+			if (name == null)
+				throw new ArgumentNullException ("name");
+			foreach (var p in GetProperties ())
+				if (p.Name == name)
+					return p;
+			return null;
+		}
+
+		public virtual bool IsAssignableFrom (TypeMirror c) {
+			if (c == null)
+				throw new ArgumentNullException ("c");
+
+			CheckMirror (c);
+
+			// This is complex so do it in the debuggee
+			return vm.conn.Type_IsAssignableFrom (id, c.Id);
+		}
+
+		public Value GetValue (FieldInfoMirror field) {
+			return GetValues (new FieldInfoMirror [] { field }) [0];
+		}
+
+		public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
+			if (fields == null)
+				throw new ArgumentNullException ("fields");
+			foreach (FieldInfoMirror f in fields) {
+				if (f == null)
+					throw new ArgumentNullException ("field");
+				CheckMirror (f);
+			}
+			long[] ids = new long [fields.Count];
+			for (int i = 0; i < fields.Count; ++i)
+				ids [i] = fields [i].Id;
+			try {
+				return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread !=  null ? thread.Id : 0));
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
+					throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
+				else
+					throw;
+			}
+		}
+
+		public Value[] GetValues (IList<FieldInfoMirror> fields) {
+			return GetValues (fields, null);
+		}
+
+		/*
+		 * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
+		 */
+		public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
+			if (thread == null)
+				throw new ArgumentNullException ("thread");
+			CheckMirror (thread);
+			return GetValues (new FieldInfoMirror [] { field }, thread) [0];
+		}
+
+		public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
+			if (fields == null)
+				throw new ArgumentNullException ("fields");
+			if (values == null)
+				throw new ArgumentNullException ("values");
+			foreach (FieldInfoMirror f in fields) {
+				if (f == null)
+					throw new ArgumentNullException ("field");
+				CheckMirror (f);
+			}
+			foreach (Value v in values) {
+				if (v == null)
+					throw new ArgumentNullException ("values");
+				CheckMirror (v);
+			}
+			long[] ids = new long [fields.Count];
+			for (int i = 0; i < fields.Count; ++i)
+				ids [i] = fields [i].Id;
+			try {
+				vm.conn.Type_SetValues (id, ids, vm.EncodeValues (values));
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
+					throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
+				else
+					throw;
+			}
+		}
+
+		public void SetValue (FieldInfoMirror field, Value value) {
+			SetValues (new FieldInfoMirror [] { field }, new Value [] { value });
+		}
+
+		public ObjectMirror GetTypeObject () {
+			return vm.GetObject (vm.conn.Type_GetObject (id));
+		}
+
+		/*
+		 * Return a list of source files without path info, where methods of 
+		 * this type are defined. Return an empty list if the information is not 
+		 * available. 
+		 * This can be used by a debugger to find out which types occur in a 
+		 * given source file, to filter the list of methods whose locations
+		 * have to be checked when placing breakpoints.
+		 */
+		public string[] GetSourceFiles () {
+			return GetSourceFiles (false);
+		}
+
+		string[] source_files;
+		string[] source_files_full_path;
+		public string[] GetSourceFiles (bool returnFullPaths) {
+			string[] res = returnFullPaths ? source_files_full_path : source_files;
+			if (res == null) {
+				res = vm.conn.Type_GetSourceFiles (id, returnFullPaths);
+				if (returnFullPaths)
+					source_files_full_path = res;
+				else
+					source_files = res;
+			}
+			return res;
+		}
+
+		public C.TypeDefinition Metadata {
+			get {
+				if (meta == null) {
+					if (Assembly.Metadata == null || MetadataToken == 0)
+						return null;
+					meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupToken (MetadataToken);
+				}
+				return meta;
+			}
+		}
+
+		TypeInfo GetInfo () {
+			if (info == null)
+				info = vm.conn.Type_GetInfo (id);
+			return info;
+		}
+
+		protected virtual TypeAttributes GetAttributeFlagsImpl () {
+			return (TypeAttributes)GetInfo ().attributes;
+		}
+
+		protected virtual bool HasElementTypeImpl () {
+			return IsArray || IsByRef || IsPointer;
+		}
+
+		protected virtual bool IsArrayImpl () {
+			return GetInfo ().rank > 0;
+		}
+
+		protected virtual bool IsByRefImpl () {
+			return GetInfo ().is_byref;
+		}
+
+		protected virtual bool IsCOMObjectImpl () {
+			return false;
+		}
+
+		protected virtual bool IsPointerImpl () {
+			return GetInfo ().is_pointer;
+		}
+
+		protected virtual bool IsPrimitiveImpl () {
+			return GetInfo ().is_primitive;
+		}
+
+		protected virtual bool IsValueTypeImpl ()
+		{
+			return GetInfo ().is_valuetype;
+		}
+		
+		protected virtual bool IsContextfulImpl ()
+		{
+			// FIXME:
+			return false;
+		}
+
+		protected virtual bool IsMarshalByRefImpl ()
+		{
+			// FIXME:
+			return false;
+		}
+
+		// Same as Enum.GetUnderlyingType ()
+		public TypeMirror EnumUnderlyingType {
+			get {
+				if (!IsEnum)
+					throw new ArgumentException ("Type is not an enum type.");
+				foreach (FieldInfoMirror f in GetFields ()) {
+					if (!f.IsStatic)
+						return f.FieldType;
+				}
+				throw new NotImplementedException ();
+			}
+		}
+
+		/*
+		 * Creating the custom attributes themselves could modify the behavior of the
+		 * debuggee, so we return objects similar to the CustomAttributeData objects
+		 * used by the reflection-only functionality on .net.
+		 */
+		public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
+			return GetCustomAttrs (null, inherit);
+		}
+
+		public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
+			if (attributeType == null)
+				throw new ArgumentNullException ("attributeType");
+			return GetCustomAttrs (attributeType, inherit);
+		}
+
+		void AppendCustomAttrs (IList<CustomAttributeDataMirror> attrs, TypeMirror type, bool inherit)
+		{
+			if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
+				cattrs = new CustomAttributeDataMirror [0];
+
+			if (cattrs == null) {
+				CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
+				cattrs = CustomAttributeDataMirror.Create (vm, info);
+			}
+
+			foreach (var attr in cattrs) {
+				if (type == null || attr.Constructor.DeclaringType == type)
+					attrs.Add (attr);
+			}
+
+			if (inherit && BaseType != null)
+				BaseType.AppendCustomAttrs (attrs, type, inherit);
+		}
+
+		CustomAttributeDataMirror[] GetCustomAttrs (TypeMirror type, bool inherit) {
+			var attrs = new List<CustomAttributeDataMirror> ();
+			AppendCustomAttrs (attrs, type, inherit);
+			return attrs.ToArray ();
+		}
+
+		public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
+			if (vm.conn.Version.AtLeast (2, 6)) {
+				long[] ids = vm.conn.Type_GetMethodsByNameFlags (id, name, (int)flags, ignoreCase);
+				MethodMirror[] m = new MethodMirror [ids.Length];
+				for (int i = 0; i < ids.Length; ++i)
+					m [i] = vm.GetMethod (ids [i]);
+				return m;
+			} else {
+				if ((flags & BindingFlags.IgnoreCase) != 0) {
+					flags &= ~BindingFlags.IgnoreCase;
+					ignoreCase = true;
+				}
+				
+				if (flags == BindingFlags.Default)
+					flags = BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static;
+				
+				MethodAttributes access = (MethodAttributes) 0;
+				bool matchInstance = false;
+				bool matchStatic = false;
+				
+				if ((flags & BindingFlags.NonPublic) != 0) {
+					access |= MethodAttributes.Private;
+					flags &= ~BindingFlags.NonPublic;
+				}
+				if ((flags & BindingFlags.Public) != 0) {
+					access |= MethodAttributes.Public;
+					flags &= ~BindingFlags.Public;
+				}
+				if ((flags & BindingFlags.Instance) != 0) {
+					flags &= ~BindingFlags.Instance;
+					matchInstance = true;
+				}
+				if ((flags & BindingFlags.Static) != 0) {
+					flags &= ~BindingFlags.Static;
+					matchStatic = true;
+				}
+				
+				if ((int) flags != 0)
+					throw new NotImplementedException ();
+				
+				var res = new List<MethodMirror> ();
+				foreach (MethodMirror m in GetMethods ()) {
+					if ((m.Attributes & access) == (MethodAttributes) 0)
+						continue;
+					
+					if (!((matchStatic && m.IsStatic) || (matchInstance && !m.IsStatic)))
+						continue;
+					
+					if ((!ignoreCase && m.Name == name) || (ignoreCase && m.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase)))
+						res.Add (m);
+				}
+				return res.ToArray ();
+			}
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
+		}
+
+		public Value InvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
+		}
+
+		[Obsolete ("Use the overload without the 'vm' argument")]
+		public IAsyncResult BeginInvokeMethod (VirtualMachine vm, ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
+		}
+
+		public IAsyncResult BeginInvokeMethod (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options, AsyncCallback callback, object state) {
+			return ObjectMirror.BeginInvokeMethod (vm, thread, method, null, arguments, options, callback, state);
+		}
+
+		public Value EndInvokeMethod (IAsyncResult asyncResult) {
+			return ObjectMirror.EndInvokeMethodInternal (asyncResult);
+		}
+
+		public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None);
+		}			
+
+		public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options) {
+			return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, options);
+		}
+
+		// Since protocol version 2.11
+		public TypeMirror[] GetInterfaces () {
+			if (ifaces == null)
+				ifaces = vm.GetTypes (vm.conn.Type_GetInterfaces (id));
+			return ifaces;
+		}
+
+		// Since protocol version 2.11
+		public InterfaceMappingMirror GetInterfaceMap (TypeMirror interfaceType) {
+			if (interfaceType == null)
+				throw new ArgumentNullException ("interfaceType");
+			if (!interfaceType.IsInterface)
+				throw new ArgumentException ("Argument must be an interface.", "interfaceType");
+			if (IsInterface)
+				throw new ArgumentException ("'this' type cannot be an interface itself");
+
+			if (iface_map == null) {
+				// Query the info in bulk
+				GetInterfaces ();
+				var ids = new long [ifaces.Length];
+				for (int i = 0; i < ifaces.Length; ++i)
+					ids [i] = ifaces [i].Id;
+
+				var ifacemap = vm.conn.Type_GetInterfaceMap (id, ids);
+
+				var imap = new Dictionary<TypeMirror, InterfaceMappingMirror> ();
+				for (int i = 0; i < ifacemap.Length; ++i) {
+					IfaceMapInfo info = ifacemap [i];
+
+					MethodMirror[] imethods = new MethodMirror [info.iface_methods.Length];
+					for (int j = 0; j < info.iface_methods.Length; ++j)
+						imethods [j] = vm.GetMethod (info.iface_methods [j]);
+
+					MethodMirror[] tmethods = new MethodMirror [info.iface_methods.Length];
+					for (int j = 0; j < info.target_methods.Length; ++j)
+						tmethods [j] = vm.GetMethod (info.target_methods [j]);
+
+					InterfaceMappingMirror map = new InterfaceMappingMirror (vm, this, vm.GetType (info.iface_id), imethods, tmethods);
+
+					imap [map.InterfaceType] = map;
+				}
+
+				iface_map = imap;
+			}
+
+			InterfaceMappingMirror res;
+			if (!iface_map.TryGetValue (interfaceType, out res))
+				throw new ArgumentException ("Interface not found", "interfaceType");
+			return res;
+		}
+
+		// Return whenever the type initializer of this type has ran
+		// Since protocol version 2.23
+		public bool IsInitialized {
+			get {
+				vm.CheckProtocolVersion (2, 23);
+				if (!inited)
+					inited = vm.conn.Type_IsInitialized (id);
+				return inited;
+			}
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/UserBreakEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/UserBreakEvent.cs
new file mode 100644
index 0000000..4303dbc
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/UserBreakEvent.cs
@@ -0,0 +1,8 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class UserBreakEvent : Event {
+		internal UserBreakEvent (VirtualMachine vm, int req_id, long thread_id) : base (EventType.UserBreak, vm, req_id, thread_id) {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/UserLogEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/UserLogEvent.cs
new file mode 100644
index 0000000..4b4b4b4
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/UserLogEvent.cs
@@ -0,0 +1,33 @@
+
+namespace Mono.Debugger.Soft
+{
+	public class UserLogEvent : Event {
+
+		int level;
+		string category, message;
+
+		internal UserLogEvent (VirtualMachine vm, int req_id, long thread_id, int level, string category, string message) : base (EventType.UserLog, vm, req_id, thread_id) {
+			this.level = level;
+			this.category = category;
+			this.message = message;
+		}
+
+		public int Level {
+			get {
+				return level;
+			}
+		}
+
+		public string Category {
+			get {
+				return category;
+			}
+		}
+
+		public string Message {
+			get {
+				return message;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs
new file mode 100644
index 0000000..18eeb92
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class VMDeathEvent : Event
+	{
+		public VMDeathEvent (VirtualMachine vm, int req_id) : base (EventType.VMDeath, vm, req_id, -1) {
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectEvent.cs
new file mode 100644
index 0000000..7157fa2
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectEvent.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class VMDisconnectEvent : Event
+	{
+		public VMDisconnectEvent (VirtualMachine vm, int req_id) : base (EventType.VMDisconnect, vm, req_id, -1) {
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectedException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectedException.cs
new file mode 100644
index 0000000..d26b1be
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectedException.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class VMDisconnectedException : Exception {
+		
+		public VMDisconnectedException () : base () {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VMMismatchException.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMMismatchException.cs
new file mode 100644
index 0000000..2d3fd81
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMMismatchException.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class VMMismatchException : Exception
+	{
+		public VMMismatchException () : base () {
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VMStartEvent.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMStartEvent.cs
new file mode 100644
index 0000000..f694828
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VMStartEvent.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+	public class VMStartEvent : Event
+	{
+		public VMStartEvent (VirtualMachine vm, int req_id, long thread_id) : base (EventType.VMStart, vm, req_id, thread_id) {
+		}
+    }
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/Value.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/Value.cs
new file mode 100644
index 0000000..67e187b
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/Value.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+	public abstract class Value : Mirror {
+
+		// FIXME: Add a 'Value' field
+
+		internal Value (VirtualMachine vm, long id) : base (vm, id) {
+		}
+	}
+}
+
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
new file mode 100644
index 0000000..b77458b
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
@@ -0,0 +1,701 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Net;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using Mono.Cecil.Metadata;
+
+namespace Mono.Debugger.Soft
+{
+	public class VirtualMachine : Mirror
+	{
+		Queue queue;
+		object queue_monitor;
+		object startup_monitor;
+		AppDomainMirror root_domain;
+		Dictionary<int, EventRequest> requests;
+		ITargetProcess process;
+
+		internal Connection conn;
+
+		VersionInfo version;
+
+		internal VirtualMachine (ITargetProcess process, Connection conn) : base () {
+			SetVirtualMachine (this);
+			queue = new Queue ();
+			queue_monitor = new Object ();
+			startup_monitor = new Object ();
+			requests = new Dictionary <int, EventRequest> ();
+			this.conn = conn;
+			this.process = process;
+			conn.ErrorHandler += ErrorHandler;
+		}
+
+		// The standard output of the process is available normally through Process
+		public StreamReader StandardOutput { get; set; }
+		public StreamReader StandardError { get; set; }
+
+		
+		public Process Process {
+			get {
+				ProcessWrapper pw = process as ProcessWrapper;
+				if (pw == null)
+				    throw new InvalidOperationException ("Process instance not available");
+				return pw.Process;
+			}
+		}
+
+		public ITargetProcess TargetProcess {
+			get {
+				return process;
+			}
+		}
+
+		public AppDomainMirror RootDomain {
+			get {
+				return root_domain;
+			}
+	    }
+
+		public EndPoint EndPoint {
+			get {
+				var tcpConn = conn as TcpConnection;
+				if (tcpConn != null)
+					return tcpConn.EndPoint;
+				return null;
+			}
+		}
+
+		public VersionInfo Version {
+			get {
+				return version;
+			}
+		}
+
+		EventSet current_es;
+		int current_es_index;
+
+		/*
+		 * It is impossible to determine when to resume when using this method, since
+		 * the debuggee is suspended only once per event-set, not event.
+		 */
+		[Obsolete ("Use GetNextEventSet () instead")]
+		public Event GetNextEvent () {
+			lock (queue_monitor) {
+				if (current_es == null || current_es_index == current_es.Events.Length) {
+					if (queue.Count == 0)
+						Monitor.Wait (queue_monitor);
+					current_es = (EventSet)queue.Dequeue ();
+					current_es_index = 0;
+				}
+				return current_es.Events [current_es_index ++];
+			}
+		}
+
+		public Event GetNextEvent (int timeout) {
+			throw new NotImplementedException ();
+		}
+
+		public EventSet GetNextEventSet () {
+			lock (queue_monitor) {
+				if (queue.Count == 0)
+					Monitor.Wait (queue_monitor);
+
+				current_es = null;
+				current_es_index = 0;
+
+				return (EventSet)queue.Dequeue ();
+			}
+		}
+
+		[Obsolete ("Use GetNextEventSet () instead")]
+		public T GetNextEvent<T> () where T : Event {
+			return GetNextEvent () as T;
+		}
+
+		public void Suspend () {
+			conn.VM_Suspend ();
+	    }
+
+		public void Resume () {
+			try {
+				conn.VM_Resume ();
+			} catch (CommandException ex) {
+				if (ex.ErrorCode == ErrorCode.NOT_SUSPENDED)
+					throw new VMNotSuspendedException ();
+				else
+					throw;
+			}
+	    }
+
+		public void Exit (int exitCode) {
+			conn.VM_Exit (exitCode);
+		}
+
+		public void Detach () {
+			conn.VM_Dispose ();
+			conn.Close ();
+			notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null);
+		}
+
+		[Obsolete ("This method was poorly named; use the Detach() method instead")]
+		public void Dispose ()
+		{
+			Detach ();
+		}
+
+		public void ForceDisconnect ()
+		{
+			conn.ForceDisconnect ();
+		}
+
+		public IList<ThreadMirror> GetThreads () {
+			long[] ids = vm.conn.VM_GetThreads ();
+			ThreadMirror[] res = new ThreadMirror [ids.Length];
+			for (int i = 0; i < ids.Length; ++i)
+				res [i] = GetThread (ids [i]);
+			return res;
+		}
+
+		// Same as the mirrorOf methods in JDI
+		public PrimitiveValue CreateValue (object value) {
+			if (value == null)
+				return new PrimitiveValue (vm, null);
+
+			if (!value.GetType ().IsPrimitive)
+				throw new ArgumentException ("value must be of a primitive type instead of '" + value.GetType () + "'", "value");
+
+			return new PrimitiveValue (vm, value);
+		}
+
+		public EnumMirror CreateEnumMirror (TypeMirror type, PrimitiveValue value) {
+			return new EnumMirror (this, type, value);
+		}
+
+		//
+		// Enable send and receive timeouts on the connection and send a keepalive event
+		// every 'keepalive_interval' milliseconds.
+		//
+
+		public void SetSocketTimeouts (int send_timeout, int receive_timeout, int keepalive_interval)
+		{
+			conn.SetSocketTimeouts (send_timeout, receive_timeout, keepalive_interval);
+		}
+
+		//
+		// Methods to create event request objects
+		//
+		public BreakpointEventRequest CreateBreakpointRequest (MethodMirror method, long il_offset) {
+			return new BreakpointEventRequest (this, method, il_offset);
+		}
+
+		public BreakpointEventRequest CreateBreakpointRequest (Location loc) {
+			if (loc == null)
+				throw new ArgumentNullException ("loc");
+			CheckMirror (loc);
+			return new BreakpointEventRequest (this, loc.Method, loc.ILOffset);
+		}
+
+		public StepEventRequest CreateStepRequest (ThreadMirror thread) {
+			return new StepEventRequest (this, thread);
+		}
+
+		public MethodEntryEventRequest CreateMethodEntryRequest () {
+			return new MethodEntryEventRequest (this);
+		}
+
+		public MethodExitEventRequest CreateMethodExitRequest () {
+			return new MethodExitEventRequest (this);
+		}
+
+		public ExceptionEventRequest CreateExceptionRequest (TypeMirror exc_type) {
+			return new ExceptionEventRequest (this, exc_type, true, true);
+		}
+
+		public ExceptionEventRequest CreateExceptionRequest (TypeMirror exc_type, bool caught, bool uncaught) {
+			return new ExceptionEventRequest (this, exc_type, caught, uncaught);
+		}
+
+		public AssemblyLoadEventRequest CreateAssemblyLoadRequest () {
+			return new AssemblyLoadEventRequest (this);
+		}
+
+		public TypeLoadEventRequest CreateTypeLoadRequest () {
+			return new TypeLoadEventRequest (this);
+		}
+
+		public void EnableEvents (params EventType[] events) {
+			foreach (EventType etype in events) {
+				if (etype == EventType.Breakpoint)
+					throw new ArgumentException ("Breakpoint events cannot be requested using EnableEvents", "events");
+				conn.EnableEvent (etype, SuspendPolicy.All, null);
+			}
+		}
+
+		public BreakpointEventRequest SetBreakpoint (MethodMirror method, long il_offset) {
+			BreakpointEventRequest req = CreateBreakpointRequest (method, il_offset);
+
+			req.Enable ();
+
+			return req;
+		}
+
+		public void ClearAllBreakpoints () {
+			conn.ClearAllBreakpoints ();
+		}
+		
+		public void Disconnect () {
+			conn.Close ();
+		}
+
+		//
+		// Return a list of TypeMirror objects for all loaded types which reference the
+		// source file FNAME. Might return false positives.
+		// Since protocol version 2.7.
+		//
+		public IList<TypeMirror> GetTypesForSourceFile (string fname, bool ignoreCase) {
+			long[] ids = conn.VM_GetTypesForSourceFile (fname, ignoreCase);
+			var res = new TypeMirror [ids.Length];
+			for (int i = 0; i < ids.Length; ++i)
+				res [i] = GetType (ids [i]);
+			return res;
+		}
+
+		//
+		// Return a list of TypeMirror objects for all loaded types named 'NAME'.
+		// NAME should be in the the same for as with Assembly.GetType ().
+		// Since protocol version 2.9.
+		//
+		public IList<TypeMirror> GetTypes (string name, bool ignoreCase) {
+			long[] ids = conn.VM_GetTypes (name, ignoreCase);
+			var res = new TypeMirror [ids.Length];
+			for (int i = 0; i < ids.Length; ++i)
+				res [i] = GetType (ids [i]);
+			return res;
+		}
+		
+		internal void queue_event_set (EventSet es) {
+			lock (queue_monitor) {
+				queue.Enqueue (es);
+				Monitor.Pulse (queue_monitor);
+			}
+		}
+
+		internal void ErrorHandler (object sender, ErrorHandlerEventArgs args) {
+			switch (args.ErrorCode) {
+			case ErrorCode.INVALID_OBJECT:
+				throw new ObjectCollectedException ();
+			case ErrorCode.INVALID_FRAMEID:
+				throw new InvalidStackFrameException ();
+			case ErrorCode.NOT_SUSPENDED:
+				throw new VMNotSuspendedException ();
+			case ErrorCode.NOT_IMPLEMENTED:
+				throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
+			case ErrorCode.ABSENT_INFORMATION:
+				throw new AbsentInformationException ();
+			case ErrorCode.NO_SEQ_POINT_AT_IL_OFFSET:
+				throw new ArgumentException ("Cannot set breakpoint on the specified IL offset.");
+			default:
+				throw new CommandException (args.ErrorCode);
+			}
+		}
+
+		/* Wait for the debuggee to start up and connect to it */
+		internal void connect () {
+			conn.Connect ();
+
+			// Test the connection
+			version = conn.Version;
+			if (version.MajorVersion != Connection.MAJOR_VERSION)
+				throw new NotSupportedException (String.Format ("The debuggee implements protocol version {0}.{1}, while {2}.{3} is required.", version.MajorVersion, version.MinorVersion, Connection.MAJOR_VERSION, Connection.MINOR_VERSION));
+
+			long root_domain_id = conn.RootDomain;
+			root_domain = GetDomain (root_domain_id);
+		}
+
+		internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri) {
+			//Console.WriteLine ("Event: " + evtype + "(" + vm_uri + ")");
+
+			switch (evtype) {
+			case EventType.VMStart:
+				/* Notify the main thread that the debuggee started up */
+				lock (startup_monitor) {
+					Monitor.Pulse (startup_monitor);
+				}
+				queue_event_set (new EventSet (this, spolicy, new Event[] { new VMStartEvent (vm, req_id, thread_id) }));
+				break;
+			case EventType.VMDeath:
+				queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id) }));
+				break;
+			case EventType.VMDisconnect:
+				queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDisconnectEvent (vm, req_id) }));
+				break;
+			default:
+				throw new Exception ();
+			}
+		}
+
+		//
+		// Methods to create instances of mirror objects
+		//
+
+		/*
+		class MirrorCache<T> {
+			static Dictionary <long, T> mirrors;
+			static object mirror_lock = new object ();
+
+			internal static T GetMirror (VirtualMachine vm, long id) {
+				lock (mirror_lock) {
+				if (mirrors == null)
+					mirrors = new Dictionary <long, T> ();
+				T obj;
+				if (!mirrors.TryGetValue (id, out obj)) {
+					obj = CreateMirror (vm, id);
+					mirrors [id] = obj;
+				}
+				return obj;
+				}
+			}
+
+			internal static T CreateMirror (VirtualMachine vm, long id) {
+			}
+		}
+		*/
+
+		// FIXME: When to remove items from the cache ?
+
+		Dictionary <long, MethodMirror> methods;
+		object methods_lock = new object ();
+
+		internal MethodMirror GetMethod (long id) {
+			lock (methods_lock) {
+				if (methods == null)
+					methods = new Dictionary <long, MethodMirror> ();
+				MethodMirror obj;
+				if (id == 0)
+					return null;
+				if (!methods.TryGetValue (id, out obj)) {
+					obj = new MethodMirror (this, id);
+					methods [id] = obj;
+				}
+				return obj;
+			}
+	    }
+
+		Dictionary <long, AssemblyMirror> assemblies;
+		object assemblies_lock = new object ();
+
+		internal AssemblyMirror GetAssembly (long id) {
+			lock (assemblies_lock) {
+				if (assemblies == null)
+					assemblies = new Dictionary <long, AssemblyMirror> ();
+				AssemblyMirror obj;
+				if (id == 0)
+					return null;
+				if (!assemblies.TryGetValue (id, out obj)) {
+					obj = new AssemblyMirror (this, id);
+					assemblies [id] = obj;
+				}
+				return obj;
+			}
+	    }
+
+		Dictionary <long, ModuleMirror> modules;
+		object modules_lock = new object ();
+
+		internal ModuleMirror GetModule (long id) {
+			lock (modules_lock) {
+				if (modules == null)
+					modules = new Dictionary <long, ModuleMirror> ();
+				ModuleMirror obj;
+				if (id == 0)
+					return null;
+				if (!modules.TryGetValue (id, out obj)) {
+					obj = new ModuleMirror (this, id);
+					modules [id] = obj;
+				}
+				return obj;
+			}
+	    }
+
+		Dictionary <long, AppDomainMirror> domains;
+		object domains_lock = new object ();
+
+		internal AppDomainMirror GetDomain (long id) {
+			lock (domains_lock) {
+				if (domains == null)
+					domains = new Dictionary <long, AppDomainMirror> ();
+				AppDomainMirror obj;
+				if (id == 0)
+					return null;
+				if (!domains.TryGetValue (id, out obj)) {
+					obj = new AppDomainMirror (this, id);
+					domains [id] = obj;
+				}
+				return obj;
+			}
+	    }
+
+		Dictionary <long, TypeMirror> types;
+		object types_lock = new object ();
+
+		internal TypeMirror GetType (long id) {
+			lock (types_lock) {
+				if (types == null)
+					types = new Dictionary <long, TypeMirror> ();
+				TypeMirror obj;
+				if (id == 0)
+					return null;
+				if (!types.TryGetValue (id, out obj)) {
+					obj = new TypeMirror (this, id);
+					types [id] = obj;
+				}
+				return obj;
+			}
+	    }
+
+		internal TypeMirror[] GetTypes (long[] ids) {
+			var res = new TypeMirror [ids.Length];
+			for (int i = 0; i < ids.Length; ++i)
+				res [i] = GetType (ids [i]);
+			return res;
+		}
+
+		Dictionary <long, ObjectMirror> objects;
+		object objects_lock = new object ();
+
+		internal T GetObject<T> (long id, long domain_id, long type_id) where T : ObjectMirror {
+			lock (objects_lock) {
+				if (objects == null)
+					objects = new Dictionary <long, ObjectMirror> ();
+				ObjectMirror obj;
+				if (!objects.TryGetValue (id, out obj)) {
+					/*
+					 * Obtain the domain/type of the object to determine the type of
+					 * object we need to create.
+					 */
+					if (domain_id == 0 || type_id == 0) {
+						if (conn.Version.AtLeast (2, 5)) {
+							var info = conn.Object_GetInfo (id);
+							domain_id = info.domain_id;
+							type_id = info.type_id;
+						} else {
+							if (domain_id == 0)
+								domain_id = conn.Object_GetDomain (id);
+							if (type_id == 0)
+								type_id = conn.Object_GetType (id);
+						}
+					}
+					AppDomainMirror d = GetDomain (domain_id);
+					TypeMirror t = GetType (type_id);
+
+					if (t.Assembly == d.Corlib && t.Namespace == "System.Threading" && t.Name == "Thread")
+						obj = new ThreadMirror (this, id, t, d);
+					else if (t.Assembly == d.Corlib && t.Namespace == "System" && t.Name == "String")
+						obj = new StringMirror (this, id, t, d);
+					else if (typeof (T) == typeof (ArrayMirror))
+						obj = new ArrayMirror (this, id, t, d);
+					else
+						obj = new ObjectMirror (this, id, t, d);
+					objects [id] = obj;
+				}
+				return (T)obj;
+			}
+	    }
+
+		internal T GetObject<T> (long id) where T : ObjectMirror {
+			return GetObject<T> (id, 0, 0);
+		}
+
+		internal ObjectMirror GetObject (long objid) {
+			return GetObject<ObjectMirror> (objid);
+		}
+
+		internal ThreadMirror GetThread (long id) {
+			return GetObject <ThreadMirror> (id);
+		}
+
+		object requests_lock = new object ();
+
+		internal void AddRequest (EventRequest req, int id) {
+			lock (requests_lock) {
+				requests [id] = req;
+			}
+		}
+
+		internal void RemoveRequest (EventRequest req, int id) {
+			lock (requests_lock) {
+				requests.Remove (id);
+			}
+		}
+
+		internal EventRequest GetRequest (int id) {
+			lock (requests_lock) {
+				return requests [id];
+			}
+		}
+
+		internal Value DecodeValue (ValueImpl v) {
+			if (v.Value != null)
+				return new PrimitiveValue (this, v.Value);
+
+			switch (v.Type) {
+			case ElementType.Void:
+				return null;
+			case ElementType.SzArray:
+			case ElementType.Array:
+				return GetObject<ArrayMirror> (v.Objid);
+			case ElementType.String:
+				return GetObject<StringMirror> (v.Objid);
+			case ElementType.Class:
+			case ElementType.Object:
+				return GetObject (v.Objid);
+			case ElementType.ValueType:
+				if (v.IsEnum)
+					return new EnumMirror (this, GetType (v.Klass), DecodeValues (v.Fields));
+				else
+					return new StructMirror (this, GetType (v.Klass), DecodeValues (v.Fields));
+			case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
+				return new PrimitiveValue (this, null);
+			default:
+				throw new NotImplementedException ("" + v.Type);
+			}
+		}
+
+		internal Value[] DecodeValues (ValueImpl[] values) {
+			Value[] res = new Value [values.Length];
+			for (int i = 0; i < values.Length; ++i)
+				res [i] = DecodeValue (values [i]);
+			return res;
+		}
+
+		internal ValueImpl EncodeValue (Value v) {
+			if (v is PrimitiveValue) {
+				object val = (v as PrimitiveValue).Value;
+				if (val == null)
+					return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 };
+				else
+					return new ValueImpl { Value = val };
+			} else if (v is ObjectMirror) {
+				return new ValueImpl { Type = ElementType.Object, Objid = (v as ObjectMirror).Id };
+			} else if (v is StructMirror) {
+				return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeValues ((v as StructMirror).Fields) };
+			} else {
+				throw new NotSupportedException ();
+			}
+		}
+
+		internal ValueImpl[] EncodeValues (IList<Value> values) {
+			ValueImpl[] res = new ValueImpl [values.Count];
+			for (int i = 0; i < values.Count; ++i)
+				res [i] = EncodeValue (values [i]);
+			return res;
+		}
+
+		internal void CheckProtocolVersion (int major, int minor) {
+			if (!conn.Version.AtLeast (major, minor))
+				throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
+		}
+    }
+
+	class EventHandler : MarshalByRefObject, IEventHandler
+	{		
+		VirtualMachine vm;
+
+		public EventHandler (VirtualMachine vm) {
+			this.vm = vm;
+		}
+
+		public void Events (SuspendPolicy suspend_policy, EventInfo[] events) {
+			var l = new List<Event> ();
+
+			for (int i = 0; i < events.Length; ++i) {
+				EventInfo ei = events [i];
+				int req_id = ei.ReqId;
+				long thread_id = ei.ThreadId;
+				long id = ei.Id;
+				long loc = ei.Location;
+
+				switch (ei.EventType) {
+				case EventType.VMStart:
+					vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null);
+					break;
+				case EventType.VMDeath:
+					vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null);
+					break;
+				case EventType.ThreadStart:
+					l.Add (new ThreadStartEvent (vm, req_id, id));
+					break;
+				case EventType.ThreadDeath:
+					l.Add (new ThreadDeathEvent (vm, req_id, id));
+					break;
+				case EventType.AssemblyLoad:
+					l.Add (new AssemblyLoadEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.AssemblyUnload:
+					l.Add (new AssemblyUnloadEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.TypeLoad:
+					l.Add (new TypeLoadEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.MethodEntry:
+					l.Add (new MethodEntryEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.MethodExit:
+					l.Add (new MethodExitEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.Breakpoint:
+					l.Add (new BreakpointEvent (vm, req_id, thread_id, id, loc));
+					break;
+				case EventType.Step:
+					l.Add (new StepEvent (vm, req_id, thread_id, id, loc));
+					break;
+				case EventType.Exception:
+					l.Add (new ExceptionEvent (vm, req_id, thread_id, id, loc));
+					break;
+				case EventType.AppDomainCreate:
+					l.Add (new AppDomainCreateEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.AppDomainUnload:
+					l.Add (new AppDomainUnloadEvent (vm, req_id, thread_id, id));
+					break;
+				case EventType.UserBreak:
+					l.Add (new UserBreakEvent (vm, req_id, thread_id));
+					break;
+				case EventType.UserLog:
+					l.Add (new UserLogEvent (vm, req_id, thread_id, ei.Level, ei.Category, ei.Message));
+					break;
+				default:
+					break;
+				}
+			}
+			
+			if (l.Count > 0)
+				vm.queue_event_set (new EventSet (vm, suspend_policy, l.ToArray ()));
+		}
+
+		public void VMDisconnect (int req_id, long thread_id, string vm_uri) {
+			vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri);
+        }
+    }
+
+	public class CommandException : Exception {
+
+		internal CommandException (ErrorCode error_code) : base ("Debuggee returned error code " + error_code + ".") {
+			ErrorCode = error_code;
+		}
+
+		public ErrorCode ErrorCode {
+			get; set;
+		}
+	}
+
+	public class VMNotSuspendedException : InvalidOperationException
+	{
+		public VMNotSuspendedException () : base ("The vm is not suspended.")
+		{
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs b/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs
new file mode 100644
index 0000000..a5bdf4f
--- /dev/null
+++ b/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs
@@ -0,0 +1,339 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.Remoting.Messaging;
+
+namespace Mono.Debugger.Soft
+{
+	public class LaunchOptions {
+		public string AgentArgs {
+			get; set;
+		}
+
+		public bool Valgrind {
+			get; set;
+		}
+		
+		public ProcessLauncher CustomProcessLauncher {
+			get; set;
+		}
+
+		public TargetProcessLauncher CustomTargetProcessLauncher {
+			get; set;
+		}
+
+		public delegate Process ProcessLauncher (ProcessStartInfo info);
+		public delegate ITargetProcess TargetProcessLauncher (ProcessStartInfo info);
+	}
+
+	public class VirtualMachineManager
+	{
+		private delegate VirtualMachine LaunchCallback (ITargetProcess p, ProcessStartInfo info, Socket socket);
+		private delegate VirtualMachine ListenCallback (Socket dbg_sock, Socket con_sock); 
+		private delegate VirtualMachine ConnectCallback (Socket dbg_sock, Socket con_sock, IPEndPoint dbg_ep, IPEndPoint con_ep); 
+
+		internal VirtualMachineManager () {
+		}
+
+		public static VirtualMachine LaunchInternal (Process p, ProcessStartInfo info, Socket socket)
+		{
+			return LaunchInternal (new ProcessWrapper (p), info, socket);
+		}
+			
+		public static VirtualMachine LaunchInternal (ITargetProcess p, ProcessStartInfo info, Socket socket) {
+			Socket accepted = null;
+			try {
+				accepted = socket.Accept ();
+			} catch (Exception) {
+				throw;
+			}
+
+			Connection conn = new TcpConnection (accepted);
+
+			VirtualMachine vm = new VirtualMachine (p, conn);
+
+			if (info.RedirectStandardOutput)
+				vm.StandardOutput = p.StandardOutput;
+			
+			if (info.RedirectStandardError)
+				vm.StandardError = p.StandardError;
+
+			conn.EventHandler = new EventHandler (vm);
+
+			vm.connect ();
+
+			return vm;
+		}
+
+		public static IAsyncResult BeginLaunch (ProcessStartInfo info, AsyncCallback callback)
+		{
+			return BeginLaunch (info, callback, null);
+		}
+
+		public static IAsyncResult BeginLaunch (ProcessStartInfo info, AsyncCallback callback, LaunchOptions options)
+		{
+			if (info == null)
+				throw new ArgumentNullException ("info");
+
+			Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+			socket.Bind (new IPEndPoint (IPAddress.Loopback, 0));
+			socket.Listen (1000);
+			IPEndPoint ep = (IPEndPoint) socket.LocalEndPoint;
+
+			// We need to inject our arguments into the psi
+			info.Arguments = string.Format ("{0} --debug --debugger-agent=transport=dt_socket,address={1}:{2}{3} {4}", 
+								options == null || !options.Valgrind ? "" : info.FileName,
+								ep.Address,
+								ep.Port,
+								options == null || options.AgentArgs == null ? "" : "," + options.AgentArgs,
+								info.Arguments);
+
+			if (options != null && options.Valgrind)
+				info.FileName = "valgrind";
+				
+			ITargetProcess p;
+			if (options != null && options.CustomProcessLauncher != null)
+				p = new ProcessWrapper (options.CustomProcessLauncher (info));
+			else if (options != null && options.CustomTargetProcessLauncher != null)
+				p = options.CustomTargetProcessLauncher (info);
+			else
+				p = new ProcessWrapper (Process.Start (info));
+			
+			p.Exited += delegate (object sender, EventArgs eargs) {
+				socket.Close ();
+			};
+
+			LaunchCallback c = new LaunchCallback (LaunchInternal);
+			return c.BeginInvoke (p, info, socket, callback, socket);
+		}
+
+		public static VirtualMachine EndLaunch (IAsyncResult asyncResult) {
+			if (asyncResult == null)
+				throw new ArgumentNullException ("asyncResult");
+
+			if (!asyncResult.IsCompleted)
+				asyncResult.AsyncWaitHandle.WaitOne ();
+
+			AsyncResult result = (AsyncResult) asyncResult;
+			LaunchCallback cb = (LaunchCallback) result.AsyncDelegate;
+			return cb.EndInvoke (asyncResult);
+		}
+
+		public static VirtualMachine Launch (ProcessStartInfo info)
+		{
+			return Launch (info, null);
+		}
+
+		public static VirtualMachine Launch (ProcessStartInfo info, LaunchOptions options)
+		{
+			return EndLaunch (BeginLaunch (info, null, options));
+		}
+
+		public static VirtualMachine Launch (string[] args)
+		{
+			return Launch (args, null);
+		}
+
+		public static VirtualMachine Launch (string[] args, LaunchOptions options)
+		{
+			ProcessStartInfo pi = new ProcessStartInfo ("mono");
+			pi.Arguments = String.Join (" ", args);
+
+			return Launch (pi, options);
+		}
+			
+		public static VirtualMachine ListenInternal (Socket dbg_sock, Socket con_sock) {
+			Socket con_acc = null;
+			Socket dbg_acc = null;
+
+			if (con_sock != null) {
+				try {
+					con_acc = con_sock.Accept ();
+				} catch (Exception) {
+					try {
+						dbg_sock.Close ();
+					} catch {}
+					throw;
+				}
+			}
+						
+			try {
+				dbg_acc = dbg_sock.Accept ();
+			} catch (Exception) {
+				if (con_sock != null) {
+					try {
+						con_sock.Close ();
+						con_acc.Close ();
+					} catch {}
+				}
+				throw;
+			}
+
+			if (con_sock != null) {
+				if (con_sock.Connected)
+					con_sock.Disconnect (false);
+				con_sock.Close ();
+			}
+
+			if (dbg_sock.Connected)
+				dbg_sock.Disconnect (false);
+			dbg_sock.Close ();
+
+			Connection transport = new TcpConnection (dbg_acc);
+			StreamReader console = con_acc != null? new StreamReader (new NetworkStream (con_acc)) : null;
+			
+			return Connect (transport, console, null);
+		}
+
+		public static IAsyncResult BeginListen (IPEndPoint dbg_ep, AsyncCallback callback) {
+			return BeginListen (dbg_ep, null, callback);
+		}
+		
+		public static IAsyncResult BeginListen (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback)
+		{
+			int dbg_port, con_port;
+			return BeginListen (dbg_ep, con_ep, callback, out dbg_port, out con_port);
+		}
+
+		public static IAsyncResult BeginListen (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback,
+			out int dbg_port, out int con_port)
+		{
+			dbg_port = con_port = 0;
+			
+			Socket dbg_sock = null;
+			Socket con_sock = null;
+
+			dbg_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+			dbg_sock.Bind (dbg_ep);
+			dbg_sock.Listen (1000);
+			dbg_port = ((IPEndPoint) dbg_sock.LocalEndPoint).Port;
+
+			if (con_ep != null) {
+				con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+				con_sock.Bind (con_ep);
+				con_sock.Listen (1000);
+				con_port = ((IPEndPoint) con_sock.LocalEndPoint).Port;
+			}
+			
+			ListenCallback c = new ListenCallback (ListenInternal);
+			return c.BeginInvoke (dbg_sock, con_sock, callback, con_sock ?? dbg_sock);
+		}
+
+		public static VirtualMachine EndListen (IAsyncResult asyncResult) {
+			if (asyncResult == null)
+				throw new ArgumentNullException ("asyncResult");
+
+			if (!asyncResult.IsCompleted)
+				asyncResult.AsyncWaitHandle.WaitOne ();
+
+			AsyncResult result = (AsyncResult) asyncResult;
+			ListenCallback cb = (ListenCallback) result.AsyncDelegate;
+			return cb.EndInvoke (asyncResult);
+		}
+
+		public static VirtualMachine Listen (IPEndPoint dbg_ep)
+		{
+			return Listen (dbg_ep, null);
+		}
+
+		public static VirtualMachine Listen (IPEndPoint dbg_ep, IPEndPoint con_ep)
+		{
+			return EndListen (BeginListen (dbg_ep, con_ep, null));
+		}
+
+		/*
+		 * Connect to a virtual machine listening at the specified address.
+		 */
+		public static VirtualMachine Connect (IPEndPoint endpoint) {
+			return Connect (endpoint, null);
+		}
+
+		public static VirtualMachine Connect (IPEndPoint endpoint, IPEndPoint consoleEndpoint) { 
+			if (endpoint == null)
+				throw new ArgumentNullException ("endpoint");
+
+			return EndConnect (BeginConnect (endpoint, consoleEndpoint, null));
+		}
+
+		public static VirtualMachine ConnectInternal (Socket dbg_sock, Socket con_sock, IPEndPoint dbg_ep, IPEndPoint con_ep) {
+			if (con_sock != null) {
+				try {
+					con_sock.Connect (con_ep);
+				} catch (Exception) {
+					try {
+						dbg_sock.Close ();
+					} catch {}
+					throw;
+				}
+			}
+						
+			try {
+				dbg_sock.Connect (dbg_ep);
+			} catch (Exception) {
+				if (con_sock != null) {
+					try {
+						con_sock.Close ();
+					} catch {}
+				}
+				throw;
+			}
+			
+			Connection transport = new TcpConnection (dbg_sock);
+			StreamReader console = con_sock != null? new StreamReader (new NetworkStream (con_sock)) : null;
+			
+			return Connect (transport, console, null);
+		}
+
+		public static IAsyncResult BeginConnect (IPEndPoint dbg_ep, AsyncCallback callback) {
+			return BeginConnect (dbg_ep, null, callback);
+		}
+
+		public static IAsyncResult BeginConnect (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback) {
+			Socket dbg_sock = null;
+			Socket con_sock = null;
+
+			dbg_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+			if (con_ep != null) {
+				con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+			}
+			
+			ConnectCallback c = new ConnectCallback (ConnectInternal);
+			return c.BeginInvoke (dbg_sock, con_sock, dbg_ep, con_ep, callback, con_sock ?? dbg_sock);
+		}
+
+		public static VirtualMachine EndConnect (IAsyncResult asyncResult) {
+			if (asyncResult == null)
+				throw new ArgumentNullException ("asyncResult");
+
+			if (!asyncResult.IsCompleted)
+				asyncResult.AsyncWaitHandle.WaitOne ();
+
+			AsyncResult result = (AsyncResult) asyncResult;
+			ConnectCallback cb = (ConnectCallback) result.AsyncDelegate;
+			return cb.EndInvoke (asyncResult);
+		}
+
+		public static void CancelConnection (IAsyncResult asyncResult)
+		{
+			((Socket)asyncResult.AsyncState).Close ();
+		}
+		
+		public static VirtualMachine Connect (Connection transport, StreamReader standardOutput, StreamReader standardError)
+		{
+			VirtualMachine vm = new VirtualMachine (null, transport);
+			
+			vm.StandardOutput = standardOutput;
+			vm.StandardError = standardError;
+			
+			transport.EventHandler = new EventHandler (vm);
+
+			vm.connect ();
+
+			return vm;
+		}
+	}
+}
diff --git a/Mono.Debugger.Soft/mono-git-revision b/Mono.Debugger.Soft/mono-git-revision
new file mode 100644
index 0000000..a702b4f
--- /dev/null
+++ b/Mono.Debugger.Soft/mono-git-revision
@@ -0,0 +1 @@
+75d1cf2f193e6bdfc9bdb025317283b83d31c67a
diff --git a/Mono.Debugger.Soft/mono.snk b/Mono.Debugger.Soft/mono.snk
new file mode 100644
index 0000000..380116c
Binary files /dev/null and b/Mono.Debugger.Soft/mono.snk differ
diff --git a/Mono.Debugging.Soft/ArrayAdaptor.cs b/Mono.Debugging.Soft/ArrayAdaptor.cs
new file mode 100644
index 0000000..462525a
--- /dev/null
+++ b/Mono.Debugging.Soft/ArrayAdaptor.cs
@@ -0,0 +1,89 @@
+// 
+// ArrayAdaptor.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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.Linq;
+using Mono.Debugging.Evaluation;
+using Mono.Debugger.Soft;
+
+namespace Mono.Debugging.Soft
+{
+	public class ArrayAdaptor: ICollectionAdaptor
+	{
+		ArrayMirror array;
+		int[] dimensions;
+		
+		public ArrayAdaptor (ArrayMirror array)
+		{
+			this.array = array;
+		}
+		
+		public int[] GetDimensions ()
+		{
+			if (dimensions == null) {
+				dimensions = new int [array.Rank];
+				for (int n=0; n<array.Rank; n++)
+					dimensions [n] = array.GetLength (n);
+			}
+			return dimensions;
+		}
+		
+		public object GetElement (int[] indices)
+		{
+			int i = GetIndex (indices);
+			return array.GetValues (i, 1)[0];
+		}
+
+		public Array GetElements (int[] indices, int count)
+		{
+			int i = GetIndex (indices);
+			return array.GetValues (i, count).ToArray ();
+		}
+		
+		public void SetElement (int[] indices, object val)
+		{
+			array.SetValues (GetIndex (indices), new Value[] { (Value) val });
+		}
+		
+		int GetIndex (int[] indices)
+		{
+			int ts = 1;
+			int i = 0;
+			int[] dims = GetDimensions ();
+			for (int n = indices.Length - 1; n >= 0; n--) {
+				i += indices [n] * ts;
+				ts *= dims [n];
+			}
+			return i;
+		}
+		
+		public object ElementType {
+			get {
+				return array.Type.GetElementType ();
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/AssemblyInfo.cs b/Mono.Debugging.Soft/AssemblyInfo.cs
new file mode 100644
index 0000000..d70591c
--- /dev/null
+++ b/Mono.Debugging.Soft/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+// 
+// AssemblyInfo.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson at novell.com>
+// 
+// Copyright (c) 2010 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.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle("Mono.Debugging.Soft")]
\ No newline at end of file
diff --git a/Mono.Debugging.Soft/ChangeLog b/Mono.Debugging.Soft/ChangeLog
new file mode 100644
index 0000000..28f5b09
--- /dev/null
+++ b/Mono.Debugging.Soft/ChangeLog
@@ -0,0 +1,264 @@
+2010-06-29  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: Show no window when starting the
+	  app.
+
+2010-06-01  Levi Bard  <levi at unity3d.com>
+
+	* SoftDebuggerSession.cs: Catch SocketException 
+	  on session exit.
+
+2010-05-31  Levi Bard  <levi at unity3d.com>
+
+	* SoftDebuggerSession.cs: Account for multiple assemblies
+	  being built from a single source file.
+
+2010-05-31  Levi Bard  <levi at unity3d.com>
+
+	* SoftDebuggerSession.cs: Clear the source-to-type map on
+	  assembly unload.
+
+2010-05-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Improved detection of null values.
+
+2010-05-10  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated to latest.
+
+	* SoftDebuggerAdaptor.cs: Handle the new
+	  AbsentInformationException.
+
+2010-05-07  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftEvaluationContext.cs:
+	* SoftDebuggerBacktrace.cs: Track api changes.
+
+2010-05-07  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* PropertyValueReference.cs: Track api changes.
+
+2010-05-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: Don't redirect output/error when
+	  using an external console. Use TargetProcess instead of
+	  Process, since Process doesn't work for external consoles.
+
+2010-04-29  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated from Mono.
+
+	* SoftDebuggerSession.cs:
+	* SoftDebuggerStartInfo.cs: Track API changes.
+
+	* SoftDebuggerAdaptor.cs: The call to ToString may return
+	  null. Return an empty string in this case. Fixes bug
+	  #599434.
+
+2010-04-26  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated.
+
+2010-04-19  Carlo Kok  <ck at remobjects.com>
+	* SoftDebuggerSession.cs:
+	* SoftEvaluationContext.cs:
+	  Allow for custom expression evaluator.
+
+2010-04-14  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: When getting the members of a type,
+	  take into account overriden virtual properties. Fixes bug
+	  #580994 - MD debugger hover window ignores virtual.
+
+2010-03-30  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: Set the current request in the Step
+	  Out command. Fixes bug #569418 - Debugger sometimes loses
+	  track of stepping.
+
+2010-03-30  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs:
+	* SoftDebuggerStartInfo.cs: Fix external console support
+	  again.
+
+2010-03-29  Levi Bard  <levi at unity3d.com>
+
+	* SoftDebuggerSession.cs: Improve assembly matching.
+
+2010-03-26  Levi Bard  <levi at unity3d.com>
+
+	* SoftDebuggerSession.cs: Handle assembly unload.
+
+2010-03-17  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Don't crash if something goes wrong
+	  while getting type data.
+
+2010-03-09  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Nicer log messages.
+
+	* LoggingService.cs: Use custom logger for the new LogMessage
+	  call. Remove unnecessary string.Format call.
+
+2010-03-09  Martin Baulig  <martin at ximian.com>
+
+	* SoftDebuggerSession.cs: Add protected virtual methods
+	OnHandleEvent(), OnVMStartEvent(), OnVMDeathEvent() and
+	OnBreakpointBound().
+
+2010-03-05  Martin Baulig  <martin at ximian.com>
+
+	Use the new Soft Debugger API to abort invocations.
+
+	* SoftDebuggerAdaptor.cs (MethodCall.Abort): Implement this.
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated.
+
+2010-03-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: Don't catch the thread abort
+	  exception, unless there is a catchpoint for it. Based on a
+	  patch by Levi Bard.
+
+2010-03-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Renamed variable to improve
+	  readability.
+
+	* SoftEvaluationContext.cs: When calling a method, make sure
+	  value type arguments are properly boxed when required.
+
+2010-03-01  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* SoftDebuggerSession.cs:
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated SDB dll, stops uncaught
+	  exception handler getting all caught exceptions on older
+	  Monos, and updates protocol.
+
+2010-03-01  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Improved support for indexers.
+	  Improved GetType implementation, so that it can now properly
+	  instantiate generic types.
+
+2010-02-26  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Implement enum conversions.
+
+2010-02-23  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated.
+
+	* SoftDebuggerSession.cs: Report unhandled exceptions.
+
+2010-02-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerBacktrace.cs: Don't crash if the debugger
+	  stopped and the current thread could not be found.
+
+2010-02-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugger.Soft.dll:
+	* Mono.Debugger.Soft.dll.mdb: Updated.
+
+	* SoftDebuggerAdaptor.cs: Add missing null check.
+
+2010-02-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs:
+	* SoftDebuggerSession.cs: Implement GetCurrentException.
+
+2010-02-17  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.Soft.csproj: Fix assembly reference. Set the
+	  autotools project flag, so it can properly resolve relative
+	  paths.
+
+2010-02-16  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Soft.csproj: Track api changes. Some engine
+	  info is now taken from extension node metadata.
+
+2010-02-10  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* SoftDebuggerSession.cs: Force-load System.Exception to work
+	  around sdb currently not giving a type load for this. Warn
+	  on duplicate type loads - they could cause problems because
+	  we can't handle them and they currently might happen e.g.
+	  with appdomains. Shorten stupidly long lines.
+
+	* LoggingService.cs: Only insert newline if exception is not
+	  null.
+
+2010-02-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: Dont print the expression when a
+	  tracepoint is hit. UpdateListTraceValue will do it.
+
+2010-02-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Implemented GetTypeArgs. Report the
+	  correct exception name when an exception is thrown in the
+	  target. Fixes bug #576427 - Debugger hides any user
+	  exception.
+
+2010-02-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerSession.cs: When a breakpoint can't be resolved,
+	  set it as invalid. Set it to valid when resolved. Fixes bug
+	  #564541 - Set breakpoint should work on expressions and not
+	  lines.
+
+2010-02-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* ArrayAdaptor.cs:
+	* Mono.Debugger.Soft.dll:
+	* SoftDebuggerAdaptor.cs:
+	* FieldValueReference.cs:
+	* SoftDebuggerSession.cs:
+	* SoftEvaluationContext.cs:
+	* SoftDebuggerBacktrace.cs:
+	* VariableValueReference.cs:
+	* PropertyValueReference.cs:
+	* Mono.Debugger.Soft.dll.mdb: Use the new namespace for the
+	  soft debugger. Updated the sdb client library.
+
+2010-01-25  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* SoftDebuggerSession.cs: Write a message to the debugger
+	  output if unable to insert a breakpoint.
+
+2010-01-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* SoftDebuggerAdaptor.cs: Implement new ForceLoadType
+	  overridable.
+
+2010-01-20  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* AssemblyInfo.cs:
+	* ArrayAdaptor.cs:
+	* LoggingService.cs:
+	* SoftDebuggerSession.cs:
+	* SoftDebuggerAdaptor.cs:
+	* Mono.Debugger.Soft.dll:
+	* FieldValueReference.cs:
+	* SoftDebuggerBacktrace.cs:
+	* SoftDebuggerStartInfo.cs:
+	* SoftEvaluationContext.cs:
+	* VariableValueReference.cs:
+	* PropertyValueReference.cs:
+	* Mono.Debugger.Soft.dll.mdb:
+	* Mono.Debugging.Soft.csproj: Split out a new dll
+	  Mono.Debugging.Soft from the soft debugger addin. It has the
+	  bits that have with no MD deps apart from Mono.Debugging,
+	  and it's strongnamed so MonoVS can use it.
+
diff --git a/Mono.Debugging.Soft/FieldValueReference.cs b/Mono.Debugging.Soft/FieldValueReference.cs
new file mode 100644
index 0000000..5dc4161
--- /dev/null
+++ b/Mono.Debugging.Soft/FieldValueReference.cs
@@ -0,0 +1,170 @@
+// 
+// FieldValueReference.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 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.Reflection;
+using Mono.Debugging.Evaluation;
+using Mono.Debugger.Soft;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Soft
+{
+	public class FieldValueReference: ValueReference
+	{
+		FieldInfoMirror field;
+		object obj;
+		TypeMirror declaringType;
+		ObjectValueFlags flags;
+		string vname;
+		
+		public FieldValueReference (EvaluationContext ctx, FieldInfoMirror field, object obj, TypeMirror declaringType)
+			: this (ctx, field, obj, declaringType, null, ObjectValueFlags.Field)
+		{
+		}
+		
+		public FieldValueReference (EvaluationContext ctx, FieldInfoMirror field, object obj, TypeMirror declaringType, string vname, ObjectValueFlags vflags): base (ctx)
+		{
+			this.field = field;
+			this.obj = obj;
+			this.declaringType = declaringType;
+			this.vname = vname;
+			flags = vflags;
+
+			if (field.IsStatic)
+				this.obj = null;
+
+			flags |= GetFlags (field);
+
+			if (obj is PrimitiveValue)
+				flags |= ObjectValueFlags.ReadOnly;
+		}
+
+		internal static ObjectValueFlags GetFlags (FieldInfoMirror field)
+		{
+			var flags = ObjectValueFlags.Field;
+
+			if (field.IsStatic)
+				flags |= ObjectValueFlags.Global;
+
+			if (field.IsPublic)
+				flags |= ObjectValueFlags.Public;
+			else if (field.IsPrivate)
+				flags |= ObjectValueFlags.Private;
+			else if (field.IsFamily)
+				flags |= ObjectValueFlags.Protected;
+			else if (field.IsFamilyAndAssembly)
+				flags |= ObjectValueFlags.Internal;
+			else if (field.IsFamilyOrAssembly)
+				flags |= ObjectValueFlags.InternalProtected;
+
+			return flags;
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return flags;
+			}
+		}
+
+		public override string Name {
+			get {
+				return vname ?? field.Name;
+			}
+		}
+
+		public override object Type {
+			get {
+				return field.FieldType;
+			}
+		}
+		
+		public override object DeclaringType {
+			get {
+				return field.DeclaringType;
+			}
+		}
+
+		public override object Value {
+			get {
+				if (obj == null) {
+					// If the type hasn't already been loaded, invoke the .cctor() for types w/ the BeforeFieldInit attribute.
+					Context.Adapter.ForceLoadType (Context, declaringType);
+
+					return declaringType.GetValue (field);
+				} else if (obj is ObjectMirror) {
+					return ((ObjectMirror)obj).GetValue (field);
+				} else if (obj is StructMirror) {
+					StructMirror sm = (StructMirror)obj;
+					int idx = 0;
+					foreach (FieldInfoMirror f in sm.Type.GetFields ()) {
+						if (f.IsStatic) continue;
+						if (f == field)
+							break;
+						idx++;
+					}
+					return sm.Fields [idx];
+				} else if (obj is StringMirror) {
+					SoftEvaluationContext cx = (SoftEvaluationContext) Context;
+					StringMirror val = (StringMirror) obj;
+					FieldInfo rfield = typeof(string).GetField (field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+					return cx.Session.VirtualMachine.CreateValue (rfield.GetValue (val.Value));
+				} else {
+					SoftEvaluationContext cx = (SoftEvaluationContext) Context;
+					PrimitiveValue val = (PrimitiveValue) obj;
+					if (val.Value == null)
+						return null;
+					FieldInfo rfield = val.Value.GetType ().GetField (field.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+					return cx.Session.VirtualMachine.CreateValue (rfield.GetValue (val.Value));
+				}
+			}
+			set {
+				if (obj == null)
+					declaringType.SetValue (field, (Value)value);
+				else if (obj is ObjectMirror)
+					((ObjectMirror)obj).SetValue (field, (Value)value);
+				else if (obj is StructMirror) {
+					StructMirror sm = (StructMirror)obj;
+					int idx = 0;
+					foreach (FieldInfoMirror f in sm.Type.GetFields ()) {
+						if (f.IsStatic) continue;
+						if (f == field)
+							break;
+						idx++;
+					}
+					if (idx != -1) {
+						sm.Fields [idx] = (Value)value;
+						// Structs are handled by-value in the debugger, so the source of the object has to be updated
+						if (ParentSource != null && obj != null)
+							ParentSource.Value = obj;
+					}
+				}
+				else
+					throw new NotSupportedException ();
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/Makefile.am b/Mono.Debugging.Soft/Makefile.am
new file mode 100644
index 0000000..c9cc874
--- /dev/null
+++ b/Mono.Debugging.Soft/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/xbuild.include
diff --git a/Mono.Debugging.Soft/Mono.Debugging.Soft.csproj b/Mono.Debugging.Soft/Mono.Debugging.Soft.csproj
new file mode 100644
index 0000000..c6d1531
--- /dev/null
+++ b/Mono.Debugging.Soft/Mono.Debugging.Soft.csproj
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{DE40756E-57F6-4AF2-B155-55E3A88CCED8}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Mono.Debugging.Soft</RootNamespace>
+    <AssemblyName>Mono.Debugging.Soft</AssemblyName>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>..\Mono.Debugging\mono.debugging.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <GenerateDocumentation>true</GenerateDocumentation>
+    <NoWarn>1591;1573</NoWarn>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DebugSymbols>true</DebugSymbols>
+    <GenerateDocumentation>true</GenerateDocumentation>
+    <NoWarn>1591;1573</NoWarn>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Mono.Debugging\Mono.Debugging.csproj">
+      <Project>{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}</Project>
+      <Name>Mono.Debugging</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\Mono.Debugger.Soft\Mono.Debugger.Soft.csproj">
+      <Project>{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}</Project>
+      <Name>Mono.Debugger.Soft</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
+      <Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
+      <Name>Mono.Cecil</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj">
+      <Project>{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}</Project>
+      <Name>Mono.Cecil.Mdb</Name>
+      <Private>False</Private>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ArrayAdaptor.cs" />
+    <Compile Include="FieldValueReference.cs" />
+    <Compile Include="PropertyValueReference.cs" />
+    <Compile Include="SoftDebuggerSession.cs" />
+    <Compile Include="VariableValueReference.cs" />
+    <Compile Include="SoftEvaluationContext.cs" />
+    <Compile Include="SoftDebuggerAdaptor.cs" />
+    <Compile Include="SoftDebuggerBacktrace.cs" />
+    <Compile Include="SoftDebuggerStartInfo.cs" />
+    <Compile Include="AssemblyInfo.cs" />
+    <Compile Include="StringAdaptor.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <None Include="Makefile.am" />
+  </ItemGroup>
+</Project>
diff --git a/Mono.Debugging.Soft/PropertyValueReference.cs b/Mono.Debugging.Soft/PropertyValueReference.cs
new file mode 100644
index 0000000..b3d446f
--- /dev/null
+++ b/Mono.Debugging.Soft/PropertyValueReference.cs
@@ -0,0 +1,128 @@
+// 
+// PropertyValueReference.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Evaluation;
+using Mono.Debugger.Soft;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Soft
+{
+	public class PropertyValueReference: ValueReference
+	{
+		PropertyInfoMirror property;
+		object obj;
+		TypeMirror declaringType;
+		Value[] indexerArgs;
+		ObjectValueFlags flags;
+		
+		public PropertyValueReference (EvaluationContext ctx, PropertyInfoMirror property, object obj, TypeMirror declaringType, MethodMirror getter, Value[] indexerArgs): base (ctx)
+		{
+			this.property = property;
+			this.obj = obj;
+			this.declaringType = declaringType;
+			this.indexerArgs = indexerArgs;
+			
+			flags = GetFlags (property, getter);
+		}
+
+		internal static ObjectValueFlags GetFlags (PropertyInfoMirror property, MethodMirror getter)
+		{
+			var flags = ObjectValueFlags.Property;
+
+			if (property.GetSetMethod (true) == null)
+				flags |= ObjectValueFlags.ReadOnly;
+
+			if (getter.IsStatic)
+				flags |= ObjectValueFlags.Global;
+
+			if (getter.IsPublic)
+				flags |= ObjectValueFlags.Public;
+			else if (getter.IsPrivate)
+				flags |= ObjectValueFlags.Private;
+			else if (getter.IsFamily)
+				flags |= ObjectValueFlags.Protected;
+			else if (getter.IsFamilyAndAssembly)
+				flags |= ObjectValueFlags.Internal;
+			else if (getter.IsFamilyOrAssembly)
+				flags |= ObjectValueFlags.InternalProtected;
+
+			if (property.DeclaringType.IsValueType)
+				flags |= ObjectValueFlags.ReadOnly; // Setting property values on structs is not supported by sdb
+
+			return flags;
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return flags;
+			}
+		}
+
+		public override string Name {
+			get {
+				return property.Name;
+			}
+		}
+
+		public override object Type {
+			get {
+				return property.PropertyType;
+			}
+		}
+		
+		public override object DeclaringType {
+			get {
+				return property.DeclaringType;
+			}
+		}
+
+		public override object Value {
+			get {
+				Context.AssertTargetInvokeAllowed ();
+				SoftEvaluationContext ctx = (SoftEvaluationContext) Context;
+				return ctx.RuntimeInvoke (property.GetGetMethod (true), obj ?? declaringType, indexerArgs);
+			}
+			set {
+				Context.AssertTargetInvokeAllowed ();
+				SoftEvaluationContext ctx = (SoftEvaluationContext) Context;
+				Value[] args = new Value [indexerArgs != null ? indexerArgs.Length + 1 : 1];
+				if (indexerArgs != null)
+					indexerArgs.CopyTo (args, 0);
+				args [args.Length - 1] = (Value) value;
+				MethodMirror setter = property.GetSetMethod (true);
+				if (setter == null)
+					throw new EvaluatorException ("Property is read-only");
+				ctx.RuntimeInvoke (setter, obj ?? declaringType, args);
+			}
+		}
+		
+		protected override bool CanEvaluate (EvaluationOptions options)
+		{
+			return options.AllowTargetInvoke;
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/SoftDebuggerAdaptor.cs b/Mono.Debugging.Soft/SoftDebuggerAdaptor.cs
new file mode 100644
index 0000000..200833d
--- /dev/null
+++ b/Mono.Debugging.Soft/SoftDebuggerAdaptor.cs
@@ -0,0 +1,1825 @@
+// 
+// SoftDebuggerAdaptor.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2011,2012 Xamain 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.Linq;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+using Mono.Debugger.Soft;
+using Mono.Debugging.Evaluation;
+using Mono.Debugging.Client;
+
+using ST = System.Threading;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Soft
+{
+	public class SoftDebuggerAdaptor : ObjectValueAdaptor
+	{
+		static readonly Dictionary<Type, OpCode> convertOps = new Dictionary<Type, OpCode> ();
+		delegate object TypeCastDelegate (object value);
+
+		static SoftDebuggerAdaptor ()
+		{
+			convertOps.Add (typeof (double), OpCodes.Conv_R8);
+			convertOps.Add (typeof (float), OpCodes.Conv_R4);
+			convertOps.Add (typeof (ulong), OpCodes.Conv_U8);
+			convertOps.Add (typeof (uint), OpCodes.Conv_U4);
+			convertOps.Add (typeof (ushort), OpCodes.Conv_U2);
+			convertOps.Add (typeof (char), OpCodes.Conv_U2);
+			convertOps.Add (typeof (byte), OpCodes.Conv_U1);
+			convertOps.Add (typeof (long), OpCodes.Conv_I8);
+			convertOps.Add (typeof (int), OpCodes.Conv_I4);
+			convertOps.Add (typeof (short), OpCodes.Conv_I2);
+			convertOps.Add (typeof (sbyte), OpCodes.Conv_I1);
+		}
+
+		public SoftDebuggerAdaptor ()
+		{
+		}
+		
+		public override string CallToString (EvaluationContext ctx, object obj)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			
+			if (obj == null)
+				return null;
+			
+			if (obj is StringMirror)
+				return ((StringMirror)obj).Value;
+
+			if (obj is EnumMirror)
+				return ((EnumMirror) obj).StringValue;
+
+			if (obj is PrimitiveValue)
+				return ((PrimitiveValue)obj).Value.ToString ();
+
+			if (obj is PointerValue)
+				return string.Format ("0x{0:x}", ((PointerValue)obj).Address);
+
+			if ((obj is StructMirror) && ((StructMirror)obj).Type.IsPrimitive) {
+				// Boxed primitive
+				StructMirror sm = (StructMirror) obj;
+				if (sm.Fields.Length > 0 && (sm.Fields[0] is PrimitiveValue))
+					return ((PrimitiveValue)sm.Fields[0]).Value.ToString ();
+			} else if ((obj is ObjectMirror) && cx.Options.AllowTargetInvoke) {
+				ObjectMirror ob = (ObjectMirror) obj;
+				MethodMirror method = OverloadResolve (cx, ob.Type, "ToString", null, new TypeMirror[0], true, false, false);
+				if (method != null && method.DeclaringType.FullName != "System.Object") {
+					StringMirror res = cx.RuntimeInvoke (method, obj, new Value[0]) as StringMirror;
+					return res != null ? res.Value : null;
+				}
+			} else if ((obj is StructMirror) && cx.Options.AllowTargetInvoke) {
+				StructMirror ob = (StructMirror) obj;
+				MethodMirror method = OverloadResolve (cx, ob.Type, "ToString", null, new TypeMirror[0], true, false, false);
+				if (method != null && method.DeclaringType.FullName != "System.ValueType") {
+					StringMirror res = cx.RuntimeInvoke (method, obj, new Value[0]) as StringMirror;
+					return res != null ? res.Value : null;
+				}
+			}
+			
+			return GetDisplayTypeName (GetValueTypeName (ctx, obj));
+		}
+
+		public override object TryConvert (EvaluationContext ctx, object obj, object targetType)
+		{
+			object res = TryCast (ctx, obj, targetType);
+			
+			if (res != null || obj == null)
+				return res;
+			
+			object otype = GetValueType (ctx, obj);
+			if (otype is Type) {
+				if (targetType is TypeMirror)
+					targetType = Type.GetType (((TypeMirror)targetType).FullName, false);
+				
+				Type tt = targetType as Type;
+				if (tt != null) {
+					try {
+						if (obj is PrimitiveValue)
+							obj = ((PrimitiveValue)obj).Value;
+						res = System.Convert.ChangeType (obj, tt);
+						return CreateValue (ctx, res);
+					} catch {
+					}
+				}
+			}
+			return null;
+		}
+
+		static TypeCastDelegate GenerateTypeCastDelegate (string methodName, Type fromType, Type toType)
+		{
+			var argTypes = new Type[] {
+				typeof (object)
+			};
+			var method = new DynamicMethod (methodName, typeof (object), argTypes, true);
+			ILGenerator il = method.GetILGenerator ();
+			ConstructorInfo ctorInfo;
+			MethodInfo methodInfo;
+			OpCode conv;
+
+			il.Emit (OpCodes.Ldarg_0);
+			il.Emit (OpCodes.Unbox_Any, fromType);
+
+			if (fromType.IsSubclassOf (typeof (System.Nullable))) {
+				PropertyInfo propInfo = fromType.GetProperty ("Value");
+				methodInfo = propInfo.GetGetMethod ();
+
+				il.Emit (OpCodes.Stloc_0);
+				il.Emit (OpCodes.Ldloca_S);
+				il.Emit (OpCodes.Call, methodInfo);
+
+				fromType = methodInfo.ReturnType;
+			}
+
+			if (!convertOps.TryGetValue (toType, out conv)) {
+				argTypes = new Type[] {
+					fromType
+				};
+
+				if (toType == typeof (string)) {
+					methodInfo = fromType.GetMethod ("ToString", new Type[0]);
+					il.Emit (OpCodes.Call, methodInfo);
+				} else if ((methodInfo = toType.GetMethod ("op_Explicit", argTypes)) != null) {
+					il.Emit (OpCodes.Call, methodInfo);
+				} else if ((methodInfo = toType.GetMethod ("op_Implicit", argTypes)) != null) {
+					il.Emit (OpCodes.Call, methodInfo);
+				} else if ((ctorInfo = toType.GetConstructor (argTypes)) != null) {
+					il.Emit (OpCodes.Call, ctorInfo);
+				} else {
+					// No idea what else to try...
+					throw new InvalidCastException ();
+				}
+			} else {
+				il.Emit (conv);
+			}
+
+			il.Emit (OpCodes.Box, toType);
+			il.Emit (OpCodes.Ret);
+
+			return (TypeCastDelegate) method.CreateDelegate (typeof (TypeCastDelegate));
+		}
+
+		static object DynamicCast (object value, Type target)
+		{
+			string methodName = string.Format ("CastFrom{0}To{1}", value.GetType ().Name, target.Name);
+			TypeCastDelegate method = GenerateTypeCastDelegate (methodName, value.GetType (), target);
+
+			return method.Invoke (value);
+		}
+
+		object TryForceCast (EvaluationContext ctx, Value value, TypeMirror fromType, TypeMirror toType)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			MethodMirror method;
+
+			method = OverloadResolve (cx, toType, "op_Explicit", null, new TypeMirror[] { fromType }, false, true, false);
+			if (method != null)
+				return cx.RuntimeInvoke (method, toType, new Value[] { value });
+
+			method = OverloadResolve (cx, toType, "op_Implicit", null, new TypeMirror[] { fromType }, false, true, false);
+			if (method != null)
+				return cx.RuntimeInvoke (method, toType, new Value[] { value });
+
+			// Finally, try a ctor...
+			try {
+				return CreateValue (ctx, toType, value);
+			} catch {
+				return null;
+			}
+		}
+
+		public override object TryCast (EvaluationContext ctx, object obj, object targetType)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			TypeMirror toType = targetType as TypeMirror;
+			TypeMirror fromType;
+			
+			if (obj == null)
+				return null;
+			
+			object valueType = GetValueType (ctx, obj);
+			if (valueType is TypeMirror) {
+				fromType = (TypeMirror) valueType;
+
+				if (toType != null && toType.IsAssignableFrom (fromType))
+					return obj;
+				
+				// Try casting the primitive type of the enum
+				EnumMirror em = obj as EnumMirror;
+				if (em != null)
+					return TryCast (ctx, CreateValue (ctx, em.Value), targetType);
+
+				if (toType == null)
+					return null;
+
+				MethodMirror method;
+
+				if (toType.CSharpName == "string") {
+					method = OverloadResolve (cx, fromType, "ToString", null, new TypeMirror[0], true, false, false);
+					if (method != null)
+						return cx.RuntimeInvoke (method, obj, new Value[0]);
+				}
+
+				if (fromType.IsGenericType && fromType.FullName.StartsWith ("System.Nullable`1", StringComparison.Ordinal)) {
+					method = OverloadResolve (cx, fromType, "get_Value", null, new TypeMirror[0], true, false, false);
+					if (method != null) {
+						obj = cx.RuntimeInvoke (method, obj, new Value[0]);
+						return TryCast (ctx, obj, targetType);
+					}
+				}
+
+				return TryForceCast (ctx, (Value) obj, fromType, toType);
+			} else if (valueType is Type) {
+				if (toType != null) {
+					if (toType.IsEnum) {
+						PrimitiveValue casted = TryCast (ctx, obj, toType.EnumUnderlyingType) as PrimitiveValue;
+						if (casted == null)
+							return null;
+						return cx.Session.VirtualMachine.CreateEnumMirror (toType, casted);
+					}
+
+					targetType = Type.GetType (toType.FullName, false);
+				}
+				
+				Type tt = targetType as Type;
+				if (tt != null) {
+					if (tt.IsAssignableFrom ((Type) valueType))
+						return obj;
+
+					try {
+						if (tt.IsPrimitive || tt == typeof (string)) {
+							if (obj is PrimitiveValue)
+								obj = ((PrimitiveValue) obj).Value;
+
+							if (obj == null)
+								return null;
+
+							object res;
+
+							try {
+								res = System.Convert.ChangeType (obj, tt);
+							} catch {
+								res = DynamicCast (obj, tt);
+							}
+
+							return CreateValue (ctx, res);
+						} else {
+							fromType = (TypeMirror) ForceLoadType (ctx, ((Type) valueType).FullName);
+							if (toType == null)
+								toType = (TypeMirror) ForceLoadType (ctx, tt.FullName);
+
+							return TryForceCast (ctx, (Value) obj, fromType, toType);
+						}
+					} catch {
+					}
+				}
+			}
+
+			return null;
+		}
+		
+		public override IStringAdaptor CreateStringAdaptor (EvaluationContext ctx, object str)
+		{
+			return new StringAdaptor ((StringMirror) str);
+		}
+
+		public override ICollectionAdaptor CreateArrayAdaptor (EvaluationContext ctx, object arr)
+		{
+			return new ArrayAdaptor ((ArrayMirror) arr);
+		}
+
+		public override object CreateNullValue (EvaluationContext ctx, object type)
+		{
+			return null;
+		}
+
+		public override object CreateTypeObject (EvaluationContext ctx, object type)
+		{
+			TypeMirror t = (TypeMirror) type;
+			return t.GetTypeObject ();
+		}
+
+		public override object CreateValue (EvaluationContext ctx, object type, params object[] args)
+		{
+			ctx.AssertTargetInvokeAllowed ();
+			
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			TypeMirror t = (TypeMirror) type;
+			
+			TypeMirror[] types = new TypeMirror [args.Length];
+			Value[] values = new Value[args.Length];
+			for (int n = 0; n < args.Length; n++) {
+				types[n] = ToTypeMirror (ctx, GetValueType (ctx, args[n]));
+				values[n] = (Value) args[n];
+			}
+			
+			MethodMirror ctor = OverloadResolve (cx, t, ".ctor", null, types, true, true, true);
+			if (ctor == null)
+				return null;
+
+			return t.NewInstance (cx.Thread, ctor, values);
+		}
+
+		public override object CreateValue (EvaluationContext ctx, object value)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			if (value is string)
+				return cx.Thread.Domain.CreateString ((string)value);
+
+			return cx.Session.VirtualMachine.CreateValue (value);
+		}
+
+		public override object GetBaseValue (EvaluationContext ctx, object val)
+		{
+			return val;
+		}
+
+		public override bool NullableHasValue (EvaluationContext ctx, object type, object obj)
+		{
+			ValueReference hasValue = GetMember (ctx, type, obj, "has_value");
+
+			return (bool) hasValue.ObjectValue;
+		}
+
+		public override ValueReference NullableGetValue (EvaluationContext ctx, object type, object obj)
+		{
+			return GetMember (ctx, type, obj, "value");
+		}
+
+		public override object GetEnclosingType (EvaluationContext ctx)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			return cx.Frame.Method.DeclaringType;
+		}
+
+		public override string[] GetImportedNamespaces (EvaluationContext ctx)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			HashSet<string> namespaces = new HashSet<string> ();
+			foreach (TypeMirror type in cx.Session.GetAllTypes ())
+				namespaces.Add (type.Namespace);
+			
+			string[] nss = new string [namespaces.Count];
+			namespaces.CopyTo (nss);
+			return nss;
+		}
+
+		public override ValueReference GetIndexerReference (EvaluationContext ctx, object target, object[] indices)
+		{
+			object valueType = GetValueType (ctx, target);
+			TypeMirror targetType = null;
+
+			if (valueType is Type)
+				targetType = (TypeMirror) ForceLoadType (ctx, ((Type) valueType).FullName);
+			else if (valueType is TypeMirror)
+				targetType = (TypeMirror) valueType;
+			else
+				return null;
+			
+			Value[] values = new Value [indices.Length];
+			TypeMirror[] types = new TypeMirror [indices.Length];
+			for (int n=0; n<indices.Length; n++) {
+				types [n] = ToTypeMirror (ctx, GetValueType (ctx, indices [n]));
+				values [n] = (Value) indices [n];
+			}
+			
+			List<MethodMirror> candidates = new List<MethodMirror> ();
+			List<PropertyInfoMirror> props = new List<PropertyInfoMirror> ();
+			
+			TypeMirror type = targetType;
+			while (type != null) {
+				foreach (PropertyInfoMirror prop in type.GetProperties ()) {
+					MethodMirror met = prop.GetGetMethod (true);
+					if (met != null && !met.IsStatic && met.GetParameters ().Length > 0) {
+						candidates.Add (met);
+						props.Add (prop);
+					}
+				}
+				type = type.BaseType;
+			}
+			
+			MethodMirror idx = OverloadResolve ((SoftEvaluationContext) ctx, targetType, null, null, types, candidates, true);
+			int i = candidates.IndexOf (idx);
+			
+			MethodMirror getter = props[i].GetGetMethod (true);
+			if (getter == null)
+				return null;
+			
+			return new PropertyValueReference (ctx, props[i], target, null, getter, values);
+		}
+		
+		static bool InGeneratedClosureOrIteratorType (EvaluationContext ctx)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			if (cx.Frame.Method.IsStatic)
+				return false;
+			TypeMirror tm = cx.Frame.Method.DeclaringType;
+			return IsGeneratedType (tm);
+		}
+		
+		internal static bool IsGeneratedType (TypeMirror tm)
+		{
+			//
+			// This should cover all C# generated special containers
+			// - anonymous methods
+			// - lambdas
+			// - iterators
+			// - async methods
+			//
+			// which allow stepping into
+			//
+			return tm.Name[0] == '<' &&
+				// mcs is of the form <${NAME}>.c__{KIND}${NUMBER}
+				(tm.Name.IndexOf (">c__", StringComparison.Ordinal) > 0 ||
+				// csc is of form <${NAME}>d__${NUMBER}
+				 tm.Name.IndexOf (">d__", StringComparison.Ordinal) > 0);
+		}
+
+		internal static string GetNameFromGeneratedType (TypeMirror tm)
+		{
+			return tm.Name.Substring (1, tm.Name.IndexOf ('>') - 1);
+		}
+		
+		static bool IsHoistedThisReference (FieldInfoMirror field)
+		{
+			// mcs is "<>f__this" or "$this" (if in an async compiler generated type)
+			// csc is "<>4__this"
+			return field.Name == "$this" ||
+				(field.Name.StartsWith ("<>", StringComparison.Ordinal) &&
+				 field.Name.EndsWith ("__this", StringComparison.Ordinal));
+		}
+		
+		static bool IsClosureReferenceField (FieldInfoMirror field)
+		{
+			// mcs is "<>f__ref"
+			// csc is "CS$<>"
+			return field.Name.StartsWith ("CS$<>", StringComparison.Ordinal) ||
+				field.Name.StartsWith ("<>f__ref", StringComparison.Ordinal);
+		}
+		
+		static bool IsClosureReferenceLocal (LocalVariable local)
+		{
+			if (local.Name == null)
+				return false;
+
+			// mcs is "$locvar" or starts with '<'
+			// csc is "CS$<>"
+			return local.Name.Length == 0 || local.Name[0] == '<' || local.Name.StartsWith ("$locvar", StringComparison.Ordinal) ||
+				local.Name.StartsWith ("CS$<>", StringComparison.Ordinal);
+		}
+		
+		static bool IsGeneratedTemporaryLocal (LocalVariable local)
+		{
+			// csc uses CS$ prefix for temporary variables and <>t__ prefix for async task-related state variables
+			return local.Name != null && (local.Name.StartsWith ("CS$", StringComparison.Ordinal) || local.Name.StartsWith ("<>t__", StringComparison.Ordinal));
+		}
+		
+		static string GetHoistedIteratorLocalName (FieldInfoMirror field)
+		{
+			//mcs captured args, of form <$>name
+			if (field.Name.StartsWith ("<$>", StringComparison.Ordinal)) {
+				return field.Name.Substring (3);
+			}
+			
+			// csc, mcs locals of form <name>__0
+			if (field.Name[0] == '<') {
+				int i = field.Name.IndexOf ('>');
+				if (i > 1) {
+					return field.Name.Substring (1, i - 1);
+				}
+			}
+			return null;
+		}
+
+		IEnumerable<ValueReference> GetHoistedLocalVariables (SoftEvaluationContext cx, ValueReference vthis)
+		{
+			if (vthis == null)
+				return new ValueReference [0];
+			
+			object val = vthis.Value;
+			if (IsNull (cx, val))
+				return new ValueReference [0];
+			
+			TypeMirror tm = (TypeMirror) vthis.Type;
+			bool isIterator = IsGeneratedType (tm);
+			
+			var list = new List<ValueReference> ();
+			TypeMirror type = (TypeMirror) vthis.Type;
+			foreach (FieldInfoMirror field in type.GetFields ()) {
+				if (IsHoistedThisReference (field))
+					continue;
+				if (IsClosureReferenceField (field)) {
+					list.AddRange (GetHoistedLocalVariables (cx, new FieldValueReference (cx, field, val, type)));
+					continue;
+				}
+				if (field.Name[0] == '<') {
+					if (isIterator) {
+						var name = GetHoistedIteratorLocalName (field);
+						if (!string.IsNullOrEmpty (name)) {
+							list.Add (new FieldValueReference (cx, field, val, type, name, ObjectValueFlags.Variable));
+						}
+					}
+				} else if (!field.Name.Contains ("$")) {
+					list.Add (new FieldValueReference (cx, field, val, type, field.Name, ObjectValueFlags.Variable));
+				}
+			}
+			return list;
+		}
+		
+		ValueReference GetHoistedThisReference (SoftEvaluationContext cx)
+		{
+			try {
+				Value val = cx.Frame.GetThis ();
+				TypeMirror type = (TypeMirror) GetValueType (cx, val);
+				return GetHoistedThisReference (cx, type, val);
+			} catch (AbsentInformationException) {
+			}
+			return null;
+		}
+		
+		ValueReference GetHoistedThisReference (SoftEvaluationContext cx, TypeMirror type, object val)
+		{
+			foreach (FieldInfoMirror field in type.GetFields ()) {
+				if (IsHoistedThisReference (field))
+					return new FieldValueReference (cx, field, val, type, "this", ObjectValueFlags.Literal);
+
+				if (IsClosureReferenceField (field)) {
+					var fieldRef = new FieldValueReference (cx, field, val, type);
+					var thisRef = GetHoistedThisReference (cx, field.FieldType, fieldRef.Value);
+					if (thisRef != null)
+						return thisRef;
+				}
+			}
+
+			return null;
+		}
+		
+		// if the local does not have a name, constructs one from the index
+		static string GetLocalName (SoftEvaluationContext cx, LocalVariable local)
+		{
+			if (!string.IsNullOrEmpty (local.Name) || cx.SourceCodeAvailable)
+				return local.Name;
+			return "loc" + local.Index;
+		}
+		
+		protected override ValueReference OnGetLocalVariable (EvaluationContext ctx, string name)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			if (InGeneratedClosureOrIteratorType (cx))
+				return FindByName (OnGetLocalVariables (cx), v => v.Name, name, ctx.CaseSensitive);
+			
+			try {
+				LocalVariable local = null;
+				if (!cx.SourceCodeAvailable) {
+					if (name.StartsWith ("loc", StringComparison.Ordinal)) {
+						int idx;
+						if (int.TryParse (name.Substring (3), out idx))
+							local = cx.Frame.Method.GetLocals ().FirstOrDefault (loc => loc.Index == idx);
+					}
+				} else {
+					local = ctx.CaseSensitive
+						? cx.Frame.GetVisibleVariableByName (name)
+						: FindByName (cx.Frame.GetVisibleVariables(), v => v.Name, name, false);
+				}
+				if (local != null) {
+					return new VariableValueReference (ctx, GetLocalName (cx, local), local);
+				}
+				return FindByName (OnGetLocalVariables (ctx), v => v.Name, name, ctx.CaseSensitive);
+			} catch (AbsentInformationException) {
+				return null;
+			}
+		}
+
+		protected override IEnumerable<ValueReference> OnGetLocalVariables (EvaluationContext ctx)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			if (InGeneratedClosureOrIteratorType (cx)) {
+				ValueReference vthis = GetThisReference (cx);
+				return GetHoistedLocalVariables (cx, vthis).Union (GetLocalVariables (cx));
+			}
+
+			return GetLocalVariables (cx);
+		}
+		
+		IEnumerable<ValueReference> GetLocalVariables (SoftEvaluationContext cx)
+		{
+			IList<LocalVariable> locals;
+			try {
+				locals = cx.Frame.GetVisibleVariables ();
+			} catch (AbsentInformationException) {
+				yield break;
+			}
+			foreach (LocalVariable local in locals) {
+				if (local.IsArg)
+					continue;
+				if (IsClosureReferenceLocal (local) && IsGeneratedType (local.Type)) {
+					foreach (var gv in GetHoistedLocalVariables (cx, new VariableValueReference (cx, local.Name, local))) {
+						yield return gv;
+					}
+				} else if (!IsGeneratedTemporaryLocal (local)) {
+					yield return new VariableValueReference (cx, GetLocalName (cx, local), local);
+				}
+			}
+		}
+
+		public override bool HasMember (EvaluationContext ctx, object type, string memberName, BindingFlags bindingFlags)
+		{
+			TypeMirror tm = (TypeMirror) type;
+
+			while (tm != null) {
+				FieldInfoMirror field = FindByName (tm.GetFields (), f => f.Name, memberName, ctx.CaseSensitive);
+				if (field != null)
+					return true;
+
+				PropertyInfoMirror prop = FindByName (tm.GetProperties (), p => p.Name, memberName, ctx.CaseSensitive);
+				if (prop != null) {
+					MethodMirror getter = prop.GetGetMethod (bindingFlags.HasFlag (BindingFlags.NonPublic));
+					if (getter != null)
+						return true;
+				}
+
+				if (bindingFlags.HasFlag (BindingFlags.DeclaredOnly))
+					break;
+
+				tm = tm.BaseType;
+			}
+
+			return false;
+		}
+
+		static bool IsAnonymousType (TypeMirror type)
+		{
+			return type.Name.StartsWith ("<>__AnonType", StringComparison.Ordinal);
+		}
+
+		protected override ValueReference GetMember (EvaluationContext ctx, object t, object co, string name)
+		{
+			TypeMirror type = t as TypeMirror;
+
+			while (type != null) {
+				FieldInfoMirror field = FindByName (type.GetFields (), f => f.Name, name, ctx.CaseSensitive);
+				if (field != null && (field.IsStatic || co != null))
+					return new FieldValueReference (ctx, field, co, type);
+
+				PropertyInfoMirror prop = FindByName (type.GetProperties (), p => p.Name, name, ctx.CaseSensitive);
+				if (prop != null && (IsStatic (prop) || co != null)) {
+					// Optimization: if the property has a CompilerGenerated backing field, use that instead.
+					// This way we avoid overhead of invoking methods on the debugee when the value is requested.
+					string cgFieldName = string.Format ("<{0}>{1}", prop.Name, IsAnonymousType (type) ? "" : "k__BackingField");
+					if ((field = FindByName (type.GetFields (), f => f.Name, cgFieldName, true)) != null && IsCompilerGenerated (field))
+						return new FieldValueReference (ctx, field, co, type, prop.Name, ObjectValueFlags.Property);
+
+					// Backing field not available, so do things the old fashioned way.
+					MethodMirror getter = prop.GetGetMethod (true);
+					if (getter == null)
+						return null;
+					
+					return new PropertyValueReference (ctx, prop, co, type, getter, null);
+				}
+
+				type = type.BaseType;
+			}
+
+			return null;
+		}
+
+		static bool IsCompilerGenerated (FieldInfoMirror field)
+		{
+			var attrs = field.GetCustomAttributes (true);
+			var generated = GetAttribute<CompilerGeneratedAttribute> (attrs);
+
+			return generated != null;
+		}
+		
+		static bool IsStatic (PropertyInfoMirror prop)
+		{
+			MethodMirror met = prop.GetGetMethod (true) ?? prop.GetSetMethod (true);
+			return met.IsStatic;
+		}
+		
+		static T FindByName<T> (IEnumerable<T> elems, Func<T,string> getName, string name, bool caseSensitive)
+		{
+			T best = default(T);
+			foreach (T t in elems) {
+				string n = getName (t);
+				if (n == name) 
+					return t;
+				if (!caseSensitive && n.Equals (name, StringComparison.CurrentCultureIgnoreCase))
+					best = t;
+			}
+			return best;
+		}
+		
+		protected override IEnumerable<ValueReference> GetMembers (EvaluationContext ctx, object t, object co, BindingFlags bindingFlags)
+		{
+			Dictionary<string, PropertyInfoMirror> subProps = new Dictionary<string, PropertyInfoMirror> ();
+			TypeMirror type = t as TypeMirror;
+			TypeMirror realType = null;
+			if (co != null && (bindingFlags & BindingFlags.Instance) != 0)
+				realType = GetValueType (ctx, co) as TypeMirror;
+
+			// First of all, get a list of properties overriden in sub-types
+			while (realType != null && realType != type) {
+				foreach (PropertyInfoMirror prop in realType.GetProperties (bindingFlags | BindingFlags.DeclaredOnly)) {
+					MethodMirror met = prop.GetGetMethod (true);
+					if (met == null || met.GetParameters ().Length != 0 || met.IsAbstract || !met.IsVirtual || met.IsStatic)
+						continue;
+					if (met.IsPublic && ((bindingFlags & BindingFlags.Public) == 0))
+						continue;
+					if (!met.IsPublic && ((bindingFlags & BindingFlags.NonPublic) == 0))
+						continue;
+					subProps [prop.Name] = prop;
+				}
+				realType = realType.BaseType;
+			}
+			
+			while (type != null) {
+				foreach (FieldInfoMirror field in type.GetFields ()) {
+					if (field.IsStatic && ((bindingFlags & BindingFlags.Static) == 0))
+						continue;
+					if (!field.IsStatic && ((bindingFlags & BindingFlags.Instance) == 0))
+						continue;
+					if (field.IsPublic && ((bindingFlags & BindingFlags.Public) == 0))
+						continue;
+					if (!field.IsPublic && ((bindingFlags & BindingFlags.NonPublic) == 0))
+						continue;
+					yield return new FieldValueReference (ctx, field, co, type);
+				}
+				foreach (PropertyInfoMirror prop in type.GetProperties (bindingFlags)) {
+					MethodMirror getter = prop.GetGetMethod (true);
+					if (getter == null || getter.GetParameters ().Length != 0 || getter.IsAbstract)
+						continue;
+					if (getter.IsStatic && ((bindingFlags & BindingFlags.Static) == 0))
+						continue;
+					if (!getter.IsStatic && ((bindingFlags & BindingFlags.Instance) == 0))
+						continue;
+					if (getter.IsPublic && ((bindingFlags & BindingFlags.Public) == 0))
+						continue;
+					if (!getter.IsPublic && ((bindingFlags & BindingFlags.NonPublic) == 0))
+						continue;
+					
+					// If a property is overriden, return the override instead of the base property
+					PropertyInfoMirror overridden;
+					if (getter.IsVirtual && subProps.TryGetValue (prop.Name, out overridden)) {
+						getter = overridden.GetGetMethod (true);
+						if (getter == null)
+							continue;
+						
+						yield return new PropertyValueReference (ctx, overridden, co, overridden.DeclaringType, getter, null);
+					} else {
+						yield return new PropertyValueReference (ctx, prop, co, type, getter, null);
+					}
+				}
+				if ((bindingFlags & BindingFlags.DeclaredOnly) != 0)
+					break;
+				type = type.BaseType;
+			}
+		}
+
+		static bool IsIEnumerable (TypeMirror type)
+		{
+			if (!type.IsInterface)
+				return false;
+
+			if (type.Namespace == "System.Collections" && type.Name == "IEnumerable")
+				return true;
+
+			if (type.Namespace == "System.Collections.Generic" && type.Name == "IEnumerable`1")
+				return true;
+
+			return false;
+		}
+
+		protected override CompletionData GetMemberCompletionData (EvaluationContext ctx, ValueReference vr)
+		{
+			HashSet<string> properties = new HashSet<string> ();
+			HashSet<string> methods = new HashSet<string> ();
+			HashSet<string> fields = new HashSet<string> ();
+			CompletionData data = new CompletionData ();
+			var type = vr.Type as TypeMirror;
+			bool isEnumerable = false;
+
+			while (type != null) {
+				if (!isEnumerable && IsIEnumerable (type))
+					isEnumerable = true;
+
+				foreach (var field in type.GetFields ()) {
+					if (field.IsStatic || field.IsSpecialName || !field.IsPublic)
+						continue;
+
+					if (fields.Add (field.Name))
+						data.Items.Add (new CompletionItem (field.Name, FieldValueReference.GetFlags (field)));
+				}
+
+				foreach (var property in type.GetProperties ()) {
+					var getter = property.GetGetMethod (true);
+
+					if (getter == null || getter.IsStatic || !getter.IsPublic)
+						continue;
+
+					if (properties.Add (property.Name))
+						data.Items.Add (new CompletionItem (property.Name, PropertyValueReference.GetFlags (property, getter)));
+				}
+
+				foreach (var method in type.GetMethods ()) {
+					if (method.IsStatic || method.IsConstructor || method.IsSpecialName || !method.IsPublic)
+						continue;
+
+					if (methods.Add (method.Name))
+						data.Items.Add (new CompletionItem (method.Name, ObjectValueFlags.Method | ObjectValueFlags.Public));
+				}
+
+				if (type.BaseType == null && type.FullName != "System.Object")
+					type = ctx.Adapter.GetType (ctx, "System.Object") as TypeMirror;
+				else
+					type = type.BaseType;
+			}
+
+			type = (TypeMirror) vr.Type;
+			foreach (var iface in type.GetInterfaces ()) {
+				if (!isEnumerable && IsIEnumerable (iface))
+					isEnumerable = true;
+			}
+
+			if (isEnumerable) {
+				// Look for LINQ extension methods...
+				var linq = ctx.Adapter.GetType (ctx, "System.Linq.Enumerable") as TypeMirror;
+				if (linq != null) {
+					foreach (var method in linq.GetMethods ()) {
+						if (!method.IsStatic || method.IsConstructor || method.IsSpecialName || !method.IsPublic)
+							continue;
+
+						if (methods.Add (method.Name))
+							data.Items.Add (new CompletionItem (method.Name, ObjectValueFlags.Method | ObjectValueFlags.Public));
+					}
+				}
+			}
+
+			data.ExpressionLength = 0;
+
+			return data;
+		}
+		
+		public override void GetNamespaceContents (EvaluationContext ctx, string namspace, out string[] childNamespaces, out string[] childTypes)
+		{
+			var soft = (SoftEvaluationContext) ctx;
+			var types = new HashSet<string> ();
+			var namespaces = new HashSet<string> ();
+			var namspacePrefix = namspace.Length > 0 ? namspace + "." : "";
+
+			foreach (var type in soft.Session.GetAllTypes ()) {
+				if (type.Namespace == namspace || type.Namespace.StartsWith (namspacePrefix, StringComparison.InvariantCulture)) {
+					namespaces.Add (type.Namespace);
+					types.Add (type.FullName);
+				}
+			}
+
+			childNamespaces = new string [namespaces.Count];
+			namespaces.CopyTo (childNamespaces);
+			
+			childTypes = new string [types.Count];
+			types.CopyTo (childTypes);
+		}
+
+		protected override IEnumerable<ValueReference> OnGetParameters (EvaluationContext ctx)
+		{
+			SoftEvaluationContext soft = (SoftEvaluationContext) ctx;
+			LocalVariable[] locals;
+
+			try {
+				locals = soft.Frame.Method.GetLocals ();
+			} catch (AbsentInformationException) {
+				yield break;
+			}
+				
+			foreach (LocalVariable var in locals) {
+				if (var.IsArg) {
+					string name = !string.IsNullOrEmpty (var.Name) ? var.Name : "arg" + var.Index;
+					yield return new VariableValueReference (ctx, name, var);
+				}
+			}
+		}
+
+		protected override ValueReference OnGetThisReference (EvaluationContext ctx)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+			if (InGeneratedClosureOrIteratorType (cx))
+				return GetHoistedThisReference (cx);
+
+			return GetThisReference (cx);
+		}
+		
+		ValueReference GetThisReference (SoftEvaluationContext cx)
+		{
+			try {
+				if (cx.Frame.Method.IsStatic)
+					return null;
+				Value val = cx.Frame.GetThis ();
+				return LiteralValueReference.CreateTargetObjectLiteral (cx, "this", val);
+			} catch (AbsentInformationException) {
+				return null;
+			}
+		}
+		
+		public override ValueReference GetCurrentException (EvaluationContext ctx)
+		{
+			try {
+				SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+				ObjectMirror exc = cx.Session.GetExceptionObject (cx.Thread);
+				if (exc != null)
+					return LiteralValueReference.CreateTargetObjectLiteral (ctx, ctx.Options.CurrentExceptionTag, exc);
+
+				return null;
+			} catch (AbsentInformationException) {
+				return null;
+			}
+		}
+
+		public override bool IsGenericType (EvaluationContext ctx, object type)
+		{
+			return type != null && ((TypeMirror) type).IsGenericType;
+		}
+
+		public override object[] GetTypeArgs (EvaluationContext ctx, object type)
+		{
+			TypeMirror tm = (TypeMirror) type;
+
+			if (tm.VirtualMachine.Version.AtLeast (2, 15))
+				return tm.GetGenericArguments ();
+
+			// fall back to parsing them from the from the FullName
+			List<string> names = new List<string> ();
+			string s = tm.FullName;
+			int i = s.IndexOf ('`');
+
+			if (i != -1) {
+				i = s.IndexOf ('[', i);
+				if (i == -1)
+					return new object [0];
+				int si = ++i;
+				int nt = 0;
+				for (; i < s.Length && (nt > 0 || s[i] != ']'); i++) {
+					if (s[i] == '[')
+						nt++;
+					else if (s[i] == ']')
+						nt--;
+					else if (s[i] == ',' && nt == 0) {
+						names.Add (s.Substring (si, i - si));
+						si = i + 1;
+					}
+				}
+				names.Add (s.Substring (si, i - si));
+				object[] types = new object [names.Count];
+				for (int n=0; n<names.Count; n++) {
+					string tn = names [n];
+					if (tn.StartsWith ("[", StringComparison.Ordinal))
+						tn = tn.Substring (1, tn.Length - 2);
+					types [n] = GetType (ctx, tn);
+					if (types [n] == null)
+						return new object [0];
+				}
+				return types;
+			}
+
+			return new object [0];
+		}
+
+		public override object GetType (EvaluationContext ctx, string name, object[] typeArgs)
+		{
+			SoftEvaluationContext cx = (SoftEvaluationContext) ctx;
+
+			int i = name.IndexOf (',');
+			if (i != -1) {
+				// Find first comma outside brackets
+				int nest = 0;
+				for (int n = 0; n < name.Length; n++) {
+					char c = name [n];
+					if (c == '[')
+						nest++;
+					else if (c == ']')
+						nest--;
+					else if (c == ',' && nest == 0) {
+						name = name.Substring (0, n).Trim ();
+						break;
+					}
+				}
+			}
+			
+			if (typeArgs != null && typeArgs.Length > 0) {
+				string args = "";
+				foreach (object t in typeArgs) {
+					if (args.Length > 0)
+						args += ",";
+					string tn;
+					if (t is TypeMirror) {
+						TypeMirror atm = (TypeMirror) t;
+						tn = atm.FullName + "," + atm.Assembly.GetName ();
+					} else {
+						Type atm = (Type) t;
+						tn = atm.FullName + "," + atm.Assembly.GetName ();
+					}
+					if (tn.IndexOf (',') != -1)
+						tn = "[" + tn + "]";
+					args += tn;
+				}
+				name += "[" +args + "]";
+			}
+			
+			TypeMirror tm = cx.Session.GetType (name);
+			if (tm != null)
+				return tm;
+
+			foreach (AssemblyMirror asm in cx.Thread.Domain.GetAssemblies ()) {
+				tm = asm.GetType (name, false, false);
+				if (tm != null)
+					return tm;
+			}
+			return null;
+		}
+
+		public override object GetParentType (EvaluationContext ctx, object type)
+		{
+			TypeMirror tm = type as TypeMirror;
+
+			if (tm != null) {
+				int plus = tm.FullName.LastIndexOf ('+');
+
+				return plus != -1 ? GetType (ctx, tm.FullName.Substring (0, plus)) : null;
+			}
+
+			return ((Type) type).DeclaringType;
+		}
+
+		public override IEnumerable<object> GetNestedTypes (EvaluationContext ctx, object type)
+		{
+			TypeMirror t = (TypeMirror) type;
+			foreach (TypeMirror nt in t.GetNestedTypes ())
+				yield return nt;
+		}
+		
+		public override string GetTypeName (EvaluationContext ctx, object type)
+		{
+			TypeMirror tm = type as TypeMirror;
+			if (tm != null) {
+				if (IsGeneratedType (tm)) {
+					// Return the name of the container-type.
+					return tm.FullName.Substring (0, tm.FullName.LastIndexOf ('+'));
+				}
+				
+				return tm.FullName;
+			}
+
+			return ((Type)type).FullName;
+		}
+		
+		public override object GetValueType (EvaluationContext ctx, object val)
+		{
+			if (val == null)
+				return typeof (Object);
+			if (val is ArrayMirror)
+				return ((ArrayMirror)val).Type;
+			if (val is ObjectMirror)
+				return ((ObjectMirror)val).Type;
+			if (val is EnumMirror)
+				return ((EnumMirror)val).Type;
+			if (val is StructMirror)
+				return ((StructMirror)val).Type;
+			if (val is PointerValue)
+				return ((PointerValue) val).Type;
+			if (val is PrimitiveValue) {
+				PrimitiveValue pv = (PrimitiveValue) val;
+				if (pv.Value == null)
+					return typeof(Object);
+
+				return pv.Value.GetType ();
+			}
+
+			throw new NotSupportedException ();
+		}
+		
+		public override object GetBaseType (EvaluationContext ctx, object type)
+		{
+			if (type is TypeMirror)
+				return ((TypeMirror)type).BaseType;
+
+			return null;
+		}
+
+		public override bool HasMethod (EvaluationContext ctx, object targetType, string methodName, object[] genericTypeArgs, object[] argTypes, BindingFlags flags)
+		{
+			SoftEvaluationContext soft = (SoftEvaluationContext) ctx;
+			TypeMirror[] typeArgs = null;
+			TypeMirror[] types = null;
+
+			if (genericTypeArgs != null) {
+				typeArgs = new TypeMirror [genericTypeArgs.Length];
+				for (int n = 0; n < genericTypeArgs.Length; n++) {
+					if (genericTypeArgs[n] is TypeMirror)
+						typeArgs[n] = (TypeMirror) genericTypeArgs[n];
+					else
+						typeArgs[n] = (TypeMirror) GetType (soft, ((Type) genericTypeArgs[n]).FullName);
+				}
+			}
+
+			if (argTypes != null) {
+				types = new TypeMirror [argTypes.Length];
+				for (int n = 0; n < argTypes.Length; n++) {
+					if (argTypes[n] is TypeMirror)
+						types[n] = (TypeMirror) argTypes[n];
+					else
+						types[n] = (TypeMirror) GetType (soft, ((Type) argTypes[n]).FullName);
+				}
+			}
+			
+			MethodMirror method = OverloadResolve (soft, (TypeMirror) targetType, methodName, typeArgs, types, (flags & BindingFlags.Instance) != 0, (flags & BindingFlags.Static) != 0, false);
+			return method != null;
+		}
+		
+		public override bool IsExternalType (EvaluationContext ctx, object type)
+		{
+			TypeMirror tm = type as TypeMirror;
+
+			if (tm != null)
+				return ((SoftEvaluationContext) ctx).Session.IsExternalCode (tm);
+
+			return true;
+		}
+
+		public override bool IsString (EvaluationContext ctx, object val)
+		{
+			return val is StringMirror;
+		}
+		
+		public override bool IsArray (EvaluationContext ctx, object val)
+		{
+			return val is ArrayMirror;
+		}
+
+		public override bool IsValueType (object type)
+		{
+			TypeMirror t = type as TypeMirror;
+			return t != null && t.IsValueType;
+		}
+
+		public override bool IsClass (EvaluationContext ctx, object type)
+		{
+			TypeMirror t = type as TypeMirror;
+			return t != null && (t.IsClass || t.IsValueType) && !t.IsPrimitive;
+		}
+
+		public override bool IsNull (EvaluationContext ctx, object val)
+		{
+			return val == null || ((val is PrimitiveValue) && ((PrimitiveValue)val).Value == null) || ((val is PointerValue) && ((PointerValue)val).Address == 0);
+		}
+
+		public override bool IsPrimitive (EvaluationContext ctx, object val)
+		{
+			return val is PrimitiveValue || val is StringMirror || ((val is StructMirror) && ((StructMirror)val).Type.IsPrimitive) || val is PointerValue;
+		}
+
+		public override bool IsPointer (EvaluationContext ctx, object val)
+		{
+			return val is PointerValue;
+		}
+
+		public override bool IsEnum (EvaluationContext ctx, object val)
+		{
+			return val is EnumMirror;
+		}
+		
+		protected override TypeDisplayData OnGetTypeDisplayData (EvaluationContext ctx, object type)
+		{
+			SoftEvaluationContext soft = (SoftEvaluationContext) ctx;
+
+			Dictionary<string, DebuggerBrowsableState> memberData = null;
+			bool isCompilerGenerated = false;
+			string displayValue = null;
+			string displayName = null;
+			string displayType = null;
+			string proxyType = null;
+
+
+			try {
+				var tm = (TypeMirror) type;
+				foreach (var attr in tm.GetCustomAttributes (true)) {
+					string attrName = attr.Constructor.DeclaringType.FullName;
+					if (attrName == "System.Diagnostics.DebuggerDisplayAttribute") {
+						var display = BuildAttribute<DebuggerDisplayAttribute> (attr);
+						displayValue = display.Value;
+						displayName = display.Name;
+						displayType = display.Type;
+					} else if (attrName == "System.Diagnostics.DebuggerTypeProxyAttribute") {
+						var proxy = BuildAttribute<DebuggerTypeProxyAttribute> (attr);
+						proxyType = proxy.ProxyTypeName;
+						if (!string.IsNullOrEmpty (proxyType))
+							ForceLoadType (soft, proxyType);
+					} else if (attrName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") {
+						isCompilerGenerated = true;
+					}
+				}
+
+				foreach (var field in tm.GetFields ()) {
+					var attrs = field.GetCustomAttributes (true);
+					var browsable = GetAttribute <DebuggerBrowsableAttribute> (attrs);
+
+					if (browsable == null) {
+						var generated = GetAttribute<CompilerGeneratedAttribute> (attrs);
+						if (generated != null)
+							browsable = new DebuggerBrowsableAttribute (DebuggerBrowsableState.Never);
+					}
+
+					if (browsable != null) {
+						if (memberData == null)
+							memberData = new Dictionary<string, DebuggerBrowsableState> ();
+						memberData [field.Name] = browsable.State;
+					}
+				}
+
+				foreach (var property in tm.GetProperties ()) {
+					var browsable = GetAttribute <DebuggerBrowsableAttribute> (property.GetCustomAttributes (true));
+					if (browsable != null) {
+						if (memberData == null)
+							memberData = new Dictionary<string, DebuggerBrowsableState> ();
+						memberData [property.Name] = browsable.State;
+					}
+				}
+			} catch (Exception ex) {
+				soft.Session.WriteDebuggerOutput (true, ex.ToString ());
+			}
+
+			return new TypeDisplayData (proxyType, displayValue, displayType, displayName, isCompilerGenerated, memberData);
+		}
+		
+		static T GetAttribute<T> (CustomAttributeDataMirror[] attrs)
+		{
+			foreach (var attr in attrs) {
+				if (attr.Constructor.DeclaringType.FullName == typeof(T).FullName)
+					return BuildAttribute<T> (attr);
+			}
+
+			return default(T);
+		}
+
+		public override bool IsTypeLoaded (EvaluationContext ctx, string typeName)
+		{
+			var soft = (SoftEvaluationContext) ctx;
+			
+			return soft.Session.GetType (typeName) != null;
+		}
+		
+		public override bool IsTypeLoaded (EvaluationContext ctx, object type)
+		{
+			var tm = (TypeMirror) type;
+
+			if (tm.VirtualMachine.Version.AtLeast (2, 23))
+				return tm.IsInitialized;
+
+			return IsTypeLoaded (ctx, tm.FullName);
+		}
+
+		public override bool ForceLoadType (EvaluationContext ctx, object type)
+		{
+			var soft = (SoftEvaluationContext) ctx;
+			var tm = (TypeMirror) type;
+
+			if (!tm.VirtualMachine.Version.AtLeast (2, 23))
+				return IsTypeLoaded (ctx, tm.FullName);
+
+			if (tm.IsInitialized)
+				return true;
+
+			if (!tm.Attributes.HasFlag (TypeAttributes.BeforeFieldInit))
+				return false;
+
+			MethodMirror cctor = OverloadResolve (soft, tm, ".cctor", null, new TypeMirror[0], false, true, false);
+			if (cctor == null)
+				return true;
+
+			try {
+				tm.InvokeMethod (soft.Thread, cctor, new Value[0], InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded);
+			} catch {
+				return false;
+			} finally {
+				soft.Session.StackVersion++;
+			}
+
+			return true;
+		}
+		
+		static T BuildAttribute<T> (CustomAttributeDataMirror attr)
+		{
+			List<object> args = new List<object> ();
+
+			foreach (CustomAttributeTypedArgumentMirror arg in attr.ConstructorArguments) {
+				object val = arg.Value;
+				if (val is TypeMirror) {
+					// The debugger attributes that take a type as parameter of the constructor have
+					// a corresponding constructor overload that takes a type name. We'll use that
+					// constructor because we can't load target types in the debugger process.
+					// So what we do here is convert the Type to a String.
+					TypeMirror tm = (TypeMirror) val;
+					val = tm.FullName + ", " + tm.Assembly.ManifestModule.Name;
+				} else if (val is EnumMirror) {
+					EnumMirror em = (EnumMirror) val;
+					val = em.Value;
+				}
+				args.Add (val);
+			}
+
+			Type type = typeof(T);
+			object at = Activator.CreateInstance (type, args.ToArray ());
+			foreach (CustomAttributeNamedArgumentMirror arg in attr.NamedArguments) {
+				object val = arg.TypedValue.Value;
+				string postFix = "";
+				if (arg.TypedValue.ArgumentType == typeof(Type))
+					postFix = "TypeName";
+				if (arg.Field != null)
+					type.GetField (arg.Field.Name + postFix).SetValue (at, val);
+				else if (arg.Property != null)
+					type.GetProperty (arg.Property.Name + postFix).SetValue (at, val, null);
+			}
+
+			return (T) at;
+		}
+		
+		TypeMirror ToTypeMirror (EvaluationContext ctx, object type)
+		{
+			TypeMirror t = type as TypeMirror;
+			if (t != null)
+				return t;
+			return (TypeMirror) GetType (ctx, ((Type)type).FullName);
+		}
+
+		public override object RuntimeInvoke (EvaluationContext ctx, object targetType, object target, string methodName, object[] argTypes, object[] argValues)
+		{
+			return RuntimeInvoke (ctx, targetType, target, methodName, new object [0], argTypes, argValues);
+		}
+
+		public override object RuntimeInvoke (EvaluationContext ctx, object targetType, object target, string methodName, object[] genericTypeArgs, object[] argTypes, object[] argValues)
+		{
+			var type = ToTypeMirror (ctx, targetType);
+			var soft = (SoftEvaluationContext) ctx;
+
+			soft.AssertTargetInvokeAllowed ();
+
+			TypeMirror[] genericTypes = new TypeMirror [genericTypeArgs != null ? genericTypeArgs.Length : 0];
+			for (int n = 0; n < genericTypes.Length; n++)
+				genericTypes[n] = ToTypeMirror (soft, genericTypeArgs[n]);
+
+			TypeMirror[] types = new TypeMirror [argTypes.Length];
+			for (int n = 0; n < argTypes.Length; n++)
+				types[n] = ToTypeMirror (soft, argTypes[n]);
+
+			MethodMirror method = OverloadResolve (soft, type, methodName, genericTypes, types, target != null, target == null, true);
+
+			ParameterInfoMirror[] mparams = method.GetParameters ();
+			Value[] values = new Value [argValues.Length];
+			for (int n = 0; n < argValues.Length; n++) {
+				var param_type = mparams[n].ParameterType;
+
+				if (param_type.FullName != types[n].FullName && !param_type.IsAssignableFrom (types[n]) && param_type.IsGenericType) {
+					bool throwCastException = true;
+
+					if (method.VirtualMachine.Version.AtLeast (2, 15)) {
+						var args = param_type.GetGenericArguments ();
+
+						if (args.Length == genericTypes.Length) {
+							var real_type = soft.Adapter.GetType (soft, param_type.GetGenericTypeDefinition ().FullName, genericTypes);
+
+							values[n] = (Value) TryCast (soft, (Value) argValues[n], real_type);
+							if (!(values[n] == null && argValues[n] != null && !soft.Adapter.IsNull (soft, argValues[n])))
+								throwCastException = false;
+						}
+					}
+
+					if (throwCastException) {
+						string fromType = !IsGeneratedType (types[n]) ? soft.Adapter.GetDisplayTypeName (soft, types[n]) : types[n].FullName;
+						string toType = soft.Adapter.GetDisplayTypeName (soft, param_type);
+
+						throw new EvaluatorException ("Argument {0}: Cannot implicitly convert `{1}' to `{2}'", n, fromType, toType);
+					}
+				} else {
+					values[n] = (Value) argValues[n];
+				}
+			}
+
+			return soft.RuntimeInvoke (method, target ?? targetType, values);
+		}
+
+		public static MethodMirror OverloadResolve (SoftEvaluationContext ctx, TypeMirror type, string methodName, TypeMirror[] genericTypeArgs, TypeMirror[] argTypes, bool allowInstance, bool allowStatic, bool throwIfNotFound)
+		{
+			List<MethodMirror> candidates = new List<MethodMirror> ();
+			var cache = ctx.Session.OverloadResolveCache;
+			TypeMirror currentType = type;
+			
+			while (currentType != null) {
+				MethodMirror[] methods = null;
+				
+				if (ctx.CaseSensitive) {
+					lock (cache) {
+						cache.TryGetValue (Tuple.Create (currentType, methodName), out methods);
+					}
+				}
+				
+				if (methods == null) {
+					if (currentType.VirtualMachine.Version.AtLeast (2, 7))
+						methods = currentType.GetMethodsByNameFlags (methodName, BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static, !ctx.CaseSensitive);
+					else
+						methods = currentType.GetMethods ();
+					
+					if (ctx.CaseSensitive) {
+						lock (cache) {
+							cache [Tuple.Create (currentType, methodName)] = methods;
+						}
+					}
+				}
+				
+				foreach (MethodMirror method in methods) {
+					if (method.Name == methodName || (!ctx.CaseSensitive && method.Name.Equals (methodName, StringComparison.CurrentCultureIgnoreCase))) {
+						MethodMirror actualMethod;
+
+						if (genericTypeArgs != null && genericTypeArgs.Length > 0 && method.VirtualMachine.Version.AtLeast (2, 24) && method.IsGenericMethod) {
+							actualMethod = method.GetGenericMethodDefinition ().MakeGenericMethod (genericTypeArgs);
+						} else {
+							actualMethod = method;
+						}
+
+						ParameterInfoMirror[] parms = actualMethod.GetParameters ();
+						if (argTypes == null || parms.Length == argTypes.Length && ((actualMethod.IsStatic && allowStatic) || (!actualMethod.IsStatic && allowInstance)))
+							candidates.Add (actualMethod);
+					}
+				}
+
+				if (argTypes == null && candidates.Count > 0)
+					break; // when argtypes is null, we are just looking for *any* match (not a specific match)
+				
+				if (methodName == ".ctor")
+					break; // Can't create objects using constructor from base classes
+				
+				// Make sure that we always pull in at least System.Object methods (this is mostly needed for cases where 'type' was an interface)
+				if (currentType.BaseType == null && currentType.FullName != "System.Object")
+					currentType = ctx.Adapter.GetType (ctx, "System.Object") as TypeMirror;
+				else
+					currentType = currentType.BaseType;
+			}
+
+			return OverloadResolve (ctx, type, methodName, genericTypeArgs, argTypes, candidates, throwIfNotFound);
+		}
+
+		static bool IsApplicable (SoftEvaluationContext ctx, MethodMirror method, TypeMirror[] genericTypeArgs, TypeMirror[] types, out string error, out int matchCount)
+		{
+			ParameterInfoMirror[] mparams = method.GetParameters ();
+			matchCount = 0;
+
+			for (int i = 0; i < types.Length; i++) {
+				TypeMirror param_type = mparams[i].ParameterType;
+
+				if (param_type.FullName == types[i].FullName) {
+					matchCount++;
+					continue;
+				}
+
+				if (param_type.IsAssignableFrom (types[i]))
+					continue;
+
+				if (param_type.IsGenericType) {
+					if (genericTypeArgs != null && method.VirtualMachine.Version.AtLeast (2, 12)) {
+						// FIXME: how can we make this more definitive?
+						if (param_type.GetGenericArguments ().Length == genericTypeArgs.Length)
+							continue;
+					} else {
+						// no way to check... assume it'll work?
+						continue;
+					}
+				}
+
+				string fromType = !IsGeneratedType (types[i]) ? ctx.Adapter.GetDisplayTypeName (ctx, types[i]) : types[i].FullName;
+				string toType = ctx.Adapter.GetDisplayTypeName (ctx, param_type);
+
+				error = String.Format ("Argument {0}: Cannot implicitly convert `{1}' to `{2}'", i, fromType, toType);
+				return false;
+			}
+
+			error = null;
+			return true;
+		}
+
+		static MethodMirror OverloadResolve (SoftEvaluationContext ctx, TypeMirror type, string methodName, TypeMirror[] genericTypeArgs, TypeMirror[] argTypes, List<MethodMirror> candidates, bool throwIfNotFound)
+		{
+			if (candidates.Count == 0) {
+				if (throwIfNotFound) {
+					string typeName = ctx.Adapter.GetDisplayTypeName (ctx, type);
+
+					if (methodName == null)
+						throw new EvaluatorException ("Indexer not found in type `{0}'.", typeName);
+
+					if (genericTypeArgs != null && genericTypeArgs.Length > 0) {
+						var types = string.Join (", ", genericTypeArgs.Select (t => ctx.Adapter.GetDisplayTypeName (ctx, t)));
+
+						throw new EvaluatorException ("Method `{0}<{1}>' not found in type `{2}'.", methodName, types, typeName);
+					}
+
+					throw new EvaluatorException ("Method `{0}' not found in type `{1}'.", methodName, typeName);
+				}
+
+				return null;
+			}
+
+			if (argTypes == null) {
+				// This is just a probe to see if the type contains *any* methods of the given name
+				return candidates[0];
+			}
+
+			if (candidates.Count == 1) {
+				string error;
+				int matchCount;
+
+				if (IsApplicable (ctx, candidates[0], genericTypeArgs, argTypes, out error, out matchCount))
+					return candidates[0];
+
+				if (throwIfNotFound)
+					throw new EvaluatorException ("Invalid arguments for method `{0}': {1}", methodName, error);
+
+				return null;
+			}
+			
+			// Ok, now we need to find an exact match.
+			MethodMirror match = null;
+			int bestCount = -1;
+			bool repeatedBestCount = false;
+			
+			foreach (MethodMirror method in candidates) {
+				string error;
+				int matchCount;
+				
+				if (!IsApplicable (ctx, method, genericTypeArgs, argTypes, out error, out matchCount))
+					continue;
+
+				if (matchCount == bestCount) {
+					repeatedBestCount = true;
+				} else if (matchCount > bestCount) {
+					match = method;
+					bestCount = matchCount;
+					repeatedBestCount = false;
+				}
+			}
+			
+			if (match == null) {
+				if (!throwIfNotFound)
+					return null;
+
+				if (methodName != null)
+					throw new EvaluatorException ("Invalid arguments for method `{0}'.", methodName);
+
+				throw new EvaluatorException ("Invalid arguments for indexer.");
+			}
+			
+			if (repeatedBestCount) {
+				// If there is an ambiguous match, just pick the first match. If the user was expecting
+				// something else, he can provide more specific arguments
+				
+/*				if (!throwIfNotFound)
+					return null;
+				if (methodName != null)
+					throw new EvaluatorException ("Ambiguous method `{0}'; need to use full name", methodName);
+				else
+					throw new EvaluatorException ("Ambiguous arguments for indexer.", methodName);
+*/			}
+			 
+			return match;
+		}		
+
+		public override object TargetObjectToObject (EvaluationContext ctx, object obj)
+		{
+			if (obj is StringMirror) {
+				StringMirror mirror = (StringMirror) obj;
+				string str;
+				
+				if (ctx.Options.EllipsizeStrings) {
+					if (mirror.VirtualMachine.Version.AtLeast (2, 10)) {
+						int length = mirror.Length;
+						
+						if (length > ctx.Options.EllipsizedLength)
+							str = new string (mirror.GetChars (0, ctx.Options.EllipsizedLength)) + EvaluationOptions.Ellipsis;
+						else
+							str = mirror.Value;
+					} else {
+						str = mirror.Value;
+						if (str.Length > ctx.Options.EllipsizedLength)
+							str = str.Substring (0, ctx.Options.EllipsizedLength) + EvaluationOptions.Ellipsis;
+					}
+				} else {
+					str = mirror.Value;
+				}
+				
+				return str;
+			} else if (obj is PrimitiveValue) {
+				return ((PrimitiveValue)obj).Value;
+			} else if (obj is PointerValue) {
+				return new IntPtr (((PointerValue)obj).Address);
+			} else if (obj is StructMirror) {
+				StructMirror sm = (StructMirror) obj;
+
+				if (sm.Type.IsPrimitive) {
+					// Boxed primitive
+					if (sm.Type.FullName == "System.IntPtr")
+						return new IntPtr ((long)((PrimitiveValue)sm.Fields[0]).Value);
+					if (sm.Fields.Length > 0 && (sm.Fields[0] is PrimitiveValue))
+						return ((PrimitiveValue)sm.Fields[0]).Value;
+				} else if (sm.Type.FullName == "System.Decimal") {
+					SoftEvaluationContext soft = (SoftEvaluationContext) ctx;
+					MethodMirror method = OverloadResolve (soft, sm.Type, "GetBits", null, new TypeMirror[1] { sm.Type }, false, true, false);
+					if (method != null) {
+						ArrayMirror array;
+						
+						try {
+							array = sm.Type.InvokeMethod (soft.Thread, method, new Value[1] { sm }, InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded) as ArrayMirror;
+						} catch {
+							array = null;
+						} finally {
+							soft.Session.StackVersion++;
+						}
+						
+						if (array != null) {
+							int[] bits = new int [4];
+							for (int i = 0; i < 4; i++)
+								bits[i] = (int) TargetObjectToObject (ctx, array[i]);
+							
+							return new decimal (bits);
+						}
+					}
+				}
+			}
+			return base.TargetObjectToObject (ctx, obj);
+		}
+	}
+
+	class MethodCall: AsyncOperation
+	{
+		const InvokeOptions options = InvokeOptions.DisableBreakpoints | InvokeOptions.SingleThreaded;
+
+		readonly ST.ManualResetEvent shutdownEvent = new ST.ManualResetEvent (false);
+		readonly SoftEvaluationContext ctx;
+		readonly MethodMirror function;
+		readonly Value[] args;
+		readonly object obj;
+		IAsyncResult handle;
+		Exception exception;
+		Value result;
+		
+		public MethodCall (SoftEvaluationContext ctx, MethodMirror function, object obj, Value[] args)
+		{
+			this.ctx = ctx;
+			this.function = function;
+			this.obj = obj;
+			this.args = args;
+		}
+		
+		public override string Description {
+			get {
+				return function.DeclaringType.FullName + "." + function.Name;
+			}
+		}
+
+		public override void Invoke ()
+		{
+			try {
+				if (obj is ObjectMirror)
+					handle = ((ObjectMirror)obj).BeginInvokeMethod (ctx.Thread, function, args, options, null, null);
+				else if (obj is TypeMirror)
+					handle = ((TypeMirror)obj).BeginInvokeMethod (ctx.Thread, function, args, options, null, null);
+				else if (obj is StructMirror)
+					handle = ((StructMirror)obj).BeginInvokeMethod (ctx.Thread, function, args, options, null, null);
+				else if (obj is PrimitiveValue)
+					handle = ((PrimitiveValue)obj).BeginInvokeMethod (ctx.Thread, function, args, options, null, null);
+				else
+					throw new ArgumentException ("Soft debugger method calls cannot be invoked on objects of type " + obj.GetType ().Name);
+			} catch (InvocationException ex) {
+				ctx.Session.StackVersion++;
+				exception = ex;
+			} catch (Exception ex) {
+				ctx.Session.StackVersion++;
+				DebuggerLoggingService.LogError ("Error in soft debugger method call thread on " + GetInfo (), ex);
+				exception = ex;
+			}
+		}
+
+		public override void Abort ()
+		{
+			if (handle is IInvokeAsyncResult) {
+				var info = GetInfo ();
+				DebuggerLoggingService.LogMessage ("Aborting invocation of " + info);
+				((IInvokeAsyncResult) handle).Abort ();
+				// Don't wait for the abort to finish. The engine will do it.
+			} else {
+				throw new NotSupportedException ();
+			}
+		}
+		
+		public override void Shutdown ()
+		{
+			shutdownEvent.Set ();
+		}
+		
+		void EndInvoke ()
+		{
+			try {
+				if (obj is ObjectMirror)
+					result = ((ObjectMirror)obj).EndInvokeMethod (handle);
+				else if (obj is TypeMirror)
+					result = ((TypeMirror)obj).EndInvokeMethod (handle);
+				else if (obj is StructMirror)
+					result = ((StructMirror)obj).EndInvokeMethod (handle);
+				else
+					result = ((PrimitiveValue)obj).EndInvokeMethod (handle);
+			} catch (InvocationException ex) {
+				if (!Aborting && ex.Exception != null) {
+					string ename = ctx.Adapter.GetValueTypeName (ctx, ex.Exception);
+					ValueReference vref = ctx.Adapter.GetMember (ctx, null, ex.Exception, "Message");
+					if (vref != null) {
+						exception = new Exception (ename + ": " + (string)vref.ObjectValue);
+						return;
+					} else {
+						exception = new Exception (ename);
+						return;
+					}
+				}
+				exception = ex;
+			} catch (Exception ex) {
+				DebuggerLoggingService.LogError ("Error in soft debugger method call thread on " + GetInfo (), ex);
+				exception = ex;
+			} finally {
+				ctx.Session.StackVersion++;
+			}
+		}
+		
+		string GetInfo ()
+		{
+			try {
+				TypeMirror type = null;
+				if (obj is ObjectMirror)
+					type = ((ObjectMirror)obj).Type;
+				else if (obj is TypeMirror)
+					type = (TypeMirror)obj;
+				else if (obj is StructMirror)
+					type = ((StructMirror)obj).Type;
+				return string.Format ("method {0} on object {1}",
+				                      function == null? "[null]" : function.FullName,
+				                      type == null? "[null]" : type.FullName);
+			} catch (Exception ex) {
+				DebuggerLoggingService.LogError ("Error getting info for SDB MethodCall", ex);
+				return "";
+			}
+		}
+
+		public override bool WaitForCompleted (int timeout)
+		{
+			if (handle == null)
+				return true;
+			int res = ST.WaitHandle.WaitAny (new ST.WaitHandle[] { handle.AsyncWaitHandle, shutdownEvent }, timeout); 
+			if (res == 0) {
+				EndInvoke ();
+				return true;
+			}
+			// Return true if shut down.
+			return res == 1;
+		}
+
+		public Value ReturnValue {
+			get {
+				if (exception != null)
+					throw new EvaluatorException (exception.Message);
+				return result;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/SoftDebuggerBacktrace.cs b/Mono.Debugging.Soft/SoftDebuggerBacktrace.cs
new file mode 100644
index 0000000..caf7546
--- /dev/null
+++ b/Mono.Debugging.Soft/SoftDebuggerBacktrace.cs
@@ -0,0 +1,215 @@
+// 
+// SoftDebuggerBacktrace.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 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.Linq;
+using System.Text;
+using System.Collections.Generic;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+using MDB = Mono.Debugger.Soft;
+using DC = Mono.Debugging.Client;
+using Mono.Debugging.Evaluation;
+
+namespace Mono.Debugging.Soft
+{
+	internal class SoftDebuggerStackFrame : Mono.Debugging.Client.StackFrame {
+		public Mono.Debugger.Soft.StackFrame StackFrame {
+			get; private set;
+		}
+		
+		public SoftDebuggerStackFrame (Mono.Debugger.Soft.StackFrame frame, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, bool isDebuggerHidden, string fullModuleName, string fullTypeName)
+			: base (frame.ILOffset, addressSpace, location, language, isExternalCode, hasDebugInfo, isDebuggerHidden, fullModuleName, fullTypeName)
+		{
+			StackFrame = frame;
+		}
+	}
+	
+	public class SoftDebuggerBacktrace: BaseBacktrace
+	{
+		MDB.StackFrame[] frames;
+		SoftDebuggerSession session;
+		MDB.ThreadMirror thread;
+		int stackVersion;
+		
+		public SoftDebuggerBacktrace (SoftDebuggerSession session, MDB.ThreadMirror thread): base (session.Adaptor)
+		{
+			this.session = session;
+			this.thread = thread;
+			stackVersion = session.StackVersion;
+			if (thread != null)
+				this.frames = thread.GetFrames ();
+			else
+				this.frames = new MDB.StackFrame[0];
+		}
+		
+		void ValidateStack ()
+		{
+			if (stackVersion != session.StackVersion && thread != null)
+				frames = thread.GetFrames ();
+		}
+
+		public override DC.StackFrame[] GetStackFrames (int firstIndex, int lastIndex)
+		{
+			ValidateStack ();
+
+			if (lastIndex < 0)
+				lastIndex = frames.Length - 1;
+
+			List<DC.StackFrame> list = new List<DC.StackFrame> ();
+			for (int n = firstIndex; n <= lastIndex && n < frames.Length; n++)
+				list.Add (CreateStackFrame (frames[n], n));
+
+			return list.ToArray ();
+		}
+		
+		public override int FrameCount {
+			get {
+				ValidateStack ();
+				return frames.Length;
+			}
+		}
+		
+		DC.StackFrame CreateStackFrame (MDB.StackFrame frame, int frameIndex)
+		{
+			MDB.MethodMirror method = frame.Method;
+			MDB.TypeMirror type = method.DeclaringType;
+			string fileName = frame.FileName;
+			string typeFullName = null;
+			string typeFQN = null;
+			string methodName;
+			
+			if (fileName != null)
+				fileName = SoftDebuggerSession.NormalizePath (fileName);
+			
+			if (method.VirtualMachine.Version.AtLeast (2, 12) && method.IsGenericMethod) {
+				StringBuilder name = new StringBuilder (method.Name);
+				
+				name.Append ('<');
+				
+				if (method.VirtualMachine.Version.AtLeast (2, 15)) {
+					bool first = true;
+					
+					foreach (var argumentType in method.GetGenericArguments ()) {
+						if (!first)
+							name.Append (", ");
+						
+						name.Append (session.Adaptor.GetDisplayTypeName (argumentType.FullName));
+						first = false;
+					}
+				}
+				
+				name.Append ('>');
+				
+				methodName = name.ToString ();
+			} else {
+				methodName = method.Name;
+			}
+			
+			// Compiler generated anonymous/lambda methods
+			bool special_method = false;
+			if (methodName [0] == '<' && methodName.Contains (">m__")) {
+				int nidx = methodName.IndexOf (">m__", StringComparison.Ordinal) + 2;
+				methodName = "AnonymousMethod" + methodName.Substring (nidx, method.Name.Length - nidx);
+				special_method = true;
+			}
+			
+			if (type != null) {
+				string typeDisplayName = session.Adaptor.GetDisplayTypeName (type.FullName);
+				
+				if (SoftDebuggerAdaptor.IsGeneratedType (type)) {
+					// The user-friendly method name is embedded in the generated type name
+					var mn = SoftDebuggerAdaptor.GetNameFromGeneratedType (type);
+					
+					// Strip off the generated type name
+					int dot = typeDisplayName.LastIndexOf ('.');
+					var tname = typeDisplayName.Substring (0, dot);
+
+					// Keep any type arguments
+					int targs = typeDisplayName.LastIndexOf ('<');
+					if (targs > dot + 1)
+						mn += typeDisplayName.Substring (targs, typeDisplayName.Length - targs);
+
+					typeDisplayName = tname;
+					
+					if (special_method)
+						typeDisplayName += "." + mn;
+					else
+						methodName = mn;
+				}
+				
+				methodName = typeDisplayName + "." + methodName;
+				
+				typeFQN = type.Module.FullyQualifiedName;
+				typeFullName = type.FullName;
+			}
+
+			bool hidden = false;
+			if (session.VirtualMachine.Version.AtLeast (2, 21)) {
+				var ctx = GetEvaluationContext (frameIndex, session.EvaluationOptions);
+				var hiddenAttr = session.Adaptor.GetType (ctx, "System.Diagnostics.DebuggerHiddenAttribute") as MDB.TypeMirror;
+			
+				hidden = method.GetCustomAttributes (hiddenAttr, true).Any ();
+			}
+
+			var location = new DC.SourceLocation (methodName, fileName, frame.LineNumber, frame.ColumnNumber);
+			var external = session.IsExternalCode (frame);
+			string addressSpace = string.Empty;
+			bool hasDebugInfo = false;
+			string language;
+
+			if (frame.Method != null) {
+				if (frame.IsNativeTransition) {
+					language = "Transition";
+				} else {
+					addressSpace = method.FullName;
+					language = "Managed";
+					hasDebugInfo = true;
+				}
+			} else {
+				language = "Native";
+			}
+
+			return new SoftDebuggerStackFrame (frame, addressSpace, location, language, external, hasDebugInfo, hidden, typeFQN, typeFullName);
+		}
+		
+		protected override EvaluationContext GetEvaluationContext (int frameIndex, EvaluationOptions options)
+		{
+			ValidateStack ();
+			if (frameIndex >= frames.Length)
+				return null;
+			
+			MDB.StackFrame frame = frames [frameIndex];
+			return new SoftEvaluationContext (session, frame, options);
+		}
+		
+		public override AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count)
+		{
+			return session.Disassemble (frames [frameIndex], firstLine, count);
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/SoftDebuggerSession.cs b/Mono.Debugging.Soft/SoftDebuggerSession.cs
new file mode 100644
index 0000000..f718e0e
--- /dev/null
+++ b/Mono.Debugging.Soft/SoftDebuggerSession.cs
@@ -0,0 +1,2638 @@
+// 
+// SoftDebuggerSession.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 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.
+
+//#define DEBUG_EVENT_QUEUEING
+
+using System;
+using System.IO;
+using System.Net;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Reflection;
+using System.Net.Sockets;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using Mono.Cecil.Mdb;
+using Mono.CompilerServices.SymbolWriter;
+using Mono.Debugging.Client;
+using Mono.Debugger.Soft;
+using Mono.Debugging.Evaluation;
+using MDB = Mono.Debugger.Soft;
+
+namespace Mono.Debugging.Soft
+{
+	public class SoftDebuggerSession : DebuggerSession
+	{
+		VirtualMachine vm;
+		Thread eventHandler;
+		Dictionary<string, List<TypeMirror>> source_to_type = new Dictionary<string, List<TypeMirror>> (PathComparer);
+		Dictionary<TypeMirror, string[]> type_to_source = new Dictionary<TypeMirror, string[]> ();
+		bool useFullPaths = true;
+		Dictionary<string,TypeMirror> types = new Dictionary<string, TypeMirror> ();
+		Dictionary<string, MonoSymbolFile> symbolFiles = new Dictionary<string, MonoSymbolFile> ();
+		Dictionary<EventRequest,BreakInfo> breakpoints = new Dictionary<EventRequest,BreakInfo> ();
+		List<BreakInfo> pending_bes = new List<BreakInfo> ();
+		ThreadMirror current_thread, recent_thread;
+		ProcessInfo[] procs;
+		ThreadInfo[] current_threads;
+		bool started;
+		bool autoStepInto;
+		internal int StackVersion;
+		StepEventRequest currentStepRequest;
+		long currentAddress = -1;
+		ExceptionEventRequest unhandledExceptionRequest;
+		string remoteProcessName;
+		Dictionary<long,long> localThreadIds = new Dictionary<long, long> ();
+		IConnectionDialog connectionDialog;
+		TypeLoadEventRequest typeLoadReq, typeLoadTypeNameReq;
+		
+		Dictionary<long,ObjectMirror> activeExceptionsByThread = new Dictionary<long, ObjectMirror> ();
+		
+		Thread outputReader;
+		Thread errorReader;
+		
+		IAsyncResult connectionHandle;
+		SoftDebuggerStartArgs startArgs;
+		
+		LinkedList<List<Event>> queuedEventSets = new LinkedList<List<Event>> ();
+		
+		List<string> userAssemblyNames;
+		List<AssemblyMirror> assemblyFilters;
+		Dictionary<string, string> assemblyPathMap;
+		
+		bool loggedSymlinkedRuntimesBug = false;
+
+		Dictionary<Tuple<TypeMirror,string>, MethodMirror[]> overloadResolveCache;
+		
+		public SoftDebuggerAdaptor Adaptor {
+			get { return adaptor; }
+		}
+		
+		readonly SoftDebuggerAdaptor adaptor = new SoftDebuggerAdaptor ();
+		
+		public SoftDebuggerSession ()
+		{
+			Adaptor.BusyStateChanged += delegate(object sender, BusyStateEventArgs e) {
+				SetBusyState (e);
+			};
+			overloadResolveCache = new Dictionary<Tuple<TypeMirror,string>, MethodMirror[]> ();
+		}
+		
+		protected override void OnRun (DebuggerStartInfo startInfo)
+		{
+			if (HasExited)
+				throw new InvalidOperationException ("Already exited");
+			
+			var dsi = (SoftDebuggerStartInfo) startInfo;
+			if (dsi.StartArgs is SoftDebuggerLaunchArgs) {
+				StartLaunching (dsi);
+			} else if (dsi.StartArgs is SoftDebuggerConnectArgs) {
+				StartConnecting (dsi);
+			} else if (dsi.StartArgs is SoftDebuggerListenArgs) {
+				StartListening (dsi);
+			} else if (dsi.StartArgs.ConnectionProvider != null) {
+				StartConnection (dsi);
+			} else {
+				throw new ArgumentException ("StartArgs has no ConnectionProvider");
+			}
+		}
+		
+		void StartConnection (SoftDebuggerStartInfo dsi)
+		{
+			startArgs = dsi.StartArgs;
+			
+			RegisterUserAssemblies (dsi);
+			
+			if (!String.IsNullOrEmpty (dsi.LogMessage))
+				LogWriter (false, dsi.LogMessage + "\n");
+			
+			AsyncCallback callback = null;
+			int attemptNumber = 0;
+			int maxAttempts = startArgs.MaxConnectionAttempts;
+			int timeBetweenAttempts = startArgs.TimeBetweenConnectionAttempts;
+			callback = delegate (IAsyncResult ar) {
+				try {
+					string appName;
+					VirtualMachine vm;
+					startArgs.ConnectionProvider.EndConnect (ar, out vm, out appName);
+					remoteProcessName = appName;
+					ConnectionStarted (vm);
+					return;
+				} catch (Exception ex) {
+					attemptNumber++;
+					if (!ShouldRetryConnection (ex, attemptNumber)
+						|| !startArgs.ConnectionProvider.ShouldRetryConnection (ex)
+						|| attemptNumber == maxAttempts
+						|| HasExited)
+					{
+						OnConnectionError (ex);
+						return;
+					}
+				}
+				try {
+					if (timeBetweenAttempts > 0)
+						Thread.Sleep (timeBetweenAttempts);
+					ConnectionStarting (startArgs.ConnectionProvider.BeginConnect (dsi, callback), dsi, false, 0);
+				} catch (Exception ex2) {
+					OnConnectionError (ex2);
+				}
+			};
+			//the "listening" value is never used, pass a dummy value
+			ConnectionStarting (startArgs.ConnectionProvider.BeginConnect (dsi, callback), dsi, false, 0);
+		}
+		
+		void StartLaunching (SoftDebuggerStartInfo dsi)
+		{
+			var args = (SoftDebuggerLaunchArgs) dsi.StartArgs;
+			var runtime = string.IsNullOrEmpty (args.MonoRuntimePrefix) ? "mono" : Path.Combine (Path.Combine (args.MonoRuntimePrefix, "bin"), "mono");
+			RegisterUserAssemblies (dsi);
+			
+			var psi = new System.Diagnostics.ProcessStartInfo (runtime) {
+				Arguments = string.Format ("\"{0}\" {1}", dsi.Command, dsi.Arguments),
+				WorkingDirectory = dsi.WorkingDirectory,
+				RedirectStandardOutput = true,
+				RedirectStandardError = true,
+				UseShellExecute = false,
+				CreateNoWindow = true,
+			};
+			
+			LaunchOptions options = null;
+			
+			if (dsi.UseExternalConsole && args.ExternalConsoleLauncher != null) {
+				options = new LaunchOptions ();
+				options.CustomTargetProcessLauncher = args.ExternalConsoleLauncher;
+				psi.RedirectStandardOutput = false;
+				psi.RedirectStandardError = false;
+			}
+
+			var sdbLog = Environment.GetEnvironmentVariable ("MONODEVELOP_SDB_LOG");
+			if (!string.IsNullOrEmpty (sdbLog)) {
+				options = options ?? new LaunchOptions ();
+				options.AgentArgs = string.Format ("loglevel=1,logfile='{0}'", sdbLog);
+			}
+			
+			foreach (var env in args.MonoRuntimeEnvironmentVariables)
+				psi.EnvironmentVariables[env.Key] = env.Value;
+			
+			foreach (var env in dsi.EnvironmentVariables)
+				psi.EnvironmentVariables[env.Key] = env.Value;
+			
+			if (!String.IsNullOrEmpty (dsi.LogMessage))
+				OnDebuggerOutput (false, dsi.LogMessage + "\n");
+			
+			var callback = HandleConnectionCallbackErrors ((IAsyncResult ar) => {
+				ConnectionStarted (VirtualMachineManager.EndLaunch (ar));
+			});
+			ConnectionStarting (VirtualMachineManager.BeginLaunch (psi, callback, options), dsi, true, 0);
+		}
+		
+		/// <summary>Starts the debugger listening for a connection over TCP/IP</summary>
+		protected void StartListening (SoftDebuggerStartInfo dsi)
+		{
+			int dp, cp;
+			StartListening (dsi, out dp, out cp);
+		}
+		
+		/// <summary>Starts the debugger listening for a connection over TCP/IP</summary>
+		protected void StartListening (SoftDebuggerStartInfo dsi, out int assignedDebugPort)
+		{
+			int cp;
+			StartListening (dsi, out assignedDebugPort, out cp);
+		}
+		
+		/// <summary>Starts the debugger listening for a connection over TCP/IP</summary>
+		protected void StartListening (SoftDebuggerStartInfo dsi, out int assignedDebugPort, out int assignedConsolePort)
+		{
+		
+			IPEndPoint dbgEP, conEP;
+			InitForRemoteSession (dsi, out dbgEP, out conEP);
+			
+			var callback = HandleConnectionCallbackErrors (delegate (IAsyncResult ar) {
+				ConnectionStarted (VirtualMachineManager.EndListen (ar));
+			});
+			var a = VirtualMachineManager.BeginListen (dbgEP, conEP, callback, out assignedDebugPort, out assignedConsolePort);
+			ConnectionStarting (a, dsi, true, 0);
+		}
+
+		protected virtual bool ShouldRetryConnection (Exception ex, int attemptNumber)
+		{
+			var sx = ex as SocketException;
+			if (sx != null) {
+				if (sx.ErrorCode == 10061) //connection refused
+					return true;
+			}
+			return false;
+		}
+		
+		protected void StartConnecting (SoftDebuggerStartInfo dsi)
+		{
+			StartConnecting (dsi, dsi.StartArgs.MaxConnectionAttempts, dsi.StartArgs.TimeBetweenConnectionAttempts);
+		}
+		
+		/// <summary>Starts the debugger connecting to a remote IP</summary>
+		protected void StartConnecting (SoftDebuggerStartInfo dsi, int maxAttempts, int timeBetweenAttempts)
+		{	
+			if (timeBetweenAttempts < 0 || timeBetweenAttempts > 10000)
+				throw new ArgumentException ("timeBetweenAttempts");
+			
+			IPEndPoint dbgEP, conEP;
+			InitForRemoteSession (dsi, out dbgEP, out conEP);
+			
+			AsyncCallback callback = null;
+			int attemptNumber = 0;
+			callback = delegate (IAsyncResult ar) {
+				try {
+					ConnectionStarted (VirtualMachineManager.EndConnect (ar));
+					return;
+				} catch (Exception ex) {
+					attemptNumber++;
+					if (!ShouldRetryConnection (ex, attemptNumber) || attemptNumber == maxAttempts || HasExited) {
+						OnConnectionError (ex);
+						return;
+					}
+				}
+				try {
+					if (timeBetweenAttempts > 0)
+						System.Threading.Thread.Sleep (timeBetweenAttempts);
+					
+					ConnectionStarting (VirtualMachineManager.BeginConnect (dbgEP, conEP, callback), dsi, false, attemptNumber);
+					
+				} catch (Exception ex2) {
+					OnConnectionError (ex2);
+				}
+			};
+			
+			ConnectionStarting (VirtualMachineManager.BeginConnect (dbgEP, conEP, callback), dsi, false, 0);
+		}
+		
+		void InitForRemoteSession (SoftDebuggerStartInfo dsi, out IPEndPoint dbgEP, out IPEndPoint conEP)
+		{
+			if (remoteProcessName != null)
+				throw new InvalidOperationException ("Cannot initialize connection more than once");
+			
+			var args = (SoftDebuggerRemoteArgs) dsi.StartArgs;
+			
+			remoteProcessName = args.AppName;
+			
+			RegisterUserAssemblies (dsi);
+			
+			dbgEP = new IPEndPoint (args.Address, args.DebugPort);
+			conEP = args.RedirectOutput? new IPEndPoint (args.Address, args.OutputPort) : null;
+			
+			if (!String.IsNullOrEmpty (dsi.LogMessage))
+				LogWriter (false, dsi.LogMessage + "\n");
+		}
+		
+		///<summary>Catches errors in async callbacks and hands off to OnConnectionError</summary>
+		AsyncCallback HandleConnectionCallbackErrors (AsyncCallback callback)
+		{
+			return delegate (IAsyncResult ar) {
+				connectionHandle = null;
+				try {
+					callback (ar);
+				} catch (Exception ex) {
+					OnConnectionError (ex);
+				}
+			};
+		}
+		
+		/// <summary>
+		/// Called if an error happens while making the connection. Default terminates the session.
+		/// </summary>
+		protected virtual void OnConnectionError (Exception ex)
+		{
+			//if the exception was caused by cancelling the session
+			if (HasExited)
+				return;
+			
+			if (!HandleException (new ConnectionException (ex))) {
+				DebuggerLoggingService.LogAndShowException ("Unhandled error launching soft debugger", ex);
+			}
+			
+			// The session is dead
+			// HandleException doesn't actually handle exceptions, it just displays them.
+			EndSession ();
+		}
+		
+		void ConnectionStarting (IAsyncResult connectionHandle, DebuggerStartInfo dsi, bool listening, int attemptNumber) 
+		{
+			if (this.connectionHandle != null && (attemptNumber == 0 || !this.connectionHandle.IsCompleted))
+				throw new InvalidOperationException ("Already connecting");
+			
+			this.connectionHandle = connectionHandle;
+			
+			if (ConnectionDialogCreator != null && attemptNumber == 0) {
+				connectionDialog = ConnectionDialogCreator ();
+				connectionDialog.UserCancelled += delegate {
+					EndSession ();
+				};
+			}
+			if (connectionDialog != null)
+				connectionDialog.SetMessage (dsi, GetConnectingMessage (dsi), listening, attemptNumber);
+		}
+		
+		protected virtual string GetConnectingMessage (DebuggerStartInfo dsi)
+		{
+			return null;
+		}
+		
+		void EndLaunch ()
+		{
+			HideConnectionDialog ();
+			if (connectionHandle != null) {
+				if (startArgs != null && startArgs.ConnectionProvider != null) {
+					startArgs.ConnectionProvider.CancelConnect (connectionHandle);
+					startArgs = null;
+				} else {
+					VirtualMachineManager.CancelConnection (connectionHandle);
+				}
+				connectionHandle = null;
+			}
+		}
+		
+		protected virtual void EndSession ()
+		{
+			if (!HasExited) {
+				EndLaunch ();
+				OnTargetEvent (new TargetEventArgs (TargetEventType.TargetExited));
+			}
+		}
+
+		public Dictionary<Tuple<TypeMirror, string>, MethodMirror[]> OverloadResolveCache {
+			get {
+				return overloadResolveCache;
+			}
+		}
+		
+		void HideConnectionDialog ()
+		{
+			if (connectionDialog != null) {
+				connectionDialog.Dispose ();
+				connectionDialog = null;
+			}
+		}
+		
+		/// <summary>
+		/// If subclasses do an async connect in OnRun, they should pass the resulting VM to this method.
+		/// If the vm is null, the session will be closed.
+		/// </summary>
+		void ConnectionStarted (VirtualMachine vm)
+		{
+			if (this.vm != null)
+				throw new InvalidOperationException ("The VM has already connected");
+			
+			if (vm == null) {
+				EndSession ();
+				return;
+			}
+			
+			connectionHandle = null;
+			
+			this.vm = vm;
+			
+			//full paths, from GetSourceFiles (true), are only supported by sdb protocol 2.2 and later
+			useFullPaths = vm.Version.AtLeast (2, 2);
+			
+			ConnectOutput (vm.StandardOutput, false);
+			ConnectOutput (vm.StandardError, true);
+			
+			HideConnectionDialog ();
+			
+			vm.EnableEvents (EventType.AssemblyLoad, EventType.ThreadStart, EventType.ThreadDeath,
+				EventType.AssemblyUnload, EventType.UserBreak, EventType.UserLog);
+			try {
+				unhandledExceptionRequest = vm.CreateExceptionRequest (null, false, true);
+				unhandledExceptionRequest.Enable ();
+			} catch (NotSupportedException) {
+				//Mono < 2.6.3 doesn't support catching unhandled exceptions
+			}
+
+			if (vm.Version.AtLeast (2, 9)) {
+				/* Created later */
+			} else {
+				vm.EnableEvents (EventType.TypeLoad);
+			}
+			
+			started = true;
+			
+			/* Wait for the VMStart event */
+			HandleEventSet (vm.GetNextEventSet ());
+			
+			eventHandler = new Thread (EventHandler);
+			eventHandler.Name = "SDB Event Handler";
+			eventHandler.IsBackground = true;
+			eventHandler.Start ();
+		}
+		
+		void RegisterUserAssemblies (SoftDebuggerStartInfo dsi)
+		{
+			if (Options.ProjectAssembliesOnly && dsi.UserAssemblyNames != null) {
+				assemblyFilters = new List<AssemblyMirror> ();
+				userAssemblyNames = dsi.UserAssemblyNames.Select (x => x.ToString ()).ToList ();
+			}
+			
+			assemblyPathMap = dsi.AssemblyPathMap;
+			if (assemblyPathMap == null)
+				assemblyPathMap = new Dictionary<string, string> ();
+		}
+		
+		protected bool SetSocketTimeouts (int sendTimeout, int receiveTimeout, int keepaliveInterval)
+		{
+			try {
+				if (vm.Version.AtLeast (2, 4)) {
+					vm.EnableEvents (EventType.KeepAlive);
+					vm.SetSocketTimeouts (sendTimeout, receiveTimeout, keepaliveInterval);
+					return true;
+				}
+
+				return false;
+			} catch {
+				return false;
+			}
+		}
+
+		protected void ConnectOutput (StreamReader reader, bool error)
+		{
+			Thread t = (error ? errorReader : outputReader);
+			if (t != null || reader == null)
+				return;
+			t = new Thread (delegate () {
+				ReadOutput (reader, error);
+			});
+			t.Name = error? "SDB error reader" : "SDB output reader";
+			t.IsBackground = true;
+			t.Start ();
+
+			if (error)
+				errorReader = t;	
+			else
+				outputReader = t;
+		}
+
+		void ReadOutput (StreamReader reader, bool isError)
+		{
+			try {
+				var buffer = new char [1024];
+				while (!HasExited) {
+					int c = reader.Read (buffer, 0, buffer.Length);
+					if (c > 0) {
+						OnTargetOutput (isError, new string (buffer, 0, c));
+					} else {
+						//FIXME: workaround for buggy console stream that never blocks
+						Thread.Sleep (250);
+					}
+				}
+			} catch {
+				// Ignore
+			}
+		}
+
+		protected virtual void OnResumed ()
+		{
+			current_threads = null;
+			current_thread = null;
+			procs = null;
+			activeExceptionsByThread.Clear ();
+		}
+		
+		public VirtualMachine VirtualMachine {
+			get { return vm; }
+		}
+		
+		public TypeMirror GetType (string fullName)
+		{
+			TypeMirror tm;
+			types.TryGetValue (fullName, out tm);
+			return tm;
+		}
+		
+		public IEnumerable<TypeMirror> GetAllTypes ()
+		{
+			return types.Values;
+		}
+
+		protected override bool AllowBreakEventChanges {
+			get { return true; }
+		}
+
+		public override void Dispose ()
+		{
+			base.Dispose ();
+
+			if (symbolFiles == null)
+				return;
+
+			if (!HasExited)
+				EndLaunch ();
+
+			foreach (var symfile in symbolFiles)
+				symfile.Value.Dispose ();
+
+			symbolFiles.Clear ();
+			symbolFiles = null;
+
+			if (!HasExited) {
+				if (vm != null) {
+					ThreadPool.QueueUserWorkItem (delegate {
+						try {
+							vm.Exit (0);
+						} catch (VMDisconnectedException) {
+						} catch (Exception ex) {
+							DebuggerLoggingService.LogError ("Error exiting SDB VM:", ex);
+						}
+					});
+				}
+			}
+			
+			Adaptor.Dispose ();
+		}
+
+		protected override void OnAttachToProcess (long processId)
+		{
+			throw new NotSupportedException ();
+		}
+
+		protected override void OnContinue ()
+		{
+			ThreadPool.QueueUserWorkItem (delegate {
+				try {
+					Adaptor.CancelAsyncOperations (); // This call can block, so it has to run in background thread to avoid keeping the main session lock
+					OnResumed ();
+					vm.Resume ();
+					DequeueEventsForFirstThread ();
+				} catch (Exception ex) {
+					if (!HandleException (ex))
+						OnDebuggerOutput (true, ex.ToString ());
+				}
+			});
+		}
+
+		protected override void OnDetach ()
+		{
+			throw new NotSupportedException ();
+		}
+
+		protected override void OnExit ()
+		{
+			HasExited = true;
+			EndLaunch ();
+			if (vm != null) {
+				try {
+					vm.Exit (0);
+				} catch (VMDisconnectedException) {
+					// The VM was already disconnected, ignore.
+				} catch (SocketException se) {
+					// This will often happen during normal operation
+					DebuggerLoggingService.LogError ("Error closing debugger session", se);
+				} catch (IOException ex) {
+					// This will often happen during normal operation
+					DebuggerLoggingService.LogError ("Error closing debugger session", ex);
+				}
+			}
+			QueueEnsureExited ();
+		}
+		
+		void QueueEnsureExited ()
+		{
+			if (vm != null) {
+				//FIXME: this might never get reached if the IDE is Exited first
+				try {
+					if (vm.Process != null) {
+						ThreadPool.QueueUserWorkItem (delegate {
+							// This is a workaround for a mono bug
+							// Without this call, the process may become zombie in mono < 2.10.2
+							vm.Process.WaitForExit ();
+						});
+					}
+				} catch {
+					// Ignore
+				}
+				var t = new System.Timers.Timer ();
+				t.Interval = 3000;
+				t.Elapsed += delegate {
+					try {
+						t.Enabled = false;
+						t.Dispose ();
+						EnsureExited ();
+					} catch (Exception ex) {
+						DebuggerLoggingService.LogError ("Failed to force-terminate process", ex);
+					}
+					try {
+						if (vm != null) {
+							//this is a no-op if it already closed
+							vm.ForceDisconnect ();
+						}
+					} catch (Exception ex) {
+						DebuggerLoggingService.LogError ("Failed to force-close debugger connection", ex);
+					}
+				};
+				t.Enabled = true;
+			}	
+		}
+		
+		/// <summary>This is a fallback in case the debugger agent doesn't respond to an exit call</summary>
+		protected virtual void EnsureExited ()
+		{
+			try {
+				if (vm != null && vm.TargetProcess != null && !vm.TargetProcess.HasExited)
+					vm.TargetProcess.Kill ();
+			} catch (Exception ex) {
+				DebuggerLoggingService.LogError ("Error force-terminating soft debugger process", ex);
+			}
+		}
+
+		protected override void OnFinish ()
+		{
+			Step (StepDepth.Out, StepSize.Line);
+		}
+
+		protected override ProcessInfo[] OnGetProcesses ()
+		{
+			if (procs == null) {
+				if (remoteProcessName != null || vm.TargetProcess == null) {
+					procs = new ProcessInfo[] { new ProcessInfo (0, remoteProcessName ?? "mono") };
+				} else {
+					try {
+						procs = new ProcessInfo[] { new ProcessInfo (vm.TargetProcess.Id, vm.TargetProcess.ProcessName) };
+					} catch (Exception ex) {
+						if (!loggedSymlinkedRuntimesBug) {
+							loggedSymlinkedRuntimesBug = true;
+							DebuggerLoggingService.LogError ("Error getting debugger process info. Known Mono bug with symlinked runtimes.", ex);
+						}
+						procs = new ProcessInfo[] { new ProcessInfo (0, "mono") };
+					}
+				}
+			}
+			return new ProcessInfo[] { new ProcessInfo (procs[0].Id, procs[0].Name) };
+		}
+
+		protected override Backtrace OnGetThreadBacktrace (long processId, long threadId)
+		{
+			return GetThreadBacktrace (GetThread (processId, threadId));
+		}
+		
+		Backtrace GetThreadBacktrace (ThreadMirror thread)
+		{
+			return new Backtrace (new SoftDebuggerBacktrace (this, thread));
+		}
+
+		string GetThreadName (ThreadMirror t)
+		{
+			string name = t.Name;
+			if (string.IsNullOrEmpty (name)) {
+				try {
+					if (t.IsThreadPoolThread)
+						return "<Thread Pool>";
+				} catch (ObjectCollectedException e) {
+					if (vm.Version.AtLeast (2, 2)) {
+						throw;
+					}
+					return "<Thread>";
+				}
+			}
+			return name;
+		}
+
+		protected override ThreadInfo[] OnGetThreads (long processId)
+		{
+			if (current_threads == null) {
+				IList<ThreadMirror> mirrors = vm.GetThreads ();
+				var threads = new ThreadInfo[mirrors.Count];
+				for (int i = 0; i < mirrors.Count; i++) {
+					ThreadMirror t = mirrors [i];
+					threads[i] = new ThreadInfo (processId, GetId (t), GetThreadName (t), null);
+				}
+				current_threads = threads;
+			}
+			return current_threads;
+		}
+		
+		ThreadMirror GetThread (long processId, long threadId)
+		{
+			foreach (ThreadMirror t in vm.GetThreads ())
+				if (GetId (t) == threadId)
+					return t;
+			return null;
+		}
+		
+		ThreadInfo GetThread (ProcessInfo process, ThreadMirror thread)
+		{
+			long tid = GetId (thread);
+			foreach (var t in OnGetThreads (process.Id))
+				if (t.Id == tid)
+					return t;
+			return null;
+		}
+		
+		protected override BreakEventInfo OnInsertBreakEvent (BreakEvent ev)
+		{
+			lock (pending_bes) {
+				var bi = new BreakInfo ();
+
+				if (HasExited) {
+					bi.SetStatus (BreakEventStatus.Disconnected, null);
+					return bi;
+				}
+
+				if (ev is FunctionBreakpoint) {
+					var fb = (FunctionBreakpoint) ev;
+					bool resolved = false;
+
+					foreach (var location in FindFunctionLocations (fb.FunctionName, fb.ParamTypes)) {
+						string paramList = string.Empty;
+
+						if (fb.ParamTypes != null)
+							paramList = "(" + string.Join (", ", fb.ParamTypes) + ")";
+
+						OnDebuggerOutput (false, string.Format ("Resolved pending breakpoint for '{0}{1}' to {2}:{3} [0x{4:x5}].\n",
+						                                        fb.FunctionName, paramList, location.SourceFile, location.LineNumber, location.ILOffset));
+
+						bi.FileName = location.SourceFile;
+						bi.Location = location;
+
+						InsertBreakpoint (fb, bi);
+						bi.SetStatus (BreakEventStatus.Bound, null);
+						resolved = true;
+					}
+
+					if (!resolved) {
+						// FIXME: handle types like GenericType<>, GenericType<SomeOtherType>, and GenericType<...>+NestedGenricType<...>
+						int dot = fb.FunctionName.LastIndexOf ('.');
+						if (dot != -1)
+							bi.TypeName = fb.FunctionName.Substring (0, dot);
+
+						bi.SetStatus (BreakEventStatus.NotBound, null);
+						pending_bes.Add (bi);
+					}
+				} else if (ev is Breakpoint) {
+					var bp = (Breakpoint) ev;
+					bool insideLoadedRange;
+					bool resolved = false;
+					bool generic;
+
+					bi.FileName = bp.FileName;
+
+					foreach (var location in FindLocationsByFile (bp.FileName, bp.Line, bp.Column, out generic, out insideLoadedRange)) {
+						OnDebuggerOutput (false, string.Format ("Resolved pending breakpoint at '{0}:{1},{2}' to {3} [0x{4:x5}].\n",
+						                                        bp.FileName, bp.Line, bp.Column, GetPrettyMethodName (location.Method), location.ILOffset));
+
+						bi.Location = location;
+						InsertBreakpoint (bp, bi);
+						bi.SetStatus (BreakEventStatus.Bound, null);
+						resolved = true;
+					}
+
+					if (resolved) {
+						// Note: if the type or method is generic, there may be more instances so don't assume we are done resolving the breakpoint
+						if (generic)
+							pending_bes.Add (bi);
+					} else {
+						pending_bes.Add (bi);
+						if (insideLoadedRange)
+							bi.SetStatus (BreakEventStatus.Invalid, null);
+						else
+							bi.SetStatus (BreakEventStatus.NotBound, null);
+					}
+				} else if (ev is Catchpoint) {
+					var cp = (Catchpoint) ev;
+					TypeMirror type;
+
+					if (!types.TryGetValue (cp.ExceptionName, out type)) {
+						//
+						// Same as in FindLocationByFile (), fetch types matching the type name
+						if (vm.Version.AtLeast (2, 9)) {
+							foreach (TypeMirror t in vm.GetTypes (cp.ExceptionName, false))
+								ProcessType (t);
+						}
+					}
+
+					if (types.TryGetValue (cp.ExceptionName, out type)) {
+						InsertCatchpoint (cp, bi, type);
+						bi.SetStatus (BreakEventStatus.Bound, null);
+					} else {
+						bi.TypeName = cp.ExceptionName;
+						pending_bes.Add (bi);
+						bi.SetStatus (BreakEventStatus.NotBound, null);
+					}
+				}
+
+				/*
+				 * TypeLoad events lead to too much wire traffic + suspend/resume work, so
+				 * filter them using the file names used by pending breakpoints.
+				 */
+				if (vm.Version.AtLeast (2, 9)) {
+					var sourceFileList = pending_bes.Where (b => b.FileName != null).Select (b => b.FileName).ToArray ();
+					if (sourceFileList.Length > 0) {
+						//HACK: explicitly try lowercased drivename on windows, since csc (when not hosted in VS) lowercases
+						//the drivename in the pdb files that get converted to mdbs as-is
+						//FIXME: we should really do a case-insensitive request on Win/Mac, when sdb supports that
+						if (IsWindows) {
+							int originalCount = sourceFileList.Length;
+							Array.Resize (ref sourceFileList, originalCount * 2);
+							for (int i = 0; i < originalCount; i++) {
+								string n = sourceFileList[i];
+								sourceFileList[originalCount + i] = char.ToLower (n[0]) + n.Substring (1);
+							}
+						}
+
+						if (typeLoadReq == null) {
+							typeLoadReq = vm.CreateTypeLoadRequest ();
+						}
+						typeLoadReq.Enabled = false;
+						typeLoadReq.SourceFileFilter = sourceFileList;
+						typeLoadReq.Enabled = true;
+					}
+
+					var typeNameList = pending_bes.Where (b => b.TypeName != null).Select (b => b.TypeName).ToArray ();
+					if (typeNameList.Length > 0) {
+						// Use a separate request since the filters are ANDed together
+						if (typeLoadTypeNameReq == null) {
+							typeLoadTypeNameReq = vm.CreateTypeLoadRequest ();
+						}
+						typeLoadTypeNameReq.Enabled = false;
+						typeLoadTypeNameReq.TypeNameFilter = typeNameList;
+						typeLoadTypeNameReq.Enabled = true;
+					}
+				}
+
+				return bi;
+			}
+		}
+
+		protected override void OnRemoveBreakEvent (BreakEventInfo binfo)
+		{
+			if (HasExited)
+				return;
+
+			lock (pending_bes) {
+				var bi = (BreakInfo) binfo;
+				if (bi.Requests.Count != 0) {
+					foreach (var request in bi.Requests)
+						request.Enabled = false;
+
+					RemoveQueuedBreakEvents (bi.Requests);
+				}
+
+				pending_bes.Remove (bi);
+			}
+		}
+
+		protected override void OnEnableBreakEvent (BreakEventInfo binfo, bool enable)
+		{
+			if (HasExited)
+				return;
+
+			lock (pending_bes) {
+				var bi = (BreakInfo) binfo;
+				if (bi.Requests.Count != 0) {
+					foreach (var request in bi.Requests)
+						request.Enabled = enable;
+
+					if (!enable)
+						RemoveQueuedBreakEvents (bi.Requests);
+				}
+			}
+		}
+
+		protected override void OnUpdateBreakEvent (BreakEventInfo binfo)
+		{
+		}
+
+		void InsertBreakpoint (Breakpoint bp, BreakInfo bi)
+		{
+			EventRequest request;
+			
+			request = vm.SetBreakpoint (bi.Location.Method, bi.Location.ILOffset);
+			request.Enabled = bp.Enabled;
+			bi.Requests.Add (request);
+			
+			breakpoints[request] = bi;
+			
+			if (bi.Location.LineNumber != bp.Line || bi.Location.ColumnNumber != bp.Column)
+				bi.AdjustBreakpointLocation (bi.Location.LineNumber, bi.Location.ColumnNumber);
+		}
+		
+		void InsertCatchpoint (Catchpoint cp, BreakInfo bi, TypeMirror excType)
+		{
+			ExceptionEventRequest request;
+			
+			request = vm.CreateExceptionRequest (excType, true, true);
+			request.Count = cp.HitCount; // Note: need to set HitCount *before* enabling
+			request.Enabled = cp.Enabled;
+			if (vm.Version.AtLeast (2, 25))
+				request.IncludeSubclasses = cp.IncludeSubclasses;
+			
+			bi.Requests.Add (request);
+		}
+		
+		static bool CheckTypeName (string typeName, string name)
+		{
+			// if the name provided is empty, it matches anything.
+			if (name.Length == 0)
+				return true;
+
+			if (name.StartsWith ("global::", StringComparison.Ordinal)) {
+				if (typeName != name.Substring ("global::".Length))
+					return false;
+			} else if (name.StartsWith ("::", StringComparison.Ordinal)) {
+				if (typeName != name.Substring ("::".Length))
+					return false;
+			} else {
+				// be a little more flexible with what we match... i.e. "Console" should match "System.Console"
+				if (typeName.Length > name.Length) {
+					if (!typeName.EndsWith (name, StringComparison.InvariantCulture))
+						return false;
+
+					char delim = typeName[typeName.Length - name.Length];
+					if (delim != '.' && delim != '+')
+						return false;
+				} else if (typeName != name) {
+					return false;
+				}
+			}
+
+			return true;
+		}
+
+		static bool CheckTypeName (TypeMirror type, string name)
+		{
+			if (name.Length == 0) {
+				// empty name matches anything
+				return true;
+			}
+
+			if (name[name.Length - 1] == '?') {
+				// canonicalize the user-specified nullable type
+				return CheckTypeName (type, string.Format ("System.Nullable<{0}>", name.Substring (0, name.Length - 1)));
+			}
+
+			if (type.IsArray) {
+				int startIndex = name.LastIndexOf ('[');
+				int endIndex = name.Length - 1;
+
+				if (startIndex == -1 || name[endIndex] != ']') {
+					// the user-specified type is not an array
+					return false;
+				}
+
+				var rank = name.Substring (startIndex + 1, endIndex - (startIndex + 1)).Split (new char[] { ',' });
+				if (rank.Length != type.GetArrayRank ())
+					return false;
+
+				return CheckTypeName (type.GetElementType (), name.Substring (0, startIndex).TrimEnd ());
+			}
+
+			if (type.IsPointer) {
+				if (name.Length < 2 || name[name.Length - 1] != '*')
+					return false;
+
+				return CheckTypeName (type.GetElementType (), name.Substring (0, name.Length - 1).TrimEnd ());
+			}
+
+			if (type.IsGenericType) {
+				int startIndex = name.IndexOf ('<');
+				int endIndex = name.Length - 1;
+
+				if (startIndex == -1 || name[endIndex] != '>') {
+					// the user-specified type is not a generic type
+					return false;
+				}
+
+				// make sure that the type name matches (minus generics)
+				string subName = name.Substring (0, startIndex);
+				string typeName = type.FullName;
+				int tick;
+
+				if ((tick = typeName.IndexOf ('`')) != -1)
+					typeName = typeName.Substring (0, tick);
+
+				if (!CheckTypeName (typeName, subName))
+					return false;
+
+				string[] paramTypes;
+				if (!FunctionBreakpoint.TryParseParameters (name, startIndex + 1, endIndex, out paramTypes))
+					return false;
+
+				TypeMirror[] argTypes = type.GetGenericArguments ();
+				if (paramTypes.Length != argTypes.Length)
+					return false;
+
+				for (int i = 0; i < paramTypes.Length; i++) {
+					if (!CheckTypeName (argTypes[i], paramTypes[i]))
+						return false;
+				}
+			} else if (!CheckTypeName (type.CSharpName, name)) {
+				if (!CheckTypeName (type.FullName, name))
+					return false;
+			}
+
+			return true;
+		}
+
+		static bool CheckMethodParams (MethodMirror method, string[] paramTypes)
+		{
+			if (paramTypes == null) {
+				// User supplied no params to match against, match anything we find.
+				return true;
+			}
+
+			var parameters = method.GetParameters ();
+			if (parameters.Length != paramTypes.Length)
+				return false;
+
+			for (int i = 0; i < paramTypes.Length; i++) {
+				if (!CheckTypeName (parameters[i].ParameterType, paramTypes[i]))
+					return false;
+			}
+
+			return true;
+		}
+		
+		bool IsGenericMethod (MethodMirror method)
+		{
+			return vm.Version.AtLeast (2, 12) && method.IsGenericMethod;
+		}
+		
+		IEnumerable<Location> FindFunctionLocations (string function, string[] paramTypes)
+		{
+			if (!started)
+				yield break;
+			
+			if (vm.Version.AtLeast (2, 9)) {
+				int dot = function.LastIndexOf ('.');
+				if (dot == -1 || dot + 1 == function.Length)
+					yield break;
+
+				// FIXME: handle types like GenericType<>, GenericType<SomeOtherType>, and GenericType<...>+NestedGenricType<...>
+				string methodName = function.Substring (dot + 1);
+				string typeName = function.Substring (0, dot);
+
+				// FIXME: need a way of querying all types so we can substring match typeName (e.g. user may have typed "Console" instead of "System.Console")
+				foreach (var type in vm.GetTypes (typeName, false)) {
+					ProcessType (type);
+					
+					foreach (var method in type.GetMethodsByNameFlags (methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, false)) {
+						if (!CheckMethodParams (method, paramTypes))
+							continue;
+						
+						Location location = GetLocFromMethod (method);
+						if (location != null)
+							yield return location;
+					}
+				}
+			}
+			
+			yield break;
+		}
+		
+		IList<Location> FindLocationsByFile (string file, int line, int column, out bool genericTypeOrMethod, out bool insideLoadedRange)
+		{
+			List<Location> locations = new List<Location> ();
+
+			genericTypeOrMethod = false;
+			insideLoadedRange = false;
+			
+			if (!started)
+				return locations;
+
+			string filename = PathToFileName (file);
+
+			//
+			// Fetch types matching the source file from the debuggee, and add them
+			// to the source file->type mapping tables.
+			// This is needed because we don't receive type load events for all types,
+			// just the ones which match a source file with an existing breakpoint.
+			//
+			if (vm.Version.AtLeast (2, 9)) {
+				//FIXME: do a case insensitive request on Win/Mac when sdb supports it (currently asserts NOTIMPLEMENTED)
+				var typesInFile = vm.GetTypesForSourceFile (filename, false);
+				
+				//HACK: explicitly try lowercased drivename on windows, since csc (when not hosted in VS) lowercases
+				//the drivename in the pdb files that get converted to mdbs as-is
+				if (typesInFile.Count == 0 && IsWindows) {
+					string alternateCaseFilename = char.ToLower (filename[0]) + filename.Substring (1);
+					typesInFile = vm.GetTypesForSourceFile (alternateCaseFilename, false);
+				}
+				
+				foreach (TypeMirror t in typesInFile)
+					ProcessType (t);
+			}
+
+			// Try already loaded types in the current source file
+			List<TypeMirror> types;
+
+			if (source_to_type.TryGetValue (filename, out types)) {
+				foreach (TypeMirror type in types) {
+					bool genericMethod;
+					bool insideRange;
+					
+					var loc = GetLocFromType (type, filename, line, column, out genericMethod, out insideRange);
+					if (insideRange)
+						insideLoadedRange = true;
+					
+					if (loc != null) {
+						if (genericMethod || type.IsGenericType)
+							genericTypeOrMethod = true;
+
+						locations.Add (loc);
+					}
+				}
+			}
+			
+			return locations;
+		}
+		
+		public override bool CanCancelAsyncEvaluations {
+			get {
+				return Adaptor.IsEvaluating;
+			}
+		}
+		
+		protected override void OnCancelAsyncEvaluations ()
+		{
+			Adaptor.CancelAsyncOperations ();
+		}
+		
+		protected override void OnNextInstruction ()
+		{
+			Step (StepDepth.Over, StepSize.Min);
+		}
+
+		protected override void OnNextLine ()
+		{
+			Step (StepDepth.Over, StepSize.Line);
+		}
+		
+		void Step (StepDepth depth, StepSize size)
+		{
+			ThreadPool.QueueUserWorkItem (delegate {
+				try {
+					Adaptor.CancelAsyncOperations (); // This call can block, so it has to run in background thread to avoid keeping the main session lock
+					var req = vm.CreateStepRequest (current_thread);
+					req.Depth = depth;
+					req.Size = size;
+					req.Filter = StepFilter.StaticCtor | StepFilter.DebuggerHidden | StepFilter.DebuggerStepThrough;
+					if (assemblyFilters != null && assemblyFilters.Count > 0)
+						req.AssemblyFilter = assemblyFilters;
+					req.Enabled = true;
+					currentStepRequest = req;
+					OnResumed ();
+					vm.Resume ();
+					DequeueEventsForFirstThread ();
+				} catch (CommandException ex) {
+					string reason;
+
+					switch (ex.ErrorCode) {
+					case ErrorCode.INVALID_FRAMEID: reason = "invalid frame id"; break;
+					case ErrorCode.NOT_SUSPENDED: reason = "VM not suspended"; break;
+					case ErrorCode.ERR_UNLOADED: reason = "AppDomain has been unloaded"; break;
+					case ErrorCode.NO_SEQ_POINT_AT_IL_OFFSET: reason = "no sequence point at the specified IL offset"; break;
+					default: reason = ex.ErrorCode.ToString (); break;
+					}
+
+					OnDebuggerOutput (true, string.Format ("Step request failed: {0}.", reason));
+					DebuggerLoggingService.LogError ("Step request failed", ex);
+				} catch (Exception ex) {
+					OnDebuggerOutput (true, string.Format ("Step request failed: {0}", ex.Message));
+					DebuggerLoggingService.LogError ("Step request failed", ex);
+				}
+			});
+		}
+
+		void EventHandler ()
+		{
+			while (true) {
+				try {
+					EventSet e = vm.GetNextEventSet ();
+					var type = e[0].EventType;
+					if (type == EventType.VMDeath || type == EventType.VMDisconnect) {
+						break;
+					}
+					HandleEventSet (e);
+				} catch (Exception ex) {
+					if (HasExited)
+						break;
+
+					if (!HandleException (ex))
+						OnDebuggerOutput (true, ex.ToString ());
+
+					if (ex is VMDisconnectedException || ex is IOException || ex is SocketException)
+						break;
+				}
+			}
+			
+			try {
+				// This is a workaround for a mono bug
+				// Without this call, the process may become zombie in mono < 2.10.2
+				if (vm.Process != null)
+					vm.Process.WaitForExit (1);
+			} catch {
+				// Ignore
+			}
+
+			OnTargetEvent (new TargetEventArgs (TargetEventType.TargetExited));
+		}
+		
+		protected override bool HandleException (Exception ex)
+		{
+			HideConnectionDialog ();
+
+			if (HasExited)
+				return true;
+			
+			if (ex is VMDisconnectedException || ex is IOException) {
+				ex = new DisconnectedException (ex);
+				HasExited = true;
+			} else if (ex is SocketException) {
+				ex = new DebugSocketException (ex);
+				HasExited = true;
+			}
+			
+			return base.HandleException (ex);
+		}
+		
+		// This method dispatches an event set.
+		//
+		// Based on the subset of events for which we register, and the contract for EventSet contents (equivalent to 
+		// Java - http://download.oracle.com/javase/1.5.0/docs/guide/jpda/jdi/com/sun/jdi/event/EventSet.html)
+		// we know that event sets we receive are either:
+		// 1) Set of step and break events for a location in a single thread.
+		// 2) Set of catchpoints for a single exception.
+		// 3) A single event of any other kind.
+		// We verify these assumptions where possible, because things will break in horrible ways if they are wrong.
+		//
+		// If we are currently stopped on a thread, and the break events are on a different thread, we must queue
+		// that event set and dequeue it next time we resume. This eliminates race conditions when multiple threads
+		// hit breakpoints or catchpoints simultaneously.
+		//
+		void HandleEventSet (EventSet es)
+		{
+#if DEBUG_EVENT_QUEUEING
+			if (!(es[0] is TypeLoadEvent))
+				Console.WriteLine ("pp eventset({0}): {1}", es.Events.Length, es[0]);
+#endif
+			var type = es[0].EventType;
+			bool isBreakEvent = type == EventType.Step || type == EventType.Breakpoint || type == EventType.Exception || type == EventType.UserBreak;
+			
+			if (isBreakEvent) {
+				if (current_thread != null && es[0].Thread.Id != current_thread.Id) {
+					QueueBreakEventSet (es.Events);
+				} else {
+					HandleBreakEventSet (es.Events, false);
+				}
+			} else {
+				if (es.Events.Length != 1)
+					throw new InvalidOperationException ("EventSet has unexpected combination of events");
+				HandleEvent (es[0]);
+
+				try {
+					vm.Resume ();
+				} catch (VMNotSuspendedException) {
+					var eventType = es [0].EventType;
+					var isTolerantEvent = eventType == EventType.VMStart || eventType == EventType.AssemblyLoad || eventType == EventType.TypeLoad 
+						|| eventType == EventType.ThreadStart || eventType == EventType.ThreadDeath
+						|| eventType == EventType.AppDomainCreate || eventType == EventType.AppDomainUnload;
+
+					if (eventType != EventType.VMStart && (vm.Version.AtLeast (2, 2) || !isTolerantEvent)) {
+						throw;
+					}
+				}
+			}
+		}
+		
+		static bool IsStepIntoRequest (StepEventRequest stepRequest)
+		{
+			return stepRequest.Depth == StepDepth.Into;
+		}
+		
+		static bool IsStepOutRequest (StepEventRequest stepRequest)
+		{
+			return stepRequest.Depth == StepDepth.Out;
+		}
+		
+		static bool IsPropertyOrOperatorMethod (MethodMirror method)
+		{
+			string name = method.Name;
+			
+			return method.IsSpecialName &&
+				(name.StartsWith ("get_", StringComparison.Ordinal) ||
+				 name.StartsWith ("set_", StringComparison.Ordinal) ||
+				 name.StartsWith ("op_", StringComparison.Ordinal));
+		}
+
+		bool IsUserAssembly (AssemblyMirror assembly)
+		{
+			if (userAssemblyNames == null)
+				return true;
+
+			var name = assembly.GetName ().FullName;
+
+			foreach (var n in userAssemblyNames) {
+				if (n == name)
+					return true;
+			}
+
+			return false;
+		}
+
+		bool IsAutoGeneratedFrameworkEnumerator (TypeMirror type)
+		{
+			if (IsUserAssembly (type.Assembly))
+				return false;
+
+			if (!SoftDebuggerAdaptor.IsGeneratedType (type))
+				return false;
+
+			foreach (var iface in type.GetInterfaces ()) {
+				if (iface.Namespace == "System.Collections" && iface.Name == "IEnumerator")
+					return true;
+			}
+
+			return false;
+		}
+		
+		void HandleBreakEventSet (Event[] es, bool dequeuing)
+		{
+			if (dequeuing && HasExited)
+				return;
+			
+			bool resume = true;
+			bool steppedOut = false;
+			bool steppedInto = false;
+			bool redoCurrentStep = false;
+			ObjectMirror exception = null;
+			TargetEventType etype = TargetEventType.TargetStopped;
+			BreakEvent breakEvent = null;
+			
+			if (es[0] is ExceptionEvent) {
+				var bad = es.FirstOrDefault (ee => ee.EventType != EventType.Exception);
+				if (bad != null)
+					throw new Exception ("Catchpoint eventset had unexpected event type " + bad.GetType ());
+				var ev = (ExceptionEvent)es[0];
+				if (ev.Request == unhandledExceptionRequest)
+					etype = TargetEventType.UnhandledException;
+				else
+					etype = TargetEventType.ExceptionThrown;
+				exception = ev.Exception;
+				if (ev.Request != unhandledExceptionRequest || exception.Type.FullName != "System.Threading.ThreadAbortException")
+					resume = false;
+			} else {
+				//always need to evaluate all breakpoints, some might be tracepoints or conditional bps with counters
+				foreach (Event e in es) {
+					if (e.EventType == EventType.Breakpoint) {
+						var be = (BreakpointEvent) e;
+						BreakInfo binfo;
+
+						if (!HandleBreakpoint (e.Thread, be.Request)) {
+							etype = TargetEventType.TargetHitBreakpoint;
+							autoStepInto = false;
+							resume = false;
+						}
+						
+						if (breakpoints.TryGetValue (be.Request, out binfo)) {
+							if (currentStepRequest != null &&
+							    binfo.Location.ILOffset == currentAddress && 
+							    e.Thread.Id == currentStepRequest.Thread.Id)
+								redoCurrentStep = true;
+							
+							breakEvent = binfo.BreakEvent;
+						}
+					} else if (e.EventType == EventType.Step) {
+						var stepRequest = e.Request as StepEventRequest;
+						steppedInto = IsStepIntoRequest (stepRequest);
+						steppedOut = IsStepOutRequest (stepRequest);
+						etype = TargetEventType.TargetStopped;
+						resume = false;
+					} else if (e.EventType == EventType.UserBreak) {
+						etype = TargetEventType.TargetStopped;
+						autoStepInto = false;
+						resume = false;
+					} else {
+						throw new Exception ("Break eventset had unexpected event type " + e.GetType ());
+					}
+				}
+			}
+			
+			if (redoCurrentStep) {
+				StepDepth depth = currentStepRequest.Depth;
+				StepSize size = currentStepRequest.Size;
+				
+				current_thread = recent_thread = es[0].Thread;
+				currentStepRequest.Enabled = false;
+				currentStepRequest = null;
+				
+				Step (depth, size);
+			} else if (resume) {
+				//all breakpoints were conditional and evaluated as false
+				vm.Resume ();
+				DequeueEventsForFirstThread ();
+			} else {
+				if (currentStepRequest != null) {
+					currentStepRequest.Enabled = false;
+					currentStepRequest = null;
+				}
+				
+				current_thread = recent_thread = es[0].Thread;
+				
+				if (exception != null)
+					activeExceptionsByThread [current_thread.ThreadId] = exception;
+				
+				var backtrace = GetThreadBacktrace (current_thread);
+				bool stepOut = false;
+				
+				if (backtrace.FrameCount > 0) {
+					var frame = backtrace.GetFrame (0) as SoftDebuggerStackFrame;
+					currentAddress = frame != null ? frame.Address : -1;
+					if (frame != null) {
+						if (steppedInto) {
+							if (Options.StepOverPropertiesAndOperators && IsPropertyOrOperatorMethod (frame.StackFrame.Method)) {
+								// We will want to call StepInto once StepOut returns...
+								autoStepInto = true;
+								stepOut = true;
+							} else if (IsAutoGeneratedFrameworkEnumerator (frame.StackFrame.Method.DeclaringType)) {
+								// User asked to step in, but we landed in an autogenerated type (probably an iterator)
+								autoStepInto = true;
+								stepOut = true;
+							}
+						}
+					}
+				}
+				
+				if (stepOut) {
+					Step (StepDepth.Out, StepSize.Min);
+				} else if (steppedOut && autoStepInto) {
+					autoStepInto = false;
+					Step (StepDepth.Into, StepSize.Min);
+				} else {
+					var args = new TargetEventArgs (etype);
+					args.Process = OnGetProcesses () [0];
+					args.Thread = GetThread (args.Process, current_thread);
+					args.Backtrace = backtrace;
+					args.BreakEvent = breakEvent;
+					
+					OnTargetEvent (args);
+				}
+			}
+		}
+		
+		void HandleEvent (Event e)
+		{
+			lock (pending_bes) {
+				switch (e.EventType) {
+				case EventType.AssemblyLoad: {
+					var ae = (AssemblyLoadEvent) e;
+					bool isExternal = !UpdateAssemblyFilters (ae.Assembly) && userAssemblyNames != null;
+					string flagExt = isExternal? " [External]" : "";
+					OnDebuggerOutput (false, string.Format ("Loaded assembly: {0}{1}\n", ae.Assembly.Location, flagExt));
+					break;
+				}
+				case EventType.AssemblyUnload: {
+					var aue = (AssemblyUnloadEvent) e;
+
+					if (assemblyFilters != null) {
+						int index = assemblyFilters.IndexOf (aue.Assembly);
+						if (index != -1)
+							assemblyFilters.RemoveAt (index);
+					}
+
+					// Mark affected breakpoints as pending again
+					var affectedBreakpoints = new List<KeyValuePair<EventRequest, BreakInfo>> (
+						breakpoints.Where (x=> (x.Value.Location.Method.DeclaringType.Assembly.Location.Equals (aue.Assembly.Location, StringComparison.OrdinalIgnoreCase)))
+					);
+					foreach (KeyValuePair<EventRequest,BreakInfo> breakpoint in affectedBreakpoints) {
+						string file = PathToFileName (breakpoint.Value.Location.SourceFile);
+						int line = breakpoint.Value.Location.LineNumber;
+						OnDebuggerOutput (false, string.Format ("Re-pending breakpoint at {0}:{1}\n", file, line));
+						breakpoints.Remove (breakpoint.Key);
+						pending_bes.Add (breakpoint.Value);
+					}
+
+					// Remove affected types from the loaded types list
+					var affectedTypes = new List<string> (
+						from pair in types
+						where pair.Value.Assembly.Location.Equals (aue.Assembly.Location, StringComparison.OrdinalIgnoreCase)
+						select pair.Key
+					);
+					foreach (string typename in affectedTypes) {
+						types.Remove (typename);
+					}
+
+					foreach (var pair in source_to_type) {
+						pair.Value.RemoveAll (delegate (TypeMirror mirror){
+							return mirror.Assembly.Location.Equals (aue.Assembly.Location, StringComparison.OrdinalIgnoreCase);
+						});
+					}
+					OnDebuggerOutput (false, string.Format ("Unloaded assembly: {0}\n", aue.Assembly.Location));
+					break;
+				}
+				case EventType.VMStart: {
+					OnStarted (new ThreadInfo (0, GetId (e.Thread), GetThreadName (e.Thread), null));
+					//HACK: 2.6.1 VM doesn't emit type load event, so work around it
+					var t = vm.RootDomain.Corlib.GetType ("System.Exception", false, false);
+					if (t != null)
+						ResolveBreakpoints (t);
+					break;
+				}
+				case EventType.TypeLoad: {
+					var t = ((TypeLoadEvent)e).Type;
+					string typeName = t.FullName;
+
+					if (types.ContainsKey (typeName)) {
+						/* This can happen since we manually add entries to 'types' */
+						/*
+						if (typeName != "System.Exception" && typeName != "<Module>")
+							DebuggerLoggingService.LogError ("Type '" + typeName + "' loaded more than once", null);
+						*/
+					} else {
+						ResolveBreakpoints (t);
+					}
+					break;
+				}
+				case EventType.ThreadStart: {
+					var ts = (ThreadStartEvent) e;
+					var name = GetThreadName (ts.Thread);
+					var id = GetId (ts.Thread);
+					OnDebuggerOutput (false, string.Format ("Thread started: {0} #{1}\n", name, id));
+					OnTargetEvent (new TargetEventArgs (TargetEventType.ThreadStarted) {
+						Thread = new ThreadInfo (0, id, name, null),
+					});
+					break;
+				}
+				case EventType.ThreadDeath: {
+					var ts = (ThreadDeathEvent) e;
+					var name = GetThreadName (ts.Thread);
+					var id = GetId (ts.Thread);
+					OnDebuggerOutput (false, string.Format ("Thread finished: {0} #{1}\n", name, id));
+					OnTargetEvent (new TargetEventArgs (TargetEventType.ThreadStopped) {
+						Thread = new ThreadInfo (0, id, ts.Thread.Name, null),
+					});
+					break;
+				}
+				case EventType.UserLog: {
+					var ul = (UserLogEvent) e;
+					OnDebuggerOutput (false, string.Format ("[{0}:{1}] {2}\n", ul.Level, ul.Category, ul.Message));
+					break;
+				}
+				default:
+					DebuggerLoggingService.LogMessage ("Unknown debugger event type {0}", e.GetType ());
+					break;
+				}
+			}
+		}
+
+		public ObjectMirror GetExceptionObject (ThreadMirror thread)
+		{
+			ObjectMirror obj;
+			if (activeExceptionsByThread.TryGetValue (thread.ThreadId, out obj))
+				return obj;
+
+			return null;
+		}
+		
+		void QueueBreakEventSet (Event[] eventSet)
+		{
+#if DEBUG_EVENT_QUEUEING
+			Console.WriteLine ("qq eventset({0}): {1}", eventSet.Length, eventSet[0]);
+#endif
+			var events = new List<Event> (eventSet);
+			lock (queuedEventSets) {
+				queuedEventSets.AddLast (events);
+			}
+		}
+		
+		void RemoveQueuedBreakEvents (List<EventRequest> requests)
+		{
+			int resume = 0;
+			
+			lock (queuedEventSets) {
+				var node = queuedEventSets.First;
+				
+				while (node != null) {
+					List<Event> q = node.Value;
+					
+					for (int i = 0; i < q.Count; i++) {
+						foreach (var request in requests) {
+							if (q[i].Request == request) {
+								q.RemoveAt (i--);
+								break;
+							}
+						}
+					}
+					
+					if (q.Count == 0) {
+						var d = node;
+						node = node.Next;
+						queuedEventSets.Remove (d);
+						resume++;
+					} else {
+						node = node.Next;
+					}
+				}
+			}
+			
+			for (int i = 0; i < resume; i++)
+				vm.Resume ();
+		}
+		
+		void DequeueEventsForFirstThread ()
+		{
+			List<List<Event>> dequeuing;
+			lock (queuedEventSets) {
+				if (queuedEventSets.Count < 1)
+					return;
+				
+				dequeuing = new List<List<Event>> ();
+				var node = queuedEventSets.First;
+				
+				//making this the current thread means that all events from other threads will get queued
+				current_thread = node.Value[0].Thread;
+				while (node != null) {
+					if (node.Value[0].Thread.Id == current_thread.Id) {
+						var d = node;
+						node = node.Next;
+						dequeuing.Add (d.Value);
+						queuedEventSets.Remove (d);
+					} else {
+						node = node.Next;
+					}
+				}
+			}
+
+#if DEBUG_EVENT_QUEUEING
+			foreach (var e in dequeuing)
+				Console.WriteLine ("dq eventset({0}): {1}", e.Count, e[0]);
+#endif
+
+			//firing this off in a thread prevents possible infinite recursion
+			ThreadPool.QueueUserWorkItem (delegate {
+				if (!HasExited) {
+					foreach (var es in dequeuing) {
+						try {
+							 HandleBreakEventSet (es.ToArray (), true);
+						} catch (Exception ex) {
+							if (!HandleException (ex))
+								OnDebuggerOutput (true, ex.ToString ());
+
+							if (ex is VMDisconnectedException || ex is IOException || ex is SocketException) {
+								OnTargetEvent (new TargetEventArgs (TargetEventType.TargetExited));
+								break;
+							}
+						}
+					}
+				}
+			});
+		}
+		
+		bool HandleBreakpoint (ThreadMirror thread, EventRequest er)
+		{
+			BreakInfo binfo;
+			if (!breakpoints.TryGetValue (er, out binfo))
+				return false;
+			
+			var bp = binfo.BreakEvent as Breakpoint;
+			if (bp == null)
+				return false;
+
+			binfo.IncrementHitCount ();
+			if (!binfo.HitCountReached)
+				return true;
+			
+			if (!string.IsNullOrEmpty (bp.ConditionExpression)) {
+				string res = EvaluateExpression (thread, bp.ConditionExpression, bp);
+				if (bp.BreakIfConditionChanges) {
+					if (res == binfo.LastConditionValue)
+						return true;
+					binfo.LastConditionValue = res;
+				} else {
+					if (res == null || res.ToLowerInvariant () != "true")
+						return true;
+				}
+			}
+			if ((bp.HitAction & HitAction.CustomAction) != HitAction.None) {
+				// If custom action returns true, execution must continue
+				return binfo.RunCustomBreakpointAction (bp.CustomActionId);
+			}
+
+			if ((bp.HitAction & HitAction.PrintExpression) != HitAction.None) {
+				string exp = EvaluateTrace (thread, bp.TraceExpression);
+				binfo.UpdateLastTraceValue (exp);
+			}
+
+			// Continue execution if we don't have break action.
+			return (bp.HitAction & HitAction.Break) == HitAction.None;
+		}
+		
+		string EvaluateTrace (ThreadMirror thread, string exp)
+		{
+			var sb = new StringBuilder ();
+			int last = 0;
+			int i = exp.IndexOf ('{');
+			while (i != -1) {
+				if (i < exp.Length - 1 && exp [i+1] == '{') {
+					sb.Append (exp.Substring (last, i - last + 1));
+					last = i + 2;
+					i = exp.IndexOf ('{', i + 2);
+					continue;
+				}
+				int j = exp.IndexOf ('}', i + 1);
+				if (j == -1)
+					break;
+				string se = exp.Substring (i + 1, j - i - 1);
+				se = EvaluateExpression (thread, se, null);
+				sb.Append (exp.Substring (last, i - last));
+				sb.Append (se);
+				last = j + 1;
+				i = exp.IndexOf ('{', last);
+			}
+			sb.Append (exp.Substring (last, exp.Length - last));
+			return sb.ToString ();
+		}
+
+		static SourceLocation GetSourceLocation (MDB.StackFrame frame)
+		{
+			return new SourceLocation (frame.Method.Name, frame.FileName, frame.LineNumber, frame.ColumnNumber);
+		}
+
+		static string FormatSourceLocation (Breakpoint bp)
+		{
+			if (string.IsNullOrEmpty (bp.FileName))
+				return null;
+
+			var location = Path.GetFileName (bp.FileName);
+			if (bp.OriginalLine > 0) {
+				location += ":" + bp.OriginalLine;
+				if (bp.OriginalColumn > 0)
+					location += "," + bp.OriginalColumn;
+			}
+
+			return location;
+		}
+
+		static bool IsBoolean (ValueReference vr)
+		{
+			if (vr.Type is Type && ((Type) vr.Type) == typeof (bool))
+				return true;
+
+			if (vr.Type is TypeMirror && ((TypeMirror) vr.Type).FullName == "System.Boolean")
+				return true;
+
+			return false;
+		}
+		
+		string EvaluateExpression (ThreadMirror thread, string expression, Breakpoint bp)
+		{
+			try {
+				var frames = thread.GetFrames ();
+				if (frames.Length == 0)
+					return string.Empty;
+
+				EvaluationOptions ops = Options.EvaluationOptions.Clone ();
+				ops.AllowTargetInvoke = true;
+
+				var ctx = new SoftEvaluationContext (this, frames[0], ops);
+
+				if (bp != null) {
+					// validate conditional breakpoint expressions so that we can provide error reporting to the user
+					var vr = ctx.Evaluator.ValidateExpression (ctx, expression);
+					if (!vr.IsValid) {
+						string message = string.Format ("Invalid expression in conditional breakpoint. {0}", vr.Message);
+						string location = FormatSourceLocation (bp);
+
+						if (!string.IsNullOrEmpty (location))
+							message = location + ": " + message;
+
+						OnDebuggerOutput (true, message);
+						return string.Empty;
+					}
+
+					// resolve types...
+					if (ctx.SourceCodeAvailable)
+						expression = ctx.Evaluator.Resolve (this, GetSourceLocation (frames[0]), expression);
+				}
+
+				ValueReference val = ctx.Evaluator.Evaluate (ctx, expression);
+				if (bp != null && !bp.BreakIfConditionChanges && !IsBoolean (val)) {
+					string message = string.Format ("Expression in conditional breakpoint did not evaluate to a boolean value: {0}", bp.ConditionExpression);
+					string location = FormatSourceLocation (bp);
+
+					if (!string.IsNullOrEmpty (location))
+						message = location + ": " + message;
+
+					OnDebuggerOutput (true, message);
+					return string.Empty;
+				}
+
+				return val.CreateObjectValue (false).Value;
+			} catch (EvaluatorException ex) {
+				string message;
+
+				if (bp != null) {
+					message = string.Format ("Failed to evaluate expression in conditional breakpoint. {0}", ex.Message);
+					string location = FormatSourceLocation (bp);
+
+					if (!string.IsNullOrEmpty (location))
+						message = location + ": " + message;
+				} else {
+					message = ex.ToString ();
+				}
+
+				OnDebuggerOutput (true, message);
+				return string.Empty;
+			} catch (Exception ex) {
+				OnDebuggerOutput (true, ex.ToString ());
+				return string.Empty;
+			}
+		}
+		
+		void ProcessType (TypeMirror t)
+		{
+			string typeName = t.FullName;
+
+			if (types.ContainsKey (typeName))
+				return;
+			types [typeName] = t;
+
+			//get the source file paths
+			//full paths, from GetSourceFiles (true), are only supported by sdb protocol 2.2 and later
+			string[] sourceFiles;
+			if (useFullPaths) {
+				sourceFiles = t.GetSourceFiles (true);
+			} else {
+				sourceFiles = t.GetSourceFiles ();
+				
+				//HACK: if mdb paths are windows paths but the sdb agent is on unix, it won't map paths to filenames correctly
+				if (IsWindows) {
+					for (int i = 0; i < sourceFiles.Length; i++) {
+						string s = sourceFiles[i];
+						if (s != null && !s.StartsWith ("/", StringComparison.Ordinal))
+							sourceFiles[i] = Path.GetFileName (s);
+					}
+				}
+			}
+			
+			for (int n=0; n<sourceFiles.Length; n++)
+				sourceFiles[n] = NormalizePath (sourceFiles[n]);
+
+			foreach (string s in sourceFiles) {
+				List<TypeMirror> typesList;
+				
+				if (source_to_type.TryGetValue (s, out typesList)) {
+					typesList.Add (t);
+				} else {
+					typesList = new List<TypeMirror> ();
+					typesList.Add (t);
+					source_to_type[s] = typesList;
+				}
+			}
+
+			type_to_source [t] = sourceFiles;
+		}
+		
+		static string[] GetParamTypes (MethodMirror method)
+		{
+			List<string> paramTypes = new List<string> ();
+			
+			foreach (var param in method.GetParameters ())
+				paramTypes.Add (param.ParameterType.CSharpName);
+			
+			return paramTypes.ToArray ();
+		}
+
+		string GetPrettyMethodName (MethodMirror method)
+		{
+			var name = new StringBuilder ();
+
+			name.Append (Adaptor.GetDisplayTypeName (method.ReturnType.FullName));
+			name.Append (" ");
+			name.Append (Adaptor.GetDisplayTypeName (method.DeclaringType.FullName));
+			name.Append (".");
+			name.Append (method.Name);
+
+			if (method.VirtualMachine.Version.AtLeast (2, 12)) {
+				if (method.IsGenericMethodDefinition || method.IsGenericMethod) {
+					name.Append ("<");
+					if (method.VirtualMachine.Version.AtLeast (2, 15)) {
+						var types = method.GetGenericArguments ();
+						for (int i = 0; i < types.Length; i++) {
+							if (i != 0)
+								name.Append (", ");
+							name.Append (Adaptor.GetDisplayTypeName (types[i].FullName));
+						}
+					}
+					name.Append (">");
+				}
+			}
+
+			name.Append (" (");
+			var @params = method.GetParameters ();
+			for (int i = 0; i < @params.Length; i++) {
+				if (i != 0)
+					name.Append (", ");
+				if (@params[i].Attributes.HasFlag (ParameterAttributes.Out)) {
+					if (@params[i].Attributes.HasFlag (ParameterAttributes.In))
+						name.Append ("ref ");
+					else
+						name.Append ("out ");
+				}
+				name.Append (Adaptor.GetDisplayTypeName (@params[i].ParameterType.FullName));
+				name.Append (" ");
+				name.Append (@params[i].Name);
+			}
+			name.Append (")");
+
+			return name.ToString ();
+		}
+
+		void ResolveBreakpoints (TypeMirror type)
+		{
+			var resolved = new List<BreakInfo> ();
+			Location loc;
+			
+			ProcessType (type);
+			
+			// First, resolve FunctionBreakpoints
+			foreach (var bi in pending_bes.Where (b => b.BreakEvent is FunctionBreakpoint)) {
+				if (CheckTypeName (type, bi.TypeName)) {
+					var bp = (FunctionBreakpoint) bi.BreakEvent;
+					string methodName = bp.FunctionName.Substring (bi.TypeName.Length + 1);
+					
+					foreach (var method in type.GetMethodsByNameFlags (methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, false)) {
+						if (!CheckMethodParams (method, bp.ParamTypes))
+							continue;
+						
+						loc = GetLocFromMethod (method);
+						if (loc != null) {
+							string paramList = "(" + string.Join (", ", bp.ParamTypes ?? GetParamTypes (method)) + ")";
+							OnDebuggerOutput (false, string.Format ("Resolved pending breakpoint for '{0}{1}' to {2}:{3} [0x{4:x5}].\n",
+							                                        bp.FunctionName, paramList, loc.SourceFile, loc.LineNumber, loc.ILOffset));
+
+							ResolvePendingBreakpoint (bi, loc);
+							
+							// Note: if the type or method is generic, there may be more instances so don't assume we are done resolving the breakpoint
+							if (bp.ParamTypes != null && !type.IsGenericType && !IsGenericMethod (method))
+								resolved.Add (bi);
+						}
+					}
+				}
+			}
+			
+			foreach (var be in resolved)
+				pending_bes.Remove (be);
+			resolved.Clear ();
+
+			// Now resolve normal Breakpoints
+			foreach (string s in type_to_source [type]) {
+				foreach (var bi in pending_bes.Where (b => (b.BreakEvent is Breakpoint) && !(b.BreakEvent is FunctionBreakpoint))) {
+					var bp = (Breakpoint) bi.BreakEvent;
+					if (PathsAreEqual (PathToFileName (bp.FileName), s)) {
+						bool insideLoadedRange;
+						bool genericMethod;
+						
+						loc = GetLocFromType (type, s, bp.Line, bp.Column, out genericMethod, out insideLoadedRange);
+						if (loc != null) {
+							OnDebuggerOutput (false, string.Format ("Resolved pending breakpoint at '{0}:{1},{2}' to {3} [0x{4:x5}].\n",
+							                                        s, bp.Line, bp.Column, GetPrettyMethodName (loc.Method), loc.ILOffset));
+							ResolvePendingBreakpoint (bi, loc);
+							
+							// Note: if the type or method is generic, there may be more instances so don't assume we are done resolving the breakpoint
+							if (!genericMethod && !type.IsGenericType)
+								resolved.Add (bi);
+						} else {
+							if (insideLoadedRange) {
+								bi.SetStatus (BreakEventStatus.Invalid, null);
+							}
+						}
+					}
+				}
+				
+				foreach (var be in resolved)
+					pending_bes.Remove (be);
+				resolved.Clear ();
+			}
+			
+			// Thirdly, resolve pending catchpoints
+			foreach (var bi in pending_bes.Where (b => b.BreakEvent is Catchpoint)) {
+				var cp = (Catchpoint) bi.BreakEvent;
+				if (cp.ExceptionName == type.FullName) {
+					ResolvePendingCatchpoint (bi, type);
+					resolved.Add (bi);
+				}
+			}
+			
+			foreach (var be in resolved)
+				pending_bes.Remove (be);
+		}
+		
+		internal static string NormalizePath (string path)
+		{
+			if (!IsWindows && path.StartsWith ("\\", StringComparison.Ordinal))
+				return path.Replace ('\\', '/');
+
+			return path;
+		}
+		
+		string PathToFileName (string path)
+		{
+			if (useFullPaths)
+				return path;
+			
+			return Path.GetFileName (path);
+		}
+
+		[DllImport ("libc")]
+		static extern IntPtr realpath (string path, IntPtr buffer);
+		
+		static string ResolveFullPath (string path)
+		{
+			if (IsWindows)
+				return Path.GetFullPath (path);
+
+			const int PATHMAX = 4096 + 1;
+			IntPtr buffer = IntPtr.Zero;
+
+			try {
+				buffer = Marshal.AllocHGlobal (PATHMAX);
+				var result = realpath (path, buffer);
+				return result == IntPtr.Zero ? "" : Marshal.PtrToStringAuto (buffer);
+			} finally {
+				if (buffer != IntPtr.Zero)
+					Marshal.FreeHGlobal (buffer);
+			}
+		}
+		
+		static bool PathsAreEqual (string p1, string p2)
+		{
+			if (string.IsNullOrWhiteSpace (p1) || string.IsNullOrWhiteSpace (p2))
+				return false;
+
+			if (PathComparer.Compare (p1, p2) == 0)
+				return true;
+
+			var rp1 = ResolveFullPath (p1);
+			var rp2 = ResolveFullPath (p2);
+
+			return PathComparer.Compare (rp1, rp2) == 0;
+		}
+		
+		Location GetLocFromMethod (MethodMirror method)
+		{
+			// Return the location of the method.
+			return method.Locations.Count > 0 ? method.Locations[0] : null;
+		}
+		
+		bool CheckBetterMatch (TypeMirror type, string file, int line, Location found)
+		{
+			if (type.Assembly == null)
+				return false;
+			
+			string assemblyFileName;
+			if (!assemblyPathMap.TryGetValue (type.Assembly.GetName ().FullName, out assemblyFileName))
+				assemblyFileName = type.Assembly.Location;
+			
+			if (assemblyFileName == null)
+				return false;
+			
+			string mdbFileName = assemblyFileName + ".mdb";
+			int foundDelta = found.LineNumber - line;
+			MonoSymbolFile mdb;
+			int fileId = -1;
+			
+			try {
+				if (!symbolFiles.TryGetValue (mdbFileName, out mdb)) {
+					if (!File.Exists (mdbFileName))
+						return false;
+					
+					mdb = MonoSymbolFile.ReadSymbolFile (mdbFileName);
+					symbolFiles.Add (mdbFileName, mdb);
+				}
+				
+				foreach (var src in mdb.Sources) {
+					if (src.FileName == file) {
+						fileId = src.Index;
+						break;
+					}
+				}
+				
+				if (fileId == -1)
+					return false;
+				
+				foreach (var method in mdb.Methods) {
+					var table = method.GetLineNumberTable ();
+					foreach (var entry in table.LineNumbers) {
+						if (entry.File != fileId)
+							continue;
+						
+						if (entry.Row >= line && (entry.Row - line) < foundDelta)
+							return true;
+					}
+				}
+			} catch {
+			}
+			
+			return false;
+		}
+		
+		Location GetLocFromType (TypeMirror type, string file, int line, int column, out bool genericMethod, out bool insideTypeRange)
+		{
+			Location target_loc = null;
+			bool fuzzy = true;
+			
+			insideTypeRange = false;
+			genericMethod = false;
+			
+			//Console.WriteLine ("Trying to resolve {0}:{1},{2} in type {3}", file, line, column, type.Name);
+			foreach (MethodMirror method in type.GetMethods ()) {
+				List<Location> locations = new List<Location> ();
+				int rangeFirstLine = int.MaxValue;
+				int rangeLastLine = -1;
+				
+				foreach (Location location in method.Locations) {
+					string srcFile = location.SourceFile;
+					
+					//Console.WriteLine ("\tExamining {0}:{1}...", srcFile, location.LineNumber);
+
+					if (srcFile != null && PathsAreEqual (PathToFileName (NormalizePath (srcFile)), file)) {
+						if (location.LineNumber < rangeFirstLine)
+							rangeFirstLine = location.LineNumber;
+						
+						if (location.LineNumber > rangeLastLine)
+							rangeLastLine = location.LineNumber;
+						
+						if (line >= rangeFirstLine && line <= rangeLastLine)
+							insideTypeRange = true;
+
+						if (location.LineNumber >= line && line >= rangeFirstLine) {
+							if (target_loc != null) {
+								if (location.LineNumber > line) {
+									if (target_loc.LineNumber - line > location.LineNumber - line) {
+										// Grab the location closest to the requested line
+										//Console.WriteLine ("\t\tLocation is closest match. (ILOffset = 0x{0:x5})", location.ILOffset);
+										locations.Clear ();
+										locations.Add (location);
+										target_loc = location;
+									}
+								} else if (target_loc.LineNumber != line) {
+									// Previous match was a fuzzy match, but now we've found an exact line match
+									//Console.WriteLine ("\t\tLocation is exact line match. (ILOffset = 0x{0:x5})", location.ILOffset);
+									locations.Clear ();
+									locations.Add (location);
+									target_loc = location;
+									fuzzy = false;
+								} else {
+									// Line number matches exactly, use the location with the lowest ILOffset
+									if (location.ILOffset < target_loc.ILOffset)
+										target_loc = location;
+
+									locations.Add (location);
+									fuzzy = false;
+								}
+							} else {
+								//Console.WriteLine ("\t\tLocation is first possible match. (ILOffset = 0x{0:x5})", location.ILOffset);
+								fuzzy = location.LineNumber != line;
+								locations.Add (location);
+								target_loc = location;
+							}
+						}
+					} else {
+						rangeFirstLine = int.MaxValue;
+						rangeLastLine = -1;
+					}
+				}
+				
+				if (target_loc != null) {
+					genericMethod = IsGenericMethod (method);
+					
+					// If we got a fuzzy match, then we need to make sure that there isn't a better
+					// match in another method (e.g. code might have been extracted out into another
+					// method by the compiler.
+					if (!fuzzy) {
+						// Exact line match... now find the best column match.
+						locations.Sort (new LocationComparer ());
+
+						// Find the closest-matching location based on column.
+						target_loc = locations[0];
+						for (int i = 1; i < locations.Count; i++) {
+							if (locations[i].ColumnNumber > column)
+								break;
+
+							// if the column numbers match, then target_loc should have the lower ILOffset (which we want)
+							if (target_loc.ColumnNumber == locations[i].ColumnNumber)
+								continue;
+
+							target_loc = locations[i];
+						}
+
+						return target_loc;
+					}
+				}
+			}
+			
+			if (target_loc != null && fuzzy && CheckBetterMatch (type, file, line, target_loc)) {
+				insideTypeRange = false;
+				return null;
+			}
+			
+			return target_loc;
+		}
+
+		void ResolvePendingBreakpoint (BreakInfo bi, Location l)
+		{
+			bi.Location = l;
+			InsertBreakpoint ((Breakpoint) bi.BreakEvent, bi);
+			bi.SetStatus (BreakEventStatus.Bound, null);
+		}
+				
+		void ResolvePendingCatchpoint (BreakInfo bi, TypeMirror type)
+		{
+			InsertCatchpoint ((Catchpoint) bi.BreakEvent, bi, type);
+			bi.SetStatus (BreakEventStatus.Bound, null);
+		}
+		
+		bool UpdateAssemblyFilters (AssemblyMirror asm)
+		{
+			var name = asm.GetName ().FullName;
+			bool found = false;
+			if (userAssemblyNames != null) {
+				//HACK: not sure how else to handle xsp-compiled pages
+				if (name.StartsWith ("App_", StringComparison.Ordinal)) {
+					found = true;
+				} else {
+					foreach (var n in userAssemblyNames) {
+						if (n == name) {
+							found = true;
+							break;
+						}
+					}
+				}
+			}
+
+			if (found) {
+				assemblyFilters.Add (asm);
+				return true;
+			}
+
+			return false;
+		}
+		
+		internal void WriteDebuggerOutput (bool isError, string msg)
+		{
+			OnDebuggerOutput (isError, msg);
+		}
+		
+		protected override void OnSetActiveThread (long processId, long threadId)
+		{
+		}
+
+		protected override void OnStepInstruction ()
+		{
+			Step (StepDepth.Into, StepSize.Min);
+		}
+
+		protected override void OnStepLine ()
+		{
+			Step (StepDepth.Into, StepSize.Line);
+		}
+
+		protected override void OnStop ()
+		{
+			vm.Suspend ();
+			
+			//emit a stop event at the current position of the most recent thread
+			//we use "getprocesses" instead of "ongetprocesses" because it attaches the process to the session
+			//using private Mono.Debugging API, so our thread/backtrace calls will cache stuff that will get used later
+			var process = GetProcesses () [0];				
+			EnsureRecentThreadIsValid (process);
+			current_thread = recent_thread;
+			OnTargetEvent (new TargetEventArgs (TargetEventType.TargetStopped) {
+				Process = process,
+				Thread = GetThread (process, recent_thread),
+				Backtrace = GetThreadBacktrace (recent_thread)});
+		}
+		
+		void EnsureRecentThreadIsValid (ProcessInfo process)
+		{
+			var infos = process.GetThreads ();
+			
+			if (ThreadIsAlive (recent_thread) && HasUserFrame (GetId (recent_thread), infos))
+				return;
+
+			var threads = vm.GetThreads ();
+			foreach (var thread in threads) {
+				if (ThreadIsAlive (thread) && HasUserFrame (GetId (thread), infos)) {
+					recent_thread = thread;
+					return;
+				}
+			}
+			recent_thread = threads[0];	
+		}
+		
+		long GetId (ThreadMirror thread)
+		{
+			long id;
+			if (!localThreadIds.TryGetValue (thread.ThreadId, out id)) {
+				id = localThreadIds.Count + 1;
+				localThreadIds [thread.ThreadId] = id;
+			}
+			return id;
+		}
+		
+		static bool ThreadIsAlive (ThreadMirror thread)
+		{
+			if (thread == null)
+				return false;
+			var state = thread.ThreadState;
+			return state != ThreadState.Stopped && state != ThreadState.Aborted;
+		}
+		
+		//we use the Mono.Debugging classes because they are cached
+		bool HasUserFrame (long tid, ThreadInfo[] infos)
+		{
+			foreach (var t in infos) {
+				if (t.Id != tid)
+					continue;
+				var bt = t.Backtrace;
+				for (int i = 0; i < bt.FrameCount; i++) {
+					var frame = bt.GetFrame (i);
+					if (frame != null && !frame.IsExternalCode)
+						return true;
+				}
+				return false;
+			}
+			return false;
+		}
+		
+		public bool IsExternalCode (Mono.Debugger.Soft.StackFrame frame)
+		{
+			return frame.Method == null || string.IsNullOrEmpty (frame.FileName)
+				|| (assemblyFilters != null && !assemblyFilters.Contains (frame.Method.DeclaringType.Assembly));
+		}
+		
+		public bool IsExternalCode (TypeMirror type)
+		{
+			return assemblyFilters != null && !assemblyFilters.Contains (type.Assembly);
+		}
+		
+		protected override AssemblyLine[] OnDisassembleFile (string file)
+		{
+			List<TypeMirror> types;
+			if (!source_to_type.TryGetValue (file, out types))
+				return new AssemblyLine [0];
+			
+			var lines = new List<AssemblyLine> ();
+			foreach (TypeMirror type in types) {
+				foreach (MethodMirror met in type.GetMethods ()) {
+					string srcFile = met.SourceFile != null ? NormalizePath (met.SourceFile) : null;
+					
+					if (srcFile == null || !PathsAreEqual (srcFile, file))
+						continue;
+					
+					var body = met.GetMethodBody ();
+					int lastLine = -1;
+					int firstPos = lines.Count;
+					string addrSpace = met.FullName;
+					
+					foreach (var ins in body.Instructions) {
+						Location loc = met.LocationAtILOffset (ins.Offset);
+						if (loc != null && lastLine == -1) {
+							lastLine = loc.LineNumber;
+							for (int n=firstPos; n<lines.Count; n++) {
+								AssemblyLine old = lines [n];
+								lines [n] = new AssemblyLine (old.Address, old.AddressSpace, old.Code, loc.LineNumber);
+							}
+						}
+						lines.Add (new AssemblyLine (ins.Offset, addrSpace, Disassemble (ins), loc != null ? loc.LineNumber : lastLine));
+					}
+				}
+			}
+			lines.Sort (delegate (AssemblyLine a1, AssemblyLine a2) {
+				int res = a1.SourceLine.CompareTo (a2.SourceLine);
+				if (res != 0)
+					return res;
+
+				return a1.Address.CompareTo (a2.Address);
+			});
+			return lines.ToArray ();
+		}
+		
+		public AssemblyLine[] Disassemble (Mono.Debugger.Soft.StackFrame frame, int firstLine, int count)
+		{
+			MethodBodyMirror body = frame.Method.GetMethodBody ();
+			var instructions = body.Instructions;
+			ILInstruction current = null;
+			foreach (var ins in instructions) {
+				if (ins.Offset >= frame.ILOffset) {
+					current = ins;
+					break;
+				}
+			}
+			if (current == null)
+				return new AssemblyLine [0];
+			
+			var result = new List<AssemblyLine> ();
+			
+			int pos = firstLine;
+			
+			while (firstLine < 0 && count > 0) {
+				if (current.Previous == null) {
+//					result.Add (new AssemblyLine (99999, "<" + (pos++) + ">"));
+					result.Add (AssemblyLine.OutOfRange);
+					count--;
+					firstLine++;
+				} else {
+					current = current.Previous;
+					firstLine++;
+				}
+			}
+			
+			while (current != null && firstLine > 0) {
+				current = current.Next;
+				firstLine--;
+			}
+			
+			while (count > 0) {
+				if (current != null) {
+					Location loc = frame.Method.LocationAtILOffset (current.Offset);
+					result.Add (new AssemblyLine (current.Offset, frame.Method.FullName, Disassemble (current), loc != null ? loc.LineNumber : -1));
+					current = current.Next;
+					pos++;
+				} else
+					result.Add (AssemblyLine.OutOfRange);
+//					result.Add (new AssemblyLine (99999, "<" + (pos++) + ">"));
+				count--;
+			}
+			return result.ToArray ();
+		}
+
+		static string EscapeString (string text)
+		{
+			StringBuilder sb = new StringBuilder ();
+			
+			sb.Append ('"');
+			for (int i = 0; i < text.Length; i++) {
+				char c = text[i];
+				string txt;
+				switch (c) {
+				case '"': txt = "\\\""; break;
+				case '\0': txt = @"\0"; break;
+				case '\\': txt = @"\\"; break;
+				case '\a': txt = @"\a"; break;
+				case '\b': txt = @"\b"; break;
+				case '\f': txt = @"\f"; break;
+				case '\v': txt = @"\v"; break;
+				case '\n': txt = @"\n"; break;
+				case '\r': txt = @"\r"; break;
+				case '\t': txt = @"\t"; break;
+				default:
+					if (char.GetUnicodeCategory (c) == UnicodeCategory.OtherNotAssigned) {
+						sb.AppendFormat ("\\u{0:X4}", c);
+					} else {
+						sb.Append (c);
+					}
+					continue;
+				}
+				sb.Append (txt);
+			}
+			sb.Append ('"');
+			
+			return sb.ToString ();
+		}
+		
+		string Disassemble (ILInstruction ins)
+		{
+			string oper;
+			if (ins.Operand is MethodMirror)
+				oper = ((MethodMirror)ins.Operand).FullName;
+			else if (ins.Operand is TypeMirror)
+				oper = ((TypeMirror)ins.Operand).FullName;
+			else if (ins.Operand is ILInstruction)
+				oper = ((ILInstruction)ins.Operand).Offset.ToString ("x8");
+			else if (ins.Operand is string)
+				oper = EscapeString ((string) ins.Operand);
+			else if (ins.Operand == null)
+				oper = string.Empty;
+			else
+				oper = ins.Operand.ToString ();
+			
+			return ins.OpCode + " " + oper;
+		}
+		
+		readonly static bool IsWindows;
+		readonly static bool IsMac;
+		readonly static StringComparer PathComparer;
+		
+		static bool IgnoreFilenameCase {
+			get {
+				return IsMac || IsWindows;
+			}
+		}
+		
+		static SoftDebuggerSession ()
+		{
+			IsWindows = Path.DirectorySeparatorChar == '\\';
+			IsMac = !IsWindows && IsRunningOnMac();
+			PathComparer = (IgnoreFilenameCase)? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
+			ThreadMirror.NativeTransitions = true;
+		}
+		
+		//From Managed.Windows.Forms/XplatUI
+		static bool IsRunningOnMac ()
+		{
+			IntPtr buf = IntPtr.Zero;
+			try {
+				buf = Marshal.AllocHGlobal (8192);
+				// This is a hacktastic way of getting sysname from uname ()
+				if (uname (buf) == 0) {
+					string os = Marshal.PtrToStringAnsi (buf);
+					if (os == "Darwin")
+						return true;
+				}
+			} catch {
+			} finally {
+				if (buf != IntPtr.Zero)
+					Marshal.FreeHGlobal (buf);
+			}
+			return false;
+		}
+		
+		[System.Runtime.InteropServices.DllImport ("libc")]
+		static extern int uname (IntPtr buf);
+	}
+
+	class LocationComparer : IComparer<Location>
+	{
+		public int Compare (Location loc0, Location loc1)
+		{
+			if (loc0.LineNumber < loc1.LineNumber)
+				return -1;
+			if (loc0.LineNumber > loc1.LineNumber)
+				return 1;
+
+			if (loc0.ColumnNumber < loc1.ColumnNumber)
+				return -1;
+			if (loc0.ColumnNumber > loc1.ColumnNumber)
+				return 1;
+
+			return loc0.ILOffset - loc1.ILOffset;
+		}
+	}
+	
+	class BreakInfo: BreakEventInfo
+	{
+		public Location Location;
+		public List<EventRequest> Requests = new List<EventRequest> ();
+		public string LastConditionValue;
+		public string FileName;
+		public string TypeName;
+	}
+	
+	class DisconnectedException: DebuggerException
+	{
+		public DisconnectedException (Exception ex):
+			base ("The connection with the debugger has been lost. The target application may have exited.", ex)
+		{
+		}
+	}
+	
+	class DebugSocketException: DebuggerException
+	{
+		public DebugSocketException (Exception ex):
+			base ("Could not open port for debugger. Another process may be using the port.", ex)
+		{
+		}
+	}
+	
+	class ConnectionException : DebuggerException
+	{
+		public ConnectionException (Exception ex):
+			base ("Could not connect to the debugger.", ex)
+		{
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/SoftDebuggerStartInfo.cs b/Mono.Debugging.Soft/SoftDebuggerStartInfo.cs
new file mode 100644
index 0000000..d51e603
--- /dev/null
+++ b/Mono.Debugging.Soft/SoftDebuggerStartInfo.cs
@@ -0,0 +1,203 @@
+// 
+// SoftDebuggerStartInfo.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Client;
+using System.Collections.Generic;
+using System.Reflection;
+using System.IO;
+using System.Net;
+using Mono.Debugger.Soft;
+
+namespace Mono.Debugging.Soft
+{
+	public class SoftDebuggerStartInfo : DebuggerStartInfo
+	{
+		public SoftDebuggerStartInfo (string monoRuntimePrefix, Dictionary<string,string> monoRuntimeEnvironmentVariables)
+			: this (new SoftDebuggerLaunchArgs (monoRuntimePrefix, monoRuntimeEnvironmentVariables))
+		{
+		}
+		
+		public SoftDebuggerStartInfo (SoftDebuggerStartArgs startArgs)
+		{
+			if (startArgs == null)
+				throw new ArgumentNullException ("startArgs");
+			this.StartArgs = startArgs;
+		}
+		
+		/// <summary>
+		/// Names of assemblies that are user code.
+		/// </summary>
+		public List<AssemblyName> UserAssemblyNames { get; set; }
+		
+		/// <summary>
+		/// A mapping of AssemblyNames to their paths.
+		/// </summary>
+		public Dictionary<string, string> AssemblyPathMap { get; set; }
+		
+		/// <summary>
+		/// The session will output this to the debug log as soon as it starts. It can be used to log warnings from
+		/// creating the SoftDebuggerStartInfo
+		/// </summary>
+		public string LogMessage { get; set; }
+		
+		/// <summary>
+		/// Args for starting the debugger connection.
+		/// </summary>
+		public SoftDebuggerStartArgs StartArgs { get; set; }
+	}
+	
+	public interface ISoftDebuggerConnectionProvider
+	{
+		IAsyncResult BeginConnect (DebuggerStartInfo dsi, AsyncCallback callback);
+		void EndConnect (IAsyncResult result, out VirtualMachine vm, out string appName);
+		void CancelConnect (IAsyncResult result);
+		bool ShouldRetryConnection (Exception ex);
+	}
+	
+	public abstract class SoftDebuggerStartArgs
+	{
+		public SoftDebuggerStartArgs ()
+		{
+			MaxConnectionAttempts = 1;
+			TimeBetweenConnectionAttempts = 500;
+		}
+		
+		public abstract ISoftDebuggerConnectionProvider ConnectionProvider { get; }
+		
+		/// <summary>
+		/// Maximum number of connection attempts. Zero or less means infinite attempts. Default is 1.
+		/// </summary>
+		public int MaxConnectionAttempts { get; set; }
+		
+		/// <summary>
+		/// The time between connection attempts, in milliseconds. Default is 500.
+		/// </summary>
+		public int TimeBetweenConnectionAttempts { get; set; }
+	}
+	
+	public abstract class SoftDebuggerRemoteArgs : SoftDebuggerStartArgs
+	{
+		public SoftDebuggerRemoteArgs (string appName, IPAddress address, int debugPort, int outputPort)
+		{
+			if (address == null)
+				throw new ArgumentNullException ("address");
+			if (debugPort < 0)
+				throw new ArgumentException ("Debug port cannot be less than zero", "debugPort");
+			
+			this.AppName = appName;
+			this.Address = address;
+			this.DebugPort = debugPort;
+			this.OutputPort = outputPort;
+		}
+		
+		/// <summary>
+		/// The IP address for the connection.
+		/// </summary>
+		public IPAddress Address { get; private set; }
+		
+		/// <summary>
+		/// Port for the debugger connection. Zero means random port.
+		/// </summary>
+		public int DebugPort { get; private set; }
+		
+		/// <summary>
+		/// Port for the console connection. Zero means random port, less than zero means that output is not redirected.
+		/// </summary>
+		public int OutputPort { get; private set; }
+		
+		/// <summary>
+		/// Application name that will be shown in the debugger.
+		/// </summary>
+		public string AppName { get; private set; }
+		
+		public bool RedirectOutput { get { return OutputPort >= 0; } }
+	}
+	
+	/// <summary>
+	/// Args for the debugger to listen for an incoming connection from a debuggee.
+	/// </summary>
+	public sealed class SoftDebuggerListenArgs : SoftDebuggerRemoteArgs
+	{
+		public SoftDebuggerListenArgs (string appName, IPAddress address, int debugPort)
+			: this (appName, address, debugPort, -1) {}
+		
+		public SoftDebuggerListenArgs (string appName, IPAddress address, int debugPort, int outputPort)
+			: base (appName, address, debugPort, outputPort)
+		{
+		}
+		
+		public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
+	}
+	
+	/// <summary>
+	/// Args for the debugger to connect to target that is listening.
+	/// </summary>
+	public sealed class SoftDebuggerConnectArgs : SoftDebuggerRemoteArgs
+	{
+		public SoftDebuggerConnectArgs (string appName, IPAddress address, int debugPort)
+			: this (appName, address, debugPort, -1) {}
+		
+		public SoftDebuggerConnectArgs (string appName, IPAddress address, int debugPort, int outputPort)
+			: base (appName, address, debugPort, outputPort)
+		{
+			if (debugPort == 0)
+				throw new ArgumentException ("Debug port cannot be zero when connecting", "debugPort");
+			if (outputPort == 0)
+				throw new ArgumentException ("Output port cannot be zero when connecting", "outputPort");
+		}
+		
+		public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
+	}
+	
+	/// <summary>
+	/// Options for the debugger to start a process directly.
+	/// </summary>
+	public sealed class SoftDebuggerLaunchArgs : SoftDebuggerStartArgs
+	{
+		public SoftDebuggerLaunchArgs (string monoRuntimePrefix, Dictionary<string,string> monoRuntimeEnvironmentVariables)
+		{
+			this.MonoRuntimePrefix = monoRuntimePrefix;
+			this.MonoRuntimeEnvironmentVariables = monoRuntimeEnvironmentVariables;
+		}
+		
+		/// <summary>
+		/// Prefix into which the target Mono runtime is installed.
+		/// </summary>
+		public string MonoRuntimePrefix { get; private set; }
+		
+		/// <summary>
+		/// Environment variables for the Mono runtime.
+		/// </summary>
+		public Dictionary<string,string> MonoRuntimeEnvironmentVariables { get; private set; }
+		
+		/// <summary>
+		/// Launcher for the external console. May be null if the app does not run on an external console.
+		/// </summary>
+		public Mono.Debugger.Soft.LaunchOptions.TargetProcessLauncher ExternalConsoleLauncher { get; set; }
+		
+		public override ISoftDebuggerConnectionProvider ConnectionProvider { get { return null; } }
+	}
+}
\ No newline at end of file
diff --git a/Mono.Debugging.Soft/SoftEvaluationContext.cs b/Mono.Debugging.Soft/SoftEvaluationContext.cs
new file mode 100644
index 0000000..ced30d6
--- /dev/null
+++ b/Mono.Debugging.Soft/SoftEvaluationContext.cs
@@ -0,0 +1,186 @@
+// 
+// SoftEvaluationContext.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Evaluation;
+using Mono.Debugger.Soft;
+using DC = Mono.Debugging.Client;
+
+namespace Mono.Debugging.Soft
+{
+	public class SoftEvaluationContext: EvaluationContext
+	{
+		SoftDebuggerSession session;
+		int stackVersion;
+		StackFrame frame;
+		bool sourceAvailable;
+		
+		public ThreadMirror Thread { get; set; }
+		
+		public SoftEvaluationContext (SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options): base (options)
+		{
+			Frame = frame;
+			Thread = frame.Thread;
+
+			string method = frame.Method.Name;
+			if (frame.Method.DeclaringType != null)
+				method = frame.Method.DeclaringType.FullName + "." + method;
+			var location = new DC.SourceLocation (method, frame.FileName, frame.LineNumber, frame.ColumnNumber);
+			string language;
+
+			if (frame.Method != null) {
+				if (frame.IsNativeTransition) {
+					language = "Transition";
+				} else {
+					language = "Managed";
+				}
+			} else {
+				language = "Native";
+			}
+			
+			Evaluator = session.GetEvaluator (new DC.StackFrame (frame.ILOffset, location, language, session.IsExternalCode (frame), true));
+			Adapter = session.Adaptor;
+			this.session = session;
+			this.stackVersion = session.StackVersion;
+			sourceAvailable = !string.IsNullOrEmpty (frame.FileName) && System.IO.File.Exists (frame.FileName);
+		}
+		
+		public StackFrame Frame {
+			get {
+				if (stackVersion != session.StackVersion)
+					UpdateFrame ();
+				return frame;
+			}
+			set {
+				frame = value;
+			}
+		}
+		
+		public bool SourceCodeAvailable {
+			get {
+				if (stackVersion != session.StackVersion)
+					sourceAvailable = !string.IsNullOrEmpty (Frame.FileName) && System.IO.File.Exists (Frame.FileName);
+				return sourceAvailable;
+			}
+		}
+		
+		public SoftDebuggerSession Session {
+			get { return session; }
+		}
+		
+		public override void WriteDebuggerError (Exception ex)
+		{
+			session.WriteDebuggerOutput (true, ex.ToString ());
+		}
+		
+		public override void WriteDebuggerOutput (string message, params object[] values)
+		{
+			session.WriteDebuggerOutput (false, string.Format (message, values));
+		}
+
+		public override void CopyFrom (EvaluationContext ctx)
+		{
+			base.CopyFrom (ctx);
+			SoftEvaluationContext other = (SoftEvaluationContext) ctx;
+			frame = other.frame;
+			stackVersion = other.stackVersion;
+			Thread = other.Thread;
+			session = other.session;
+		}
+
+		static bool IsValueTypeOrPrimitive (TypeMirror type)
+		{
+			return type != null && (type.IsValueType || type.IsPrimitive);
+		}
+
+		static bool IsValueTypeOrPrimitive (Type type)
+		{
+			return type != null && (type.IsValueType || type.IsPrimitive);
+		}
+		
+		public Value RuntimeInvoke (MethodMirror method, object target, Value[] values)
+		{
+			if (values != null) {
+				// Some arguments may need to be boxed
+				ParameterInfoMirror[] mparams = method.GetParameters ();
+				if (mparams.Length != values.Length)
+					throw new EvaluatorException ("Invalid number of arguments when calling: " + method.Name);
+				
+				for (int n = 0; n < mparams.Length; n++) {
+					TypeMirror tm = mparams [n].ParameterType;
+					if (tm.IsValueType || tm.IsPrimitive)
+						continue;
+
+					object type = Adapter.GetValueType (this, values [n]);
+					TypeMirror argTypeMirror = type as TypeMirror;
+					Type argType = type as Type;
+
+					if (IsValueTypeOrPrimitive (argTypeMirror) || IsValueTypeOrPrimitive (argType)) {
+						// A value type being assigned to a parameter which is not a value type. The value has to be boxed.
+						try {
+							values [n] = Thread.Domain.CreateBoxedValue (values [n]);
+						} catch (NotSupportedException) {
+							// This runtime doesn't support creating boxed values
+							throw new EvaluatorException ("This runtime does not support creating boxed values.");
+						}
+					}
+				}
+			}
+
+			if (!method.IsStatic && method.DeclaringType.IsClass && !IsValueTypeOrPrimitive (method.DeclaringType)) {
+				object type = Adapter.GetValueType (this, target);
+				TypeMirror targetTypeMirror = type as TypeMirror;
+				Type targetType = type as Type;
+
+				if ((target is StructMirror && ((StructMirror) target).Type != method.DeclaringType) ||
+				    (IsValueTypeOrPrimitive (targetTypeMirror) || IsValueTypeOrPrimitive (targetType))) {
+					// A value type being assigned to a parameter which is not a value type. The value has to be boxed.
+					try {
+						target = Thread.Domain.CreateBoxedValue ((Value) target);
+					} catch (NotSupportedException) {
+						// This runtime doesn't support creating boxed values
+						throw new EvaluatorException ("This runtime does not support creating boxed values.");
+					}
+				}
+			}
+			
+			MethodCall mc = new MethodCall (this, method, target, values);
+			Adapter.AsyncExecute (mc, Options.EvaluationTimeout);
+			return mc.ReturnValue;
+		}
+		
+		void UpdateFrame ()
+		{
+			stackVersion = session.StackVersion;
+			foreach (StackFrame f in Thread.GetFrames ()) {
+				if (f.FileName == Frame.FileName && f.LineNumber == Frame.LineNumber && f.ILOffset == Frame.ILOffset) {
+					Frame = f;
+					break;
+				}
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/StringAdaptor.cs b/Mono.Debugging.Soft/StringAdaptor.cs
new file mode 100644
index 0000000..6fb73c0
--- /dev/null
+++ b/Mono.Debugging.Soft/StringAdaptor.cs
@@ -0,0 +1,76 @@
+// 
+// StringAdaptor.cs
+//  
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2012 Xamarin Inc.
+// 
+// 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 Mono.Debugging.Evaluation;
+using Mono.Debugger.Soft;
+
+namespace Mono.Debugging.Soft
+{
+	public class StringAdaptor: IStringAdaptor
+	{
+		bool atleast_2_10;
+		StringMirror str;
+		string val;
+		
+		public StringAdaptor (StringMirror str)
+		{
+			atleast_2_10 = str.VirtualMachine.Version.AtLeast (2, 10);
+			this.str = str;
+		}
+		
+		public int Length {
+			get {
+				if (atleast_2_10)
+					return str.Length;
+				
+				if (val == null)
+					val = str.Value;
+				
+				return val.Length;
+			}
+		}
+		
+		public string Value {
+			get {
+				if (val == null)
+					val = str.Value;
+				
+				return val;
+			}
+		}
+		
+		public string Substring (int index, int length)
+		{
+			if (val == null && atleast_2_10)
+				return new string (str.GetChars (index, length));
+			
+			if (val == null)
+				val = str.Value;
+			
+			return val.Substring (index, length);
+		}
+	}
+}
diff --git a/Mono.Debugging.Soft/VariableValueReference.cs b/Mono.Debugging.Soft/VariableValueReference.cs
new file mode 100644
index 0000000..cb04ea6
--- /dev/null
+++ b/Mono.Debugging.Soft/VariableValueReference.cs
@@ -0,0 +1,88 @@
+// 
+// VariableValueReference.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Evaluation;
+using Mono.Debugging.Client;
+using Mono.Debugger.Soft;
+
+namespace Mono.Debugging.Soft
+{
+	public class VariableValueReference : ValueReference
+	{
+		string name;
+		LocalVariable variable;
+		
+		public VariableValueReference (EvaluationContext ctx, string name, LocalVariable variable): base (ctx)
+		{
+			this.name = name;
+			this.variable = variable;
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Variable;
+			}
+		}
+
+		public override string Name {
+			get {
+				return name;
+			}
+		}
+
+		public override object Type {
+			get {
+				return variable.Type;
+			}
+		}
+
+		public override object Value {
+			get {
+				SoftEvaluationContext ctx = (SoftEvaluationContext) Context;
+				try {
+					var value = ctx.Frame.GetValue (variable);
+
+					if (variable.Type.IsPointer) {
+						long addr = (long) ((PrimitiveValue) value).Value;
+						value = new PointerValue (value.VirtualMachine, variable.Type, addr);
+					}
+
+					return value;
+				} catch (AbsentInformationException) {
+					throw new EvaluatorException ("Value not available");
+				} catch (ArgumentException ex) {
+					throw new EvaluatorException (ex.Message);
+				}
+			}
+			set {
+				SoftEvaluationContext ctx = (SoftEvaluationContext) Context;
+				ctx.Frame.SetValue (variable, (Value) value);
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/ChangeLog b/Mono.Debugging/ChangeLog
new file mode 100644
index 0000000..beef217
--- /dev/null
+++ b/Mono.Debugging/ChangeLog
@@ -0,0 +1,1032 @@
+2010-07-13  Levi Bard  <levi at unity3d.com>
+
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs: 
+	  Add method for unescaping strings.
+
+2010-05-20  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Dispose
+	  asynchronously.
+
+2010-05-20  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs:
+	* Mono.Debugging.Evaluation/ExceptionInfoSource.cs: Fix crash
+	  when getting locals which include the last thrown exception.
+
+2010-05-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Backend/IBacktrace.cs:
+	* Mono.Debugging.Client/ExceptionInfo.cs:
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs:
+	* Mono.Debugging.Evaluation/ExceptionInfoSource.cs: Introduced
+	  ExceptionInfo, which provides information about a caught
+	  exception, including description and stack traces.
+
+	* Mono.Debugging.Client/RawValue.cs:
+	* Mono.Debugging.Evaluation/RemoteRawValue.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs: Added
+	  evaluation options to raw value methods.
+
+	* Mono.Debugging.Client/ObjectValue.cs: Connect children
+	  directly added to the object value. Propagate eval options
+	  to raw value objects.
+
+2010-05-11  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/AsyncOperationManager.cs: Fixed
+	  deadlock while shuting down.
+
+2010-05-07  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: Added HasDebugInfo
+	  argument. When set to true, the stack frame won't try to get
+	  any information from the underlaying frame.
+
+2010-05-07  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Fix
+	  support for variable definition. Implement support for
+	  pre/post increment/decrement.
+
+2010-05-07  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/NullValueReference.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/LiteralValueReference.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs:
+	* Mono.Debugging.Evaluation/NamespaceValueReference.cs: Added
+	  an EvaluationOptions argument to all methods in
+	  IObjectValueSource. With this change options are not cached
+	  anymore in ValueReference objects. This fixes bug #602894
+	  and allows MD to change the evaluation options in the middle
+	  of a debugging session.
+
+2010-05-06  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs: Use async
+	  evaluation when getting the This and Execption values.
+
+2010-04-23  Carlo Kok  <ck at remobjects.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Client/IExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	  Allow for custom expression evaluators.
+	
+	
+2010-04-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/RawValue.cs:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/RemoteRawValue.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Add
+	  support for getting raw values of members and variables.
+
+2010-04-13  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Fix bug
+	  #595270 - Flags enums in debugger show the zero value.
+
+2010-03-23  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs: Child
+	  selector fixes. Fixes bug #588307 - Cannot pin an element of
+	  multidimensional array.
+
+2010-03-15  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/AsyncOperationManager.cs: Use
+	  corrent constant for infinite waits.
+
+2010-03-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/TypeValueReference.cs: Fixed type
+	  name formatting issue.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Fixed
+	  parsing of generic type names.
+
+2010-03-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/TypeValueReference.cs: Set the
+	  correct type name for the type reference.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Added hack
+	  which allows parsing single generic type names (that is,
+	  when the expression is a type name).
+
+2010-03-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Add a
+	  better default implementation for ForceLoadType.
+
+2010-03-01  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Fix null ref.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Type data
+	  should not be static.
+
+	* Mono.Debugging.Evaluation/NRefactoryResolverVisitor.cs:
+	  Improved resolution of generic types.
+
+2010-03-01  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Add
+	  support for indexer with more than one parameter.
+
+2010-02-26  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/EvaluationOptions.cs: Added clone
+	  method.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Fix crash
+	  when parsing enums.
+
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Reset
+	  the child selector for values which are only visual group of
+	  members.
+
+2010-02-24  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: Add null check.
+
+2010-02-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Backend/IBacktrace.cs:
+	* Mono.Debugging.Client/TargetEventArgs.cs:
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Added
+	  method for getting the current exception when a catchpoint
+	  is hit or an exception unhandled.
+
+2010-02-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: Fix win32 build.
+
+2010-02-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Backend/IBacktrace.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Add
+	  support for evaluating expressions. Allow specifying
+	  evaluation options when setting a value. Added option for
+	  displaying integers using hex format. Added wait handle for
+	  waiting for async evaluation completion on ObjectValue.
+
+2010-02-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Added delegate
+	  which is called when a tracepoint is hit.
+
+	* Mono.Debugging.Client/ObjectValue.cs: New ChildSelector
+	  property.
+
+	* Mono.Debugging.Evaluation/NRefactoryResolverVisitor.cs: Fix
+	  nullref.
+
+2010-02-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Added the
+	  SetBreakEventStatus method, which can be used by subclasses
+	  to set a breakpoint as invalid. Added some docs.
+
+2010-02-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryResolverVisitor.cs:
+	  Properly resolve type references.
+
+2010-02-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Fix type
+	  arg count code.
+
+2010-01-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/NRefactoryResolverVisitor.cs: Add
+	  suport for an external type resolver. The first time an
+	  expression is evaluated in a context, the debugger tries to
+	  resolve the type references using the external resolver, and
+	  will use the resolved expression to do the evaluation.
+
+	* Mono.Debugging.Client/SourceLocation.cs: Add column field.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Added
+	  method for forcing the loading of a type.
+
+2010-01-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Generate
+	  NotSupported values when getting such exception.
+
+2010-01-20  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Makefile.am:
+	* mono.debugging.snk:
+	* Mono.Debugging.csproj: Sign and fix deps.
+
+2010-01-20  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Fix
+	  potential string parsing issue. Fixes bug #571232 -
+	  System.FormatException: Input string was not in a correct
+	  format.
+
+2009-12-18  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Workaround for
+	  possible deadlock.
+
+2009-12-16  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs: Report the
+	  correct error for unsupported expressions. Fixes bug
+	  #564452.
+
+2009-12-15  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs: Forgot assignment in
+	  update method.
+
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/LiteralValueReference.cs:
+	  LiteralExp has been replaced by EvaluationResult.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Improve
+	  formatting of arrays, enums and types.
+
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs: Fix
+	  formatting of boolean values. LiteralExp has been replaced
+	  by EvaluationResult.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Fix some
+	  evaluation issues.
+
+2009-12-11  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/LiteralValueReference.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Added a
+	  new EvaluationResult class to be used to provide expression
+	  evaluation values. This result can contain a value and a
+	  display value. The display value is shown in the value cell
+	  of the watch window, the original value is used when
+	  editing.
+
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: When
+	  setting a value, try converting it to the target type.
+
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs: Add
+	  support for character escapes.
+
+2009-12-09  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: When a
+	  RootHidden member is found, hide everything but that member.
+
+2009-12-09  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerStartInfo.cs: Added properties
+	  to support the external console option.
+
+2009-12-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Honor
+	  DebuggerBrowsableState in private and static member groups.
+
+2009-12-03  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/IObjectSource.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Created
+	  the IObjectSource interface, which can be used to keep track
+	  of the origin of an object. ValueReference objects now have
+	  a reference to the IObjectSource that generated them. This
+	  source can be used to update back struct instances.
+
+2009-12-02  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Evaluation/TimedEvaluator.cs: Name threads to
+	  make debugging easier.
+
+2009-12-02  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: If there's an
+	  exceptions when running, attaching, or finishing, exit the
+	  session, instead of just stopping it.
+
+2009-12-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: By default,
+	  don't group private members for user classes.
+
+2009-12-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/ObjectValueFlags.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/BaseTypeViewSource.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Added
+	  new evaluation options. Grouping non-public and static
+	  members is now optional. Added option for grouping members
+	  from base classes in a base group. When disabled, show the
+	  base class next to the member name when there are several
+	  members with the same name.
+
+2009-12-01  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Added
+	  several missing type and null checks.
+
+2009-11-30  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Prettify
+	  type names.
+
+2009-11-25  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: A frame should be
+	  marked external when file name IS empty.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Improve
+	  error handling.
+
+2009-11-24  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: Add property for
+	  flagging frame as external code.
+
+2009-11-20  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSessionOptions.cs: Add setting
+	  for user-code-only debugging.
+
+2009-11-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Fix calls
+	  to GetTypeDisplayData.
+
+2009-11-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/TimedEvaluator.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs:
+	  Properly dispose resources.
+
+2009-11-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Client/ObjectValueFlags.cs:
+	* Mono.Debugging.Evaluation/BaseBacktrace.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/TimedEvaluator.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs:
+	  Improved async evaluation. If an evaluation is in process,
+	  don't even try to create an evaluation context, just queue
+	  the request. Added more evaluation options. Added default
+	  implementations for some methods (in ObjectValueAdaptor) and
+	  classes (BaseBacktrace), factorized from the soft debugger.
+
+2009-11-18  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/Backtrace.cs:
+	* Mono.Debugging.Client/StackFrame.cs: Fix some serialization
+	  issues.
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Improve
+	  error message.
+
+2009-11-18  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/Backtrace.cs: Add support for
+	  refreshing object values.
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Backend/IBacktrace.cs:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Client/ObjectValueFlags.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Client/EvaluationOptions.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Backend/IObjectValueSource.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Client/DebuggerSessionOptions.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/AsyncOperationManager.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs: Add
+	  support for refreshing object values. 
+
+2009-11-17  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Client/DebuggerSessionOptions.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs:
+	* Mono.Debugging.Evaluation/AsyncOperationManager.cs:
+	* Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs: Add an
+	  Options argument to the methods that launch the debugger. By
+	  default, run debugger operations in a background thread, to
+	  avoid locking the main thread. Improve expression evaluation
+	  timeout handling. If an evaluation can't be aborted, notify
+	  the user and wait until done or stopped.
+
+2009-11-11  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/Backtrace.cs: Fix list
+	  ArgumentOutOfRangeException when soft debugger is stopped in
+	  unmanaged code. Not completely sure this is the right fix.
+
+2009-10-29  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.csproj: Flush.
+
+2009-10-18  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Fix Pocess/Process
+	  spelling. Don't lock in IsRunning or MD can deadlock.
+
+2009-10-05  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ThreadInfo.cs:
+	* Mono.Debugging.Client/ProcessInfo.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs: Use long for
+	  thread and process id.
+
+2009-10-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Don't show
+	  the static/non-public groups if they don't contain elements.
+	  Fixes bug #543782 - Debug tooltip always shows Static
+	  members group.
+
+2009-10-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs:
+	* Mono.Debugging.Evaluation/NamespaceValueReference.cs:
+	  Alphabetically sort members of types. Fixes bug #543780 -
+	  Debug tooltip shows members in random order.
+
+2009-10-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs: Allow setting the type
+	  name.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Added null
+	  check.
+
+2009-09-29  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation\ObjectValueAdaptor.cs: Add missing
+	  length check.
+
+2009-09-25  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Some minor
+	  fixes.
+
+2009-09-23  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/BreakpointStore.cs: Clear(): Properly
+	  duplicate breakpoint list.
+
+2009-09-23  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs: Added some debug code.
+
+	* Mono.Debugging.Evaluation/ICollectionAdaptor.cs:
+	  CreateElementValue is not used anymore.
+
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs: Make
+	  serializable some exceptions.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Added some
+	  preventive error checks.
+
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs: When
+	  generating an array item, use NameDisplayString when defined
+	  for the type. Fixed upperBound value for multidimensional
+	  arrays.
+
+2009-09-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Added
+	  missing null check.
+
+2009-09-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Add
+	  support for examining nested types.
+
+2009-09-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Improve error
+	  handling. Exceptions can now be intercept using a delegate.
+
+2009-09-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Try to
+	  resolve type names using the imported namespaces.
+
+2009-09-17  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/BreakEvent.cs:
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Client/BreakpointStore.cs: Added support for
+	  disabling changes in the breakpoint store. Some debuggers
+	  may not support changing breakpoints while the debugger is
+	  running.
+
+2009-09-17  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Don't crash if a
+	  breakpoint can't be removed.
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/DebuggerException.cs: Added exception
+	  to be used to report debugger errors to the user.
+
+2009-09-14  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Ignore '?'
+	  prefix. We don't use it, but VS does.
+
+2009-09-14  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/EvaluationContext.cs: Added flag
+	  for enabling/disabling execution of debugging target code
+	  while inspecting expressions.
+
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Fix cast
+	  expression evaluation.
+
+2009-08-28  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs: Allow
+	  calling a method of the class of the current
+	  debugging-scope. Fixes bug #525258.
+
+2009-07-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Evaluation/Backtrace.cs: Remove unused file.
+
+2009-07-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/Backtrace.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/ICollectionAdaptor.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NullValueReference.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/ArrayValueReference.cs:
+	* Mono.Debugging.Evaluation/LiteralValueReference.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs:
+	* Mono.Debugging.Evaluation/UserVariableReference.cs:
+	* Mono.Debugging.Evaluation/NamespaceValueReference.cs: Get
+	  rid of generic classes because they are causing a lot of
+	  trouble in mono.
+
+2009-06-23  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs: Workaround
+	  to a bug in mono 2.0. That mono version fails to compile an
+	  anonymous method in GetExpressionValuesAsync.
+
+2009-06-16  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation\TypeValueReference.cs: Only show
+	  static members as children of types.
+
+	* Mono.Debugging.Evaluation\NRefactoryEvaluator.cs: Don't
+	  crash if a method evaluation returns 'void'.
+
+	* Mono.Debugging.Evaluation\LiteralValueReference.cs: Properly
+	  support literal expressions.
+
+2009-06-15  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj: Added missing reference.
+
+2009-06-15  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Evaluation\NRefactoryEvaluator.cs: Small
+	  optimization.
+
+2009-06-12  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Evaluation:
+	* Mono.Debugging.Evaluation/Backtrace.cs:
+	* Mono.Debugging.Evaluation/RawViewSource.cs:
+	* Mono.Debugging.Evaluation/ValueReference.cs:
+	* Mono.Debugging.Evaluation/TimedEvaluator.cs:
+	* Mono.Debugging.Evaluation/TimeOutException.cs:
+	* Mono.Debugging.Evaluation/ArrayElementGroup.cs:
+	* Mono.Debugging.Evaluation/EvaluationContext.cs:
+	* Mono.Debugging.Evaluation/RemoteFrameObject.cs:
+	* Mono.Debugging.Evaluation/TypeValueReference.cs:
+	* Mono.Debugging.Evaluation/NullValueReference.cs:
+	* Mono.Debugging.Evaluation/ICollectionAdaptor.cs:
+	* Mono.Debugging.Evaluation/ObjectValueAdaptor.cs:
+	* Mono.Debugging.Evaluation/NRefactoryEvaluator.cs:
+	* Mono.Debugging.Evaluation/ArrayValueReference.cs:
+	* Mono.Debugging.Evaluation/ExpressionEvaluator.cs:
+	* Mono.Debugging.Evaluation/LiteralValueReference.cs:
+	* Mono.Debugging.Evaluation/AsyncOperationManager.cs:
+	* Mono.Debugging.Evaluation/FilteredMembersSource.cs:
+	* Mono.Debugging.Evaluation/UserVariableReference.cs:
+	* Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs:
+	* Mono.Debugging.Evaluation/NamespaceValueReference.cs: Added
+	  an expression evaluator factorized from the Mdb and Win32
+	  debugger addins.
+
+2009-06-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Backend/IDebuggerSessionFrontend.cs: Added
+	  NotifySourceFile(Un)Loaded to IDebuggerSessionFrontend.
+
+2009-05-25  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client\BreakpointStore.cs: Use case
+	  insensitive compare for files on windows.
+
+	* Mono.Debugging.Client\DebuggerSession.cs: Fix crash when
+	  updating breakpoints.
+
+2009-05-13  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client\DebuggerSession.cs: Protect access to
+	  the breakpoints collection. Added method for notifying
+	  loading/unloading of files.
+
+2009-04-27  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.csproj:
+	* Mono.Debugging.Client/IDebuggerEngine.cs: Moved
+	  IDebuggerEngine to MD.Debugger.
+
+2009-03-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/IDebuggerEngine.cs: Removed unused
+	  CanDebugPlatform and rename CanDebugFile to CanDebugCommand.
+
+2009-02-06  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.mdp:
+	* Mono.Debugging.csproj: Migrated to MSBuild file format.
+
+2009-01-26  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.mdp: Flush project format changes.
+
+2009-01-14  Michael Hutchinson  <mhutchinson at novell.com>
+
+	* Mono.Debugging.Client/StackFrame.cs: Remove Console.WriteLine noise.
+
+2008-12-19  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Makefile.am:
+	* Mono.Debugging.mdp:
+	* Mono.Debugging.Client/StackFrame.cs:
+	* Mono.Debugging.Backend/IBacktrace.cs:
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Backend/UpdateCallback.cs:
+	* Mono.Debugging.Client/ObjectValueFlags.cs:
+	* Mono.Debugging.Backend/IObjectValueUpdater.cs:
+	* Mono.Debugging.Backend/IObjectValueUpdateCallback.cs: Added support
+	for asynchronus evaluation of expressions, with support for timeouts.
+
+2008-12-04  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/DebuggerSession.cs:
+	* Mono.Debugging.Client/IDebuggerEngine.cs:
+	* Mono.Debugging.Client/DebuggerFeatures.cs: Improved support for
+	checking debugger features.
+
+2008-12-02  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ObjectValue.cs:
+	* Mono.Debugging.Client/ObjectValueFlags.cs: Added new kind of value:
+	not supported.
+
+	* Makefile.am: Fix to better support parallel building.
+
+2008-10-22  Lluis Sanchez Gual  <lluis at novell.com>
+
+	* Mono.Debugging.Client/ThreadInfo.cs: Added null check.
+
+2008-09-12  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.mdp: Updated.
+
+2008-09-03  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/DebuggerFeatures.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/TargetEventArgs.cs, Mono.Debugging.mdp,
+	  Makefile.am: When firing the TargetEvent for an Exception, provide
+	  the exception object. Added property for getting the debugger
+	  capabilities.
+
+2008-08-22  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.addin.xml, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/DebuggerExtensionNode.cs, Makefile.am:
+	  Remove Mono.Addins dependency.
+
+2008-08-07  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakpointStore.cs: Fire the change event when
+	  a breakpoint is modified.
+	* Mono.Debugging.Client/DebuggerSession.cs: Made GetBreakpointHandle
+	  protected so it can be used by add-ins.
+
+2008-08-06  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakpointStore.cs,
+	  Mono.Debugging.Client/BreakEvent.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs, Mono.Debugging.mdp: Add
+	  support for live updating of breakpoint's hit count.
+
+2008-08-05  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ThreadInfo.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs: Add location field to
+	  ThreadInfo. Reset the cached process list when receiving a target
+	  event.
+
+2008-07-25  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/StackFrame.cs,
+	  Mono.Debugging.Backend/IBacktrace.cs: Added api for getting all
+	  locals of a stack frame.
+
+2008-07-22  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakEvent.cs,
+	  Mono.Debugging.Client/Catchpoint.cs,
+	  Mono.Debugging.Client/Breakpoint.cs: Added copying methods. Added
+	  property which allows stopping on a breakpoint after the given hit
+	  count.
+
+2008-07-21  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ObjectValue.cs: Added some missing null checks.
+
+2008-07-16  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakpointStore.cs,
+	  Mono.Debugging.Client/BreakEvent.cs,
+	  Mono.Debugging.Client/Catchpoint.cs,
+	  Mono.Debugging.Client/Breakpoint.cs, Mono.Debugging.mdp,
+	  Makefile.am: Add serialization support to BreakpointStore.
+
+2008-07-16  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/CatchpointEventArgs.cs,
+	  Mono.Debugging.Client/BreakpointStore.cs,
+	  Mono.Debugging.Client/BreakEvent.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/TargetEventType.cs,
+	  Mono.Debugging.Client/Catchpoint.cs,
+	  Mono.Debugging.Client/Breakpoint.cs,
+	  Mono.Debugging.Client/BreakEventArgs.cs, Mono.Debugging.mdp,
+	  Makefile.am: Implemented support for catchpoints.
+
+2008-07-11  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakpointStore.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/Breakpoint.cs,
+	  Mono.Debugging.Backend/IDebuggerSessionFrontend.cs: Added api to
+	  support custom breakpoint hit actions.
+
+2008-07-09  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ThreadInfo.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs: Provide the process id
+	  when setting the active thread.
+
+2008-07-09  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ObjectValueFlags.cs: Added Type and Namespace.
+	* Mono.Debugging.Client/ObjectValue.cs: Properly set the name when
+	  creating an error object.
+
+2008-07-09  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/StackFrame.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/CompletionData.cs, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/IBacktrace.cs, Makefile.am: Added support
+	  for code completion.
+
+2008-07-07  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ObjectValueFlags.cs,
+	  Mono.Debugging.Client/StackFrame.cs,
+	  Mono.Debugging.Client/ObjectValue.cs,
+	  Mono.Debugging.Client/ObjectValueKind.cs, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/IBacktrace.cs, Makefile.am: Added flags enum
+	  to ObjectValue which give information about the origin of the
+	  value.
+
+2008-07-02  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/ObjectPath.cs: Implemented ToString.
+	* Mono.Debugging.Client/AssemblyLine.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs: Added support for
+	  disassembling files.
+	* Mono.Debugging.Client/ObjectValue.cs,
+	  Mono.Debugging.Client/ObjectValueKind.cs,
+	  Mono.Debugging.Backend/IObjectValueSource.cs: Implemented support
+	  for changing the value of an ObjectValue. Improved error reporting.
+
+2008-07-01  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/BreakpointStore.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/Breakpoint.cs: Add support for "invalid"
+	  breakpoints (breakpoints placed in locations where there is no
+	  source code).
+
+2008-06-26  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/Backtrace.cs: Get only the first stack frame at
+	  the begining.
+	* Mono.Debugging.Client/ThreadInfo.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs: Allow changing the active
+	  thread.
+
+2008-06-20  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/DebuggerSession.cs: Improved thread safety.
+	  Implemented Detach.
+
+2008-06-20  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/Backtrace.cs,
+	  Mono.Debugging.Client/StackFrame.cs,
+	  Mono.Debugging.Client/IDebuggerEngine.cs,
+	  Mono.Debugging.Client/ObjectPath.cs,
+	  Mono.Debugging.Client/ThreadInfo.cs,
+	  Mono.Debugging.Client/AssemblyLine.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/ProcessInfo.cs,
+	  Mono.Debugging.Client/ObjectValue.cs,
+	  Mono.Debugging.Client/TargetEventArgs.cs,
+	  Mono.Debugging.Client/ObjectValueKind.cs,
+	  Mono.Debugging.Client/DebuggerEngine.cs, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/DissassemblyBuffer.cs,
+	  Mono.Debugging.Backend/IDebuggerSessionFrontend.cs,
+	  Mono.Debugging.Backend/IBacktrace.cs,
+	  Mono.Debugging.Backend/IDebuggerSessionFactory.cs, Makefile.am:
+	  Added support for attaching processes and disassembling. Improved
+	  API. 
+
+2008-06-16  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/Backtrace.cs: Get 1 initial frame when creating
+	  the backtrace.
+	* Mono.Debugging.Client/DebuggerSession.cs: Some methods don't need to
+	  be virtual.
+	* Mono.Debugging.Client/StackFrame.cs: Improved frame description.
+
+2008-06-16  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.mdp: Fixed Mono.Addins reference.
+
+2008-05-27  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/DebuggerSession.cs, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/IDebuggerSessionBackend.cs, Makefile.am:
+	  Removed IDebuggerSessionBackend interface. Methods must now be
+	  implemented using DebuggerSession overridables.
+
+2008-05-15  Lluis Sanchez Gual <lluis at novell.com> 
+
+	* Mono.Debugging.Client/Backtrace.cs,
+	  Mono.Debugging.Client/StackFrame.cs,
+	  Mono.Debugging.Client/ObjectPath.cs,
+	  Mono.Debugging.Client/DebuggerSession.cs,
+	  Mono.Debugging.Client/ObjectValue.cs,
+	  Mono.Debugging.Client/ObjectValueKind.cs, Mono.Debugging.mdp,
+	  Mono.Debugging.Backend/IObjectValueSource.cs,
+	  Mono.Debugging.Backend/IBacktrace.cs, Makefile.am: Added api for
+	  querying variable and field values. Some improvements in
+	  ObjectValue. Added new ObjectPath class.
+
+2008-05-06  Lluis Sanchez  <lluis at novell.com>
+
+	* Imported library
+
diff --git a/Mono.Debugging/Makefile.am b/Mono.Debugging/Makefile.am
new file mode 100644
index 0000000..c9cc874
--- /dev/null
+++ b/Mono.Debugging/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/xbuild.include
diff --git a/Mono.Debugging/Mono.Debugging.Backend/DissassemblyBuffer.cs b/Mono.Debugging/Mono.Debugging.Backend/DissassemblyBuffer.cs
new file mode 100644
index 0000000..13801ec
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/DissassemblyBuffer.cs
@@ -0,0 +1,154 @@
+// DissassemblyBuffer.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public abstract class DissassemblyBuffer
+	{
+		List<AssemblyLine> lines = new List<AssemblyLine> ();
+		int baseIndex = 0;
+		long baseAddress;
+		
+		const int AddrPerLine = 4;
+		const int ExtraDownLines = 5;
+		const int ExtraUpLines = 20;
+		
+		public DissassemblyBuffer (long baseAddress)
+		{
+			this.baseAddress = baseAddress;
+		}
+		
+		public AssemblyLine[] GetLines (int firstIndex, int lastIndex)
+		{
+			//Console.WriteLine ("pp GET LINES: " + firstIndex + " " + lastIndex + " " + baseIndex);
+			
+			if (lastIndex >= 0)
+				FillDown (lastIndex);
+			if (firstIndex < 0)
+				FillUp (firstIndex);
+			
+			AssemblyLine[] array = new AssemblyLine [lastIndex - firstIndex + 1];
+			lines.CopyTo (baseIndex + firstIndex, array, 0, lastIndex - firstIndex + 1);
+			return array;
+		}
+		
+		public void FillUp (int targetLine)
+		{
+			if (baseIndex + targetLine >= 0)
+				return;
+			
+			// Lines we are missing
+			int linesReq = -(baseIndex + targetLine);
+			
+			//Console.WriteLine ("pp FILLUP: " + linesReq);
+			
+			// Last known valid address
+			long lastAddr = lines.Count > 0 ? lines [0].Address : baseAddress;
+			
+			// Addresses we are going to query to get the required lines
+			long addr = lastAddr - (linesReq + ExtraUpLines) * AddrPerLine; // 4 is just a guess
+			
+			int lastCount = 0;
+			bool limitFound = false;
+			AssemblyLine[] alines;
+			do {
+				alines = GetLines (addr, lastAddr);
+				if (alines.Length <= lastCount) {
+					limitFound = true;
+					break;
+				}
+				addr -= (linesReq + ExtraUpLines - alines.Length) * AddrPerLine;
+				lastCount = alines.Length;
+			}
+			while (alines.Length < linesReq + ExtraUpLines);
+			
+			int max = limitFound ? alines.Length : alines.Length - ExtraUpLines;
+			if (max < 0) max = 0;
+			
+			// Fill the lines
+			for (int n=0; n < max; n++)
+				lines.Insert (n, alines [n + (alines.Length - max)]);
+
+			long firstAddr = lines [0].Address;
+			for (int n=0; n < (linesReq - max); n++) {
+				AssemblyLine line = new AssemblyLine (--firstAddr, "");
+				lines.Insert (0, line);
+				max++;
+			}
+			baseIndex += max;
+		}
+		
+		public void FillDown (int targetLine)
+		{
+			if (baseIndex + targetLine < lines.Count)
+				return;
+			
+			// Lines we are missing
+			int linesReq = (baseIndex + targetLine) - lines.Count + 1;
+			
+			//Console.WriteLine ("pp FILLDOWN: " + linesReq);
+			
+			// Last known valid address
+			long lastAddr = lines.Count > 0 ? lines [lines.Count - 1].Address : baseAddress;
+			
+			// Addresses we are going to query to get the required lines
+			long addr = lastAddr + (linesReq + ExtraDownLines) * AddrPerLine; // 4 is just a guess
+			
+			int lastCount = 0;
+			bool limitFound = false;
+			AssemblyLine[] alines;
+			do {
+				alines = GetLines (lastAddr, addr);
+				if (alines.Length <= lastCount) {
+					limitFound = true;
+					break;
+				}
+				addr += (linesReq + ExtraDownLines - alines.Length) * AddrPerLine;
+				lastCount = alines.Length;
+			}
+			while (alines.Length < linesReq + ExtraDownLines);
+			
+			int max = limitFound ? alines.Length : alines.Length - ExtraDownLines;
+			
+			// Fill the lines
+			for (int n=0; n < max; n++)
+				lines.Add (alines [n]);
+
+			lastAddr = lines [lines.Count - 1].Address;
+			for (int n=0; n < (linesReq - max); n++) {
+				AssemblyLine line = new AssemblyLine (++lastAddr, "");
+				lines.Add (line);
+			}
+		}
+		
+		public abstract AssemblyLine[] GetLines (long startAddr, long endAddr);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/EvaluationResult.cs b/Mono.Debugging/Mono.Debugging.Backend/EvaluationResult.cs
new file mode 100644
index 0000000..4ec7746
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/EvaluationResult.cs
@@ -0,0 +1,55 @@
+//
+// EvaluationResult.cs
+//
+// Author:
+//       Lluis Sanchez <lluis at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+
+	[Serializable]
+	public class EvaluationResult
+	{
+		public EvaluationResult (string value)
+		{
+			Value = value;
+		}
+		
+		public EvaluationResult (string value, string displayValue)
+		{
+			Value = value;
+			DisplayValue = displayValue;
+		}
+		
+		public string Value { get; private set; }
+		public string DisplayValue { get; private set; }
+		
+		public override string ToString ()
+		{
+			return Value;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IBacktrace.cs b/Mono.Debugging/Mono.Debugging.Backend/IBacktrace.cs
new file mode 100644
index 0000000..7ace999
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IBacktrace.cs
@@ -0,0 +1,20 @@
+
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IBacktrace: IDebuggerBackendObject
+	{
+		int FrameCount { get; }
+		StackFrame[] GetStackFrames (int firstIndex, int lastIndex);
+		ObjectValue[] GetLocalVariables (int frameIndex, EvaluationOptions options);
+		ObjectValue[] GetParameters (int frameIndex, EvaluationOptions options);
+		ObjectValue GetThisReference (int frameIndex, EvaluationOptions options);
+		ExceptionInfo GetException (int frameIndex, EvaluationOptions options);
+		ObjectValue[] GetAllLocals (int frameIndex, EvaluationOptions options);
+		ObjectValue[] GetExpressionValues (int frameIndex, string[] expressions, EvaluationOptions options);
+		CompletionData GetExpressionCompletionData (int frameIndex, string exp);
+		AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count);
+		ValidationResult ValidateExpression (int frameIndex, string expression, EvaluationOptions options);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IDebuggerBackendObject.cs b/Mono.Debugging/Mono.Debugging.Backend/IDebuggerBackendObject.cs
new file mode 100644
index 0000000..2fcfc84
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IDebuggerBackendObject.cs
@@ -0,0 +1,34 @@
+//
+// IDebuggerBackendObject.cs
+//
+// Author:
+//       Lluis Sanchez <lluis at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 Mono.Debugging.Backend
+{
+	public interface IDebuggerBackendObject
+	{
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IDebuggerSessionFrontend.cs b/Mono.Debugging/Mono.Debugging.Backend/IDebuggerSessionFrontend.cs
new file mode 100644
index 0000000..b340b35
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IDebuggerSessionFrontend.cs
@@ -0,0 +1,44 @@
+// IDebuggerSession.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IDebuggerSessionFrontend
+	{
+		void NotifyTargetEvent (TargetEventArgs args);
+		void NotifyTargetOutput (bool isStderr, string line);
+		void NotifyDebuggerOutput (bool isStderr, string line);
+		void BindSourceFileBreakpoints (string fullFilePath);
+		void UnbindSourceFileBreakpoints (string fullFilePath);
+		
+		// To be called when the process is ready to run.
+		void NotifyStarted ();
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IObjectValueSource.cs b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueSource.cs
new file mode 100644
index 0000000..c9018e5
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueSource.cs
@@ -0,0 +1,43 @@
+// IObjectValueSource.cs
+//
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IObjectValueSource: IDebuggerBackendObject
+	{
+		ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options);
+		EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options);
+		ObjectValue GetValue (ObjectPath path, EvaluationOptions options);
+		
+		object GetRawValue (ObjectPath path, EvaluationOptions options);
+		void SetRawValue (ObjectPath path, object value, EvaluationOptions options);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdateCallback.cs b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdateCallback.cs
new file mode 100644
index 0000000..0b480e6
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdateCallback.cs
@@ -0,0 +1,37 @@
+// IObjectValueUpdateCallback.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	internal interface IObjectValueUpdateCallback
+	{
+		void UpdateValue (ObjectValue newValue);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdater.cs b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdater.cs
new file mode 100644
index 0000000..5bc67dd
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IObjectValueUpdater.cs
@@ -0,0 +1,37 @@
+// IObjectValueUpdater.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IObjectValueUpdater: IDebuggerBackendObject
+	{
+		void RegisterUpdateCallbacks (UpdateCallback[] callbacks);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IRawValue.cs b/Mono.Debugging/Mono.Debugging.Backend/IRawValue.cs
new file mode 100644
index 0000000..7391e97
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IRawValue.cs
@@ -0,0 +1,40 @@
+//
+// IRawValue.cs
+//
+// Author:
+//       Lluis Sanchez <lluis at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	
+	public interface IRawValue: IDebuggerBackendObject
+	{
+		object CallMethod (string name, object[] parameters, EvaluationOptions options);
+		object GetMemberValue (string name, EvaluationOptions options);
+		void SetMemberValue (string name, object value, EvaluationOptions options);
+	}
+	
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IRawValueArray.cs b/Mono.Debugging/Mono.Debugging.Backend/IRawValueArray.cs
new file mode 100644
index 0000000..d963e74
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IRawValueArray.cs
@@ -0,0 +1,40 @@
+//
+// IRawValueArray.cs
+//
+// Author:
+//       Lluis Sanchez <lluis at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IRawValueArray: IDebuggerBackendObject
+	{
+		object GetValue (int[] index);
+		Array GetValues (int[] index, int count);
+		void SetValue (int[] index, object value);
+		int[] Dimensions { get; }
+		Array ToArray ();
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/IRawValueString.cs b/Mono.Debugging/Mono.Debugging.Backend/IRawValueString.cs
new file mode 100644
index 0000000..f1b77fe
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/IRawValueString.cs
@@ -0,0 +1,39 @@
+//
+// IRawValueString.cs
+//
+// Author:
+//       Lluis Sanchez <lluis at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	public interface IRawValueString: IDebuggerBackendObject
+	{
+		string Substring (int index, int length);
+		string Value { get; }
+		int Length { get; }
+	}
+	
+}
diff --git a/Mono.Debugging/Mono.Debugging.Backend/UpdateCallback.cs b/Mono.Debugging/Mono.Debugging.Backend/UpdateCallback.cs
new file mode 100644
index 0000000..bdadddf
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Backend/UpdateCallback.cs
@@ -0,0 +1,68 @@
+// UpdateCallback.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Backend
+{
+	[Serializable]
+	public class UpdateCallback
+	{
+		ObjectPath path;
+		IObjectValueUpdateCallback callback;
+
+		internal UpdateCallback ()
+		{
+		}
+
+		internal UpdateCallback (IObjectValueUpdateCallback callback, ObjectPath path)
+		{
+			this.callback = callback;
+			this.path = path;
+		}
+
+		public ObjectPath Path {
+			get { return path; }
+		}
+
+		internal IObjectValueUpdateCallback Callback {
+			get {
+				return callback;
+			}
+		}
+
+		public void UpdateValue (ObjectValue newValue)
+		{
+			try {
+				callback.UpdateValue (newValue);
+			} catch {
+				// Ignore
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/AssemblyLine.cs b/Mono.Debugging/Mono.Debugging.Client/AssemblyLine.cs
new file mode 100644
index 0000000..830dc0b
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/AssemblyLine.cs
@@ -0,0 +1,90 @@
+// AssemblyLine.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	[Serializable]
+	public class AssemblyLine
+	{
+		long address;
+		string code;
+		int sourceLine;
+		string addressSpace;
+		
+		public string Code {
+			get {
+				return code;
+			}
+		}
+		
+		public long Address {
+			get {
+				return address;
+			}
+		}
+		
+		public string AddressSpace {
+			get {
+				return addressSpace;
+			}
+		}
+		
+		public int SourceLine {
+			get {
+				return sourceLine;
+			}
+		}
+		
+		public bool IsOutOfRange {
+			get { return address == -1 && code == null; }
+		}
+		
+		public static readonly AssemblyLine OutOfRange = new AssemblyLine (-1, null, null);
+		
+		public AssemblyLine (long address, string code): this (address, "", code, -1)
+		{
+		}
+		
+		public AssemblyLine (long address, string code, int sourceLine): this (address, "", code, sourceLine)
+		{
+		}
+		
+		public AssemblyLine (long address, string addressSpace, string code): this (address, addressSpace, code, -1)
+		{
+		}
+		
+		public AssemblyLine (long address, string addressSpace, string code, int sourceLine)
+		{
+			this.address = address;
+			this.code = code;
+			this.sourceLine = sourceLine;
+			this.addressSpace = addressSpace;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/Backtrace.cs b/Mono.Debugging/Mono.Debugging.Client/Backtrace.cs
new file mode 100644
index 0000000..72ebf82
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/Backtrace.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class Backtrace
+	{
+		IBacktrace serverBacktrace;
+		int count;
+		
+		[NonSerialized]
+		DebuggerSession session;
+
+		List<StackFrame> frames;
+		
+		public Backtrace (IBacktrace serverBacktrace)
+		{
+			this.serverBacktrace = serverBacktrace;
+			
+			count = serverBacktrace.FrameCount;
+
+			// Get some initial frames
+			if (count > 0)
+				GetFrame (0);
+		}
+		
+		internal void Attach (DebuggerSession session)
+		{
+			this.session = session;
+			serverBacktrace = session.WrapDebuggerObject (serverBacktrace);
+			if (frames != null) {
+				foreach (StackFrame f in frames) {
+					f.Attach (session);
+					f.SourceBacktrace = serverBacktrace;
+				}
+			}
+		}
+
+		public int FrameCount
+		{
+			get { return count; }
+		}
+
+		public StackFrame GetFrame (int n)
+		{
+			if (frames == null)
+				frames = new List<StackFrame>();
+
+			if (n >= frames.Count) {
+				StackFrame[] newSet = serverBacktrace.GetStackFrames(frames.Count, n + 20);
+				foreach (StackFrame sf in newSet) {
+					sf.SourceBacktrace = serverBacktrace;
+					sf.Index = frames.Count;
+					frames.Add (sf);
+					sf.Attach (session);
+				}
+			}
+			
+			if (frames.Count > 0)
+				return frames[System.Math.Min (System.Math.Max (0, n), frames.Count - 1)];
+
+			return null;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakEvent.cs b/Mono.Debugging/Mono.Debugging.Client/BreakEvent.cs
new file mode 100644
index 0000000..53112bb
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakEvent.cs
@@ -0,0 +1,338 @@
+// BreakEvent.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Xml;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class BreakEvent
+	{
+		[NonSerialized] BreakpointStore store;
+		[NonSerialized] bool enabled = true;
+		
+		HitAction hitAction = HitAction.Break;
+		string customActionId;
+		string traceExpression;
+		int hitCount;
+		string lastTraceValue;
+		
+		public BreakEvent ()
+		{
+		}
+		
+		internal BreakEvent (XmlElement elem)
+		{
+			string s = elem.GetAttribute ("enabled");
+			if (s.Length > 0)
+				bool.TryParse (s, out enabled);
+			s = elem.GetAttribute ("hitAction");
+			if (s.Length > 0)
+				Enum.TryParse<HitAction> (s, out hitAction);
+			s = elem.GetAttribute ("customActionId");
+			if (s.Length > 0)
+				customActionId = s;
+			s = elem.GetAttribute ("traceExpression");
+			if (s.Length > 0)
+				traceExpression = s;
+			s = elem.GetAttribute ("hitCountMode");
+			HitCountMode mode;
+			if (s.Length > 0 && Enum.TryParse<HitCountMode> (s, out mode))
+				HitCountMode = mode;
+			s = elem.GetAttribute ("hitCount");
+			if (s.Length > 0)
+				int.TryParse (s, out hitCount);
+
+			// this is to facilitate backward compatibility
+			if (hitCount > 0 && HitCountMode == HitCountMode.None)
+				HitCountMode = HitCountMode.GreaterThan;
+		}
+		
+		internal virtual XmlElement ToXml (XmlDocument doc)
+		{
+			XmlElement elem = doc.CreateElement (GetType().Name);
+			if (!enabled)
+				elem.SetAttribute ("enabled", "false");
+			if ((hitAction & HitAction.Break) == HitAction.None)
+				elem.SetAttribute ("hitAction", hitAction.ToString ());
+			if (!string.IsNullOrEmpty (customActionId))
+				elem.SetAttribute ("customActionId", customActionId);
+			if (!string.IsNullOrEmpty (traceExpression))
+				elem.SetAttribute ("traceExpression", traceExpression);
+			if (HitCountMode != HitCountMode.None)
+				elem.SetAttribute ("hitCountMode", HitCountMode.ToString ());
+			if (hitCount > 0)
+				elem.SetAttribute ("hitCount", hitCount.ToString ());
+			return elem;
+		}
+		
+		internal static BreakEvent FromXml (XmlElement elem)
+		{
+			if (elem.Name == "FunctionBreakpoint")
+				return new FunctionBreakpoint (elem);
+			if (elem.Name == "Breakpoint")
+				return new Breakpoint (elem);
+			if (elem.Name == "Catchpoint")
+				return new Catchpoint (elem);
+
+			return null;
+		}
+		
+		/// <summary>
+		/// Gets or sets a value indicating whether this <see cref="Mono.Debugging.Client.BreakEvent"/> is enabled.
+		/// </summary>
+		/// <value>
+		/// <c>true</c> if enabled; otherwise, <c>false</c>.
+		/// </value>
+		/// <remarks>
+		/// Changes in this property are automatically applied. There is no need to call CommitChanges().
+		/// </remarks>
+		public bool Enabled {
+			get {
+				return enabled;
+			}
+			set {
+				if (store != null && store.IsReadOnly)
+					return;
+				enabled = value;
+				if (store != null)
+					store.EnableBreakEvent (this, value);
+			}
+		}
+
+		/// <summary>
+		/// Gets the status of the break event
+		/// </summary>
+		/// <returns>
+		/// The status of the break event for the given debug session
+		/// </returns>
+		/// <param name='session'>
+		/// Session for which to get the status of the break event
+		/// </param>
+		public BreakEventStatus GetStatus (DebuggerSession session)
+		{
+			if (store == null || session == null)
+				return BreakEventStatus.Disconnected;
+			return session.GetBreakEventStatus (this);
+		}
+		
+		/// <summary>
+		/// Gets a message describing the status of the break event
+		/// </summary>
+		/// <returns>
+		/// The status message of the break event for the given debug session
+		/// </returns>
+		/// <param name='session'>
+		/// Session for which to get the status message of the break event
+		/// </param>
+		public string GetStatusMessage (DebuggerSession session)
+		{
+			if (store == null || session == null)
+				return string.Empty;
+			return session.GetBreakEventStatusMessage (this);
+		}
+		
+		/// <summary>
+		/// Gets or sets the expression to be traced when the breakpoint is hit
+		/// </summary>
+		/// <remarks>
+		/// If this break event is hit and the HitAction is TraceExpression, the debugger
+		/// will evaluate and print the value of this property.
+		/// The CommitChanges() method has to be called for changes in this
+		/// property to take effect.
+		/// </remarks>
+		public string TraceExpression {
+			get {
+				return traceExpression;
+			}
+			set {
+				traceExpression = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets the last value traced.
+		/// </summary>
+		/// <remarks>
+		/// This property returns the last evaluation of TraceExpression.
+		/// </remarks>
+		public string LastTraceValue {
+			get {
+				return lastTraceValue;
+			}
+			internal set {
+				lastTraceValue = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets or sets the action to be performed when the breakpoint is hit
+		/// </summary>
+		/// <remarks>
+		/// If the value is Break, the debugger will pause the execution.
+		/// If the value is PrintExpression, the debugger will evaluate and
+		/// print the value of the TraceExpression property.
+		/// If the value is CustomAction, the debugger will execute the
+		/// CustomBreakEventHitHandler callback specified in DebuggerSession,
+		/// and will provide the value of CustomActionId as argument.
+		/// The CommitChanges() method has to be called for changes in this
+		/// property to take effect.
+		/// </remarks>
+		public HitAction HitAction {
+			get {
+				return hitAction;
+			}
+			set {
+				hitAction = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets or sets the hit count mode.
+		/// </summary>
+		/// <remarks>
+		/// When the break event is hit, the HitCountMode is used to compare the CurrentHitCount
+		/// with the TargetHitCount to determine if the break event should trigger.
+		/// </remarks>
+		public HitCountMode HitCountMode {
+			get; set;
+		}
+
+		/// <summary>
+		/// Gets or sets the target hit count.
+		/// </summary>
+		/// <remarks>
+		/// When the break event is hit, if the value of HitCountMode is not None, then
+		/// the value of CurrentHitCount will be incremented. Execution will immediately
+		/// resume if it is determined that the CurrentHitCount vs TargetHitCount
+		/// comparison does not meet the requirements of HitCountMode.
+		/// 
+		/// The CommitChanges() method has to be called for changes in this property
+		/// to take effect.
+		/// </remarks>
+		/// 
+		/// FIXME: rename this to TargetHitCount
+		public int HitCount {
+			get {
+				return hitCount;
+			}
+			set {
+				hitCount = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets or sets the current hit count.
+		/// </summary>
+		/// <remarks>
+		/// When the break event is hit, the HitCountMode is used to compare the CurrentHitCount
+		/// with the TargetHitCount to determine if the break event should trigger.
+		/// </remarks>
+		public int CurrentHitCount {
+			get; set;
+		}
+		
+		/// <summary>
+		/// Gets or sets the custom action identifier.
+		/// </summary>
+		/// <remarks>
+		/// If this break event is hit and the value of HitAction is CustomAction,
+		/// the debugger will execute the CustomBreakEventHitHandler callback
+		/// specified in DebuggerSession, and will provide the value of this property
+		/// as argument.
+		/// The CommitChanges() method has to be called for changes in this
+		/// property to take effect.
+		/// </remarks>
+		public string CustomActionId {
+			get {
+				return customActionId;
+			}
+			set {
+				customActionId = value;
+			}
+		}
+
+		internal BreakpointStore Store {
+			get {
+				return store;
+			}
+			set {
+				store = value;
+			}
+		}
+		
+		/// <summary>
+		/// Commits changes done in the break event properties
+		/// </summary>
+		/// <remarks>
+		/// This method must be called after doing changes in the break event properties.
+		/// </remarks>
+		public void CommitChanges ()
+		{
+			if (store != null)
+				store.NotifyBreakEventChanged (this);
+		}
+		
+		internal void NotifyUpdate ()
+		{
+			if (store != null)
+				store.NotifyBreakEventUpdated (this);
+		}
+
+		public virtual bool Reset ()
+		{
+			bool changed = CurrentHitCount != 0;
+
+			CurrentHitCount = 0;
+
+			return changed;
+		}
+		
+		/// <summary>
+		/// Clone this instance.
+		/// </summary>
+		public BreakEvent Clone ()
+		{
+			return (BreakEvent) MemberwiseClone ();
+		}
+		
+		/// <summary>
+		/// Makes a copy of this instance
+		/// </summary>
+		/// <param name='ev'>
+		/// A break event from which to copy the data.
+		/// </param>
+		public virtual void CopyFrom (BreakEvent ev)
+		{
+			hitAction = ev.hitAction;
+			customActionId = ev.customActionId;
+			traceExpression = ev.traceExpression;
+			hitCount = ev.hitCount;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/BreakEventArgs.cs
new file mode 100644
index 0000000..63c8c15
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakEventArgs.cs
@@ -0,0 +1,45 @@
+// BreakEventArgs.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	public class BreakEventArgs: EventArgs
+	{
+		BreakEvent be;
+		
+		public BreakEventArgs (BreakEvent be)
+		{
+			this.be = be;
+		}
+		
+		public BreakEvent BreakEvent {
+			get { return be; }
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakEventInfo.cs b/Mono.Debugging/Mono.Debugging.Client/BreakEventInfo.cs
new file mode 100644
index 0000000..9d29f92
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakEventInfo.cs
@@ -0,0 +1,164 @@
+// 
+// BreakEventInfo.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2011 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 Mono.Debugging.Client
+{
+	/// <summary>
+	/// This class can be used to manage and get information about a breakpoint
+	/// at debug-time. It is intended to be used by DebuggerSession subclasses.
+	/// </summary>
+	public class BreakEventInfo
+	{
+		DebuggerSession session;
+		int adjustedColumn = -1;
+		int adjustedLine = -1;
+		
+		/// <summary>
+		/// Gets or sets the implementation specific handle of the breakpoint
+		/// </summary>
+		public object Handle { get; set; }
+		
+		/// <summary>
+		/// Break event that this instance represents
+		/// </summary>
+		public BreakEvent BreakEvent { get; internal set; }
+
+		/// <summary>
+		/// Gets the status of the break event
+		/// </summary>
+		public BreakEventStatus Status { get; private set; }
+
+		/// <summary>
+		/// Gets a description of the status
+		/// </summary>
+		public string StatusMessage { get; private set; }
+
+		internal void AttachSession (DebuggerSession s, BreakEvent ev)
+		{
+			session = s;
+			BreakEvent = ev;
+			session.NotifyBreakEventStatusChanged (BreakEvent);
+			if (adjustedLine != -1 || adjustedColumn != -1)
+				session.AdjustBreakpointLocation ((Breakpoint)BreakEvent, adjustedLine, adjustedColumn);
+		}
+
+		/// <summary>
+		/// Adjusts the location of a breakpoint
+		/// </summary>
+		/// <param name='newLine'>
+		/// New line.
+		/// </param>
+		/// <remarks>
+		/// This method can be used to temporarily change source code line of the breakpoint.
+		/// This is useful, for example, when two adjacent lines are mapped to a single
+		/// native offset. If the breakpoint is set to the first of those lines, the debugger
+		/// might end stopping in the second line, because it has the same native offset.
+		/// To avoid this confusion situation, the debugger implementation may decide to
+		/// adjust the position of the breakpoint, and move it to the second line.
+		/// This line adjustment has effect only during the debug session, and is automatically
+		/// reset when it terminates.
+		/// </remarks>
+		public void AdjustBreakpointLocation (int newLine, int newColumn)
+		{
+			if (session != null) {
+				session.AdjustBreakpointLocation ((Breakpoint)BreakEvent, newLine, newColumn);
+			} else {
+				adjustedColumn = newColumn;
+				adjustedLine = newLine;
+			}
+		}
+
+		/// <summary>
+		/// Increments the hit count.
+		/// </summary>
+		/// <returns><c>true</c> if the break event should trigger, or <c>false</c> otherwise.</returns>
+		public bool HitCountReached
+		{
+			get {
+				switch (BreakEvent.HitCountMode) {
+				case HitCountMode.LessThan:
+					return BreakEvent.CurrentHitCount < BreakEvent.HitCount;
+				case HitCountMode.LessThanOrEqualTo:
+					return BreakEvent.CurrentHitCount <= BreakEvent.HitCount;
+				case HitCountMode.EqualTo:
+					return BreakEvent.CurrentHitCount == BreakEvent.HitCount;
+				case HitCountMode.GreaterThan:
+					return BreakEvent.CurrentHitCount > BreakEvent.HitCount;
+				case HitCountMode.GreaterThanOrEqualTo:
+					return BreakEvent.CurrentHitCount >= BreakEvent.HitCount;
+				case HitCountMode.MultipleOf:
+					return (BreakEvent.CurrentHitCount % BreakEvent.HitCount) == 0;
+				default:
+					return true;
+				}
+			}
+		}
+
+		public void IncrementHitCount ()
+		{
+			if (BreakEvent.HitCountMode != HitCountMode.None) {
+				BreakEvent.CurrentHitCount++;
+				BreakEvent.NotifyUpdate ();
+			}
+		}
+
+		[Obsolete ("Use IncrementHitCount() instead")]
+		public void UpdateHitCount (int count)
+		{
+			BreakEvent.CurrentHitCount = count;
+			BreakEvent.NotifyUpdate ();
+		}
+		
+		public void SetStatus (BreakEventStatus s, string statusMessage)
+		{
+			if (s != Status) {
+				Status = s;
+				StatusMessage = statusMessage;
+				if (session != null)
+					session.NotifyBreakEventStatusChanged (BreakEvent);
+			}
+		}
+		
+		public bool RunCustomBreakpointAction (string actionId)
+		{
+			BreakEventHitHandler h = session.CustomBreakEventHitHandler;
+			return h != null && h (actionId, BreakEvent);
+		}
+		
+		public void UpdateLastTraceValue (string value)
+		{
+			BreakEvent.LastTraceValue = value;
+			BreakEvent.NotifyUpdate ();
+			if (value != null) {
+				if (session.BreakpointTraceHandler != null)
+					session.BreakpointTraceHandler (BreakEvent, value);
+				else
+					session.OnDebuggerOutput (false, value + "\n");
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakEventStatus.cs b/Mono.Debugging/Mono.Debugging.Client/BreakEventStatus.cs
new file mode 100644
index 0000000..24a94cf
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakEventStatus.cs
@@ -0,0 +1,57 @@
+// 
+// BreakEventStatus.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2011 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 Mono.Debugging.Client
+{
+	public enum BreakEventStatus
+	{
+		/// <summary>
+		/// The breakpoint is not connected to any debug session
+		/// </summary>
+		Disconnected = 1,
+		
+		/// <summary>
+		/// The breakpoint is not yet bound to a valid location
+		/// </summary>
+		NotBound = 2,
+		
+		/// <summary>
+		/// The breakpoint is bound 
+		/// </summary>
+		Bound = 3,
+		
+		/// <summary>
+		/// The breakpoint could not be bound because the breakpoint location is invalid
+		/// </summary>
+		Invalid = 4,
+		
+		/// <summary>
+		/// There was a debugger error while binding the breakpoint
+		/// </summary>
+		BindError = 5
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/Breakpoint.cs b/Mono.Debugging/Mono.Debugging.Client/Breakpoint.cs
new file mode 100644
index 0000000..3d3fd7a
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/Breakpoint.cs
@@ -0,0 +1,237 @@
+// Breakpoint.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Xml;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class Breakpoint: BreakEvent
+	{
+		bool breakIfConditionChanges;
+		string conditionExpression;
+		string lastConditionValue;
+		int adjustedColumn = -1;
+		int adjustedLine = -1;
+		string fileName;
+		int column;
+		int line;
+		
+		public Breakpoint (string fileName, int line, int column)
+		{
+			FileName = fileName;
+			Column = column;
+			Line = line;
+		}
+
+		public Breakpoint (string fileName, int line) : this (fileName, line, 1)
+		{
+		}
+		
+		internal Breakpoint (XmlElement elem): base (elem)
+		{
+			string s = elem.GetAttribute ("file");
+			if (!string.IsNullOrEmpty (s))
+				fileName = s;
+			
+			s = elem.GetAttribute ("line");
+			if (string.IsNullOrEmpty (s) || !int.TryParse (s, out line))
+				line = 1;
+			
+			s = elem.GetAttribute ("column");
+			if (string.IsNullOrEmpty (s) || !int.TryParse (s, out column))
+				column = 1;
+			
+			s = elem.GetAttribute ("conditionExpression");
+			if (!string.IsNullOrEmpty (s))
+				conditionExpression = s;
+			
+			s = elem.GetAttribute ("breakIfConditionChanges");
+			if (!string.IsNullOrEmpty (s) && !bool.TryParse (s, out breakIfConditionChanges))
+				breakIfConditionChanges = false;
+		}
+		
+		internal override XmlElement ToXml (XmlDocument doc)
+		{
+			XmlElement elem = base.ToXml (doc);
+			
+			if (!string.IsNullOrEmpty (fileName))
+				elem.SetAttribute ("file", fileName);
+			
+			elem.SetAttribute ("line", line.ToString ());
+			elem.SetAttribute ("column", column.ToString ());
+			
+			if (!string.IsNullOrEmpty (conditionExpression)) {
+				elem.SetAttribute ("conditionExpression", conditionExpression);
+				if (breakIfConditionChanges)
+					elem.SetAttribute ("breakIfConditionChanges", "True");
+			}
+			
+			return elem;
+		}
+		
+		public string FileName {
+			get { return fileName; }
+			protected set { fileName = value; }
+		}
+
+		public int OriginalColumn {
+			get { return column; }
+		}
+		
+		public int Column {
+			get { return adjustedColumn == -1 ? column : adjustedColumn; }
+			protected set { column = value; }
+		}
+		
+		public int OriginalLine {
+			get { return line; }
+		}
+		
+		public int Line {
+			get { return adjustedLine == -1 ? line : adjustedLine; }
+			protected set { line = value; }
+		}
+		
+		public void SetColumn (int newColumn)
+		{
+			ResetAdjustedColumn ();
+			column = newColumn;
+		}
+		
+		public void SetLine (int newLine)
+		{
+			ResetAdjustedLine ();
+			line = newLine;
+		}
+		
+		internal void SetAdjustedColumn (int newColumn)
+		{
+			adjustedColumn = newColumn;
+		}
+		
+		internal void SetAdjustedLine (int newLine)
+		{
+			adjustedLine = newLine;
+		}
+
+		// FIXME: make this private
+		internal void ResetAdjustedColumn ()
+		{
+			adjustedColumn = -1;
+		}
+
+		// FIXME: make this private
+		internal void ResetAdjustedLine ()
+		{
+			adjustedLine = -1;
+		}
+
+		public override bool Reset ()
+		{
+			bool changed = base.Reset () || HasAdjustedLine || HasAdjustedColumn;
+
+			lastConditionValue = null;
+			adjustedColumn = -1;
+			adjustedLine = -1;
+
+			return changed;
+		}
+
+		// FIXME: make this private
+		internal bool HasAdjustedColumn {
+			get { return adjustedColumn != -1; }
+		}
+
+		// FIXME: make this private
+		internal bool HasAdjustedLine {
+			get { return adjustedLine != -1; }
+		}
+
+		public string ConditionExpression {
+			get {
+				return conditionExpression;
+			}
+			set {
+				conditionExpression = value;
+			}
+		}
+		
+		public string LastConditionValue {
+			get {
+				return lastConditionValue;
+			}
+			set {
+				lastConditionValue = value;
+			}
+		}
+		
+		public bool BreakIfConditionChanges {
+			get {
+				return breakIfConditionChanges;
+			}
+			set {
+				breakIfConditionChanges = value;
+			}
+		}
+		
+		public override void CopyFrom (BreakEvent ev)
+		{
+			base.CopyFrom (ev);
+			
+			Breakpoint bp = (Breakpoint) ev;
+			
+			breakIfConditionChanges = bp.breakIfConditionChanges;
+			conditionExpression = bp.conditionExpression;
+			fileName = bp.fileName;
+			column = bp.column;
+			line = bp.line;
+		}
+	}
+
+	public enum HitCountMode {
+		None,
+		LessThan,
+		LessThanOrEqualTo,
+		EqualTo,
+		GreaterThan,
+		GreaterThanOrEqualTo,
+		MultipleOf
+	}
+
+	[Flags]
+	public enum HitAction
+	{
+		None = 0x0,
+		Break = 0x1,
+		PrintExpression = 0x2,
+		CustomAction = 0x4
+	}
+	
+	public delegate bool BreakEventHitHandler (string actionId, BreakEvent be);
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakpointEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/BreakpointEventArgs.cs
new file mode 100644
index 0000000..928a863
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakpointEventArgs.cs
@@ -0,0 +1,45 @@
+// BreakpointEventArgs.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	public class BreakpointEventArgs: EventArgs
+	{
+		Breakpoint bp;
+		
+		public BreakpointEventArgs (Breakpoint bp)
+		{
+			this.bp = bp;
+		}
+		
+		public Breakpoint Breakpoint {
+			get { return bp; }
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/BreakpointStore.cs b/Mono.Debugging/Mono.Debugging.Client/BreakpointStore.cs
new file mode 100644
index 0000000..f959564
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/BreakpointStore.cs
@@ -0,0 +1,583 @@
+// BreakpointStore.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.IO;
+using System.Linq;
+using System.Xml;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.InteropServices;
+
+namespace Mono.Debugging.Client
+{
+	public sealed class BreakpointStore: ICollection<BreakEvent>
+	{
+		static readonly StringComparer PathComparer;
+		static readonly bool IsWindows;
+		static readonly bool IsMac;
+
+		static BreakpointStore ()
+		{
+			IsWindows = Path.DirectorySeparatorChar == '\\';
+			IsMac = !IsWindows && IsRunningOnMac ();
+
+			PathComparer = IsWindows || IsMac ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
+		}
+
+		[DllImport ("libc")]
+		static extern int uname (IntPtr buf);
+
+		//From Managed.Windows.Forms/XplatUI
+		static bool IsRunningOnMac ()
+		{
+			IntPtr buf = IntPtr.Zero;
+			try {
+				buf = Marshal.AllocHGlobal (8192);
+				// This is a hacktastic way of getting sysname from uname ()
+				if (uname (buf) == 0) {
+					string os = Marshal.PtrToStringAnsi (buf);
+					if (os == "Darwin")
+						return true;
+				}
+			} catch {
+			} finally {
+				if (buf != IntPtr.Zero)
+					Marshal.FreeHGlobal (buf);
+			}
+			return false;
+		}
+
+		readonly List<BreakEvent> breakpoints = new List<BreakEvent> ();
+		
+		public int Count {
+			get {
+				return breakpoints.Count;
+			}
+		}
+
+		public bool IsReadOnly {
+			get {
+				ReadOnlyCheckEventArgs args = new ReadOnlyCheckEventArgs ();
+				EventHandler<ReadOnlyCheckEventArgs> checkingReadOnly = CheckingReadOnly;
+				if (checkingReadOnly != null)
+					checkingReadOnly (this, args);
+				return args.IsReadOnly;
+			}
+		}
+
+		public Breakpoint Add (string filename, int line, int column)
+		{
+			return Add (filename, line, column, true);
+		}
+
+		public Breakpoint Add (string filename, int line)
+		{
+			return Add (filename, line, 1, true);
+		}
+		
+		public Breakpoint Add (string filename, int line, int column, bool activate)
+		{
+			if (filename == null)
+				throw new ArgumentNullException ("filename");
+
+			if (line < 1)
+				throw new ArgumentOutOfRangeException ("line");
+
+			if (column < 1)
+				throw new ArgumentOutOfRangeException ("column");
+
+			if (IsReadOnly)
+				return null;
+
+			Breakpoint bp = new Breakpoint (filename, line, column);
+			Add (bp);
+
+			return bp;
+		}
+
+		void ICollection<BreakEvent>.Add (BreakEvent bp)
+		{
+			Add (bp);
+		}
+		
+		public bool Add (BreakEvent bp)
+		{
+			if (bp == null)
+				throw new ArgumentNullException ("bp");
+
+			if (IsReadOnly)
+				return false;
+
+			breakpoints.Add (bp);
+			bp.Store = this;
+			OnBreakEventAdded (bp);
+
+			return true;
+		}
+		
+		public Catchpoint AddCatchpoint (string exceptionName)
+		{
+			if (exceptionName == null)
+				throw new ArgumentNullException ("exceptionName");
+
+			if (IsReadOnly)
+				return null;
+
+			Catchpoint cp = new Catchpoint (exceptionName);
+			Add (cp);
+
+			return cp;
+		}
+		
+		public bool Remove (string filename, int line, int column)
+		{
+			if (filename == null)
+				throw new ArgumentNullException ("filename");
+
+			if (IsReadOnly)
+				return false;
+
+			filename = Path.GetFullPath (filename);
+			
+			for (int n=0; n<breakpoints.Count; n++) {
+				Breakpoint bp = breakpoints [n] as Breakpoint;
+				if (bp != null && FileNameEquals (bp.FileName, filename) &&
+				    (bp.OriginalLine == line || bp.Line == line) &&
+				    (bp.OriginalColumn == column || bp.Column == column)) {
+					breakpoints.RemoveAt (n);
+					OnBreakEventRemoved (bp);
+					n--;
+				}
+			}
+			return true;
+		}
+		
+		public bool RemoveCatchpoint (string exceptionName)
+		{
+			if (exceptionName == null)
+				throw new ArgumentNullException ("exceptionName");
+
+			if (IsReadOnly)
+				return false;
+
+			for (int n=0; n<breakpoints.Count; n++) {
+				Catchpoint cp = breakpoints [n] as Catchpoint;
+				if (cp != null && cp.ExceptionName == exceptionName) {
+					breakpoints.RemoveAt (n);
+					OnBreakEventRemoved (cp);
+					n--;
+				}
+			}
+			return true;
+		}
+		
+		public bool Remove (BreakEvent bp)
+		{
+			if (bp == null)
+				throw new ArgumentNullException ("bp");
+
+			if (!IsReadOnly && breakpoints.Remove (bp)) {
+				OnBreakEventRemoved (bp);
+				return true;
+			}
+
+			return false;
+		}
+		
+		public Breakpoint Toggle (string filename, int line, int column)
+		{
+			if (filename == null)
+				throw new ArgumentNullException ("filename");
+
+			if (line < 1)
+				throw new ArgumentOutOfRangeException ("line");
+
+			if (column < 1)
+				throw new ArgumentOutOfRangeException ("column");
+
+			if (IsReadOnly)
+				return null;
+			
+			ReadOnlyCollection<Breakpoint> col = GetBreakpointsAtFileLine (filename, line);
+			if (col.Count > 0) {
+				// Remove only the most-recently-added breakpoint on the specified line
+				Remove (col[col.Count - 1]);
+				return null;
+			}
+
+			return Add (filename, line, column);
+		}
+
+		public ReadOnlyCollection<BreakEvent> GetBreakevents ()
+		{
+			return breakpoints.AsReadOnly ();
+		}
+
+		public ReadOnlyCollection<Breakpoint> GetBreakpoints ()
+		{
+			List<Breakpoint> list = new List<Breakpoint> ();
+			foreach (BreakEvent be in breakpoints) {
+				if (be is Breakpoint)
+					list.Add ((Breakpoint)be);
+			}
+			return list.AsReadOnly ();
+		}
+		
+		public ReadOnlyCollection<Catchpoint> GetCatchpoints ()
+		{
+			List<Catchpoint> list = new List<Catchpoint> ();
+			foreach (BreakEvent be in breakpoints) {
+				if (be is Catchpoint)
+					list.Add ((Catchpoint) be);
+			}
+			return list.AsReadOnly ();
+		}
+		
+		public ReadOnlyCollection<Breakpoint> GetBreakpointsAtFile (string filename)
+		{
+			if (filename == null)
+				throw new ArgumentNullException ("filename");
+
+			var list = new List<Breakpoint> ();
+			
+			try {
+				filename = Path.GetFullPath (filename);
+			} catch {
+				return list.AsReadOnly ();
+			}
+			
+			foreach (BreakEvent be in breakpoints) {
+				Breakpoint bp = be as Breakpoint;
+				if (bp != null && FileNameEquals (bp.FileName, filename))
+					list.Add (bp);
+			}
+			
+			return list.AsReadOnly ();
+		}
+		
+		public ReadOnlyCollection<Breakpoint> GetBreakpointsAtFileLine (string filename, int line)
+		{
+			if (filename == null)
+				throw new ArgumentNullException ("filename");
+
+			var list = new List<Breakpoint> ();
+			
+			try {
+				filename = Path.GetFullPath (filename);
+			} catch {
+				return list.AsReadOnly ();
+			}
+			
+			foreach (BreakEvent be in breakpoints) {
+				Breakpoint bp = be as Breakpoint;
+				if (bp != null && FileNameEquals (bp.FileName, filename) && (bp.OriginalLine == line || bp.Line == line))
+					list.Add (bp);
+			}
+			
+			return list.AsReadOnly ();
+		}
+
+		public IEnumerator GetEnumerator ()
+		{
+			return breakpoints.GetEnumerator ();
+		}
+
+		IEnumerator<BreakEvent> IEnumerable<BreakEvent>.GetEnumerator ()
+		{
+			return breakpoints.GetEnumerator ();
+		}
+
+		public void Clear ()
+		{
+			List<BreakEvent> oldList = new List<BreakEvent> (breakpoints);
+			foreach (BreakEvent bp in oldList)
+				Remove (bp);
+		}
+
+		public void ClearBreakpoints ()
+		{
+			foreach (Breakpoint bp in GetBreakpoints ())
+				Remove (bp);
+		}
+
+		public void ClearCatchpoints ()
+		{
+			foreach (Catchpoint bp in GetCatchpoints ())
+				Remove (bp);
+		}
+
+		public bool Contains (BreakEvent item)
+		{
+			return breakpoints.Contains (item);
+		}
+
+		public void CopyTo (BreakEvent[] array, int arrayIndex)
+		{
+			breakpoints.CopyTo (array, arrayIndex);
+		}
+		
+		public void UpdateBreakpointLine (Breakpoint bp, int newLine)
+		{
+			if (IsReadOnly)
+				return;
+			
+			bp.SetLine (newLine);
+			NotifyBreakEventChanged (bp);
+		}
+		
+		internal void AdjustBreakpointLine (Breakpoint bp, int newLine, int newColumn)
+		{
+			if (IsReadOnly)
+				return;
+
+			bp.SetAdjustedColumn (newColumn);
+			bp.SetAdjustedLine (newLine);
+			NotifyBreakEventChanged (bp);
+		}
+		
+		internal void ResetAdjustedBreakpoints ()
+		{
+			if (IsReadOnly)
+				return;
+			
+			foreach (Breakpoint bp in breakpoints.OfType<Breakpoint> ().ToArray ()) {
+				if (bp.Reset ())
+					NotifyBreakEventChanged (bp);
+			}
+		}
+		
+		public XmlElement Save ()
+		{
+			XmlDocument doc = new XmlDocument ();
+			XmlElement elem = doc.CreateElement ("BreakpointStore");
+			foreach (BreakEvent ev in this) {
+				XmlElement be = ev.ToXml (doc);
+				elem.AppendChild (be);
+			}
+			return elem;
+		}
+		
+		public void Load (XmlElement rootElem)
+		{
+			Clear ();
+			foreach (XmlNode n in rootElem.ChildNodes) {
+				XmlElement elem = n as XmlElement;
+				if (elem == null)
+					continue;
+				BreakEvent ev = BreakEvent.FromXml (elem);
+				if (ev != null)
+					Add (ev);
+			}
+		}
+
+		[DllImport ("libc")]
+		static extern IntPtr realpath (string path, IntPtr buffer);
+
+		static string ResolveFullPath (string path)
+		{
+			if (IsWindows)
+				return Path.GetFullPath (path);
+
+			const int PATHMAX = 4096 + 1;
+			IntPtr buffer = IntPtr.Zero;
+
+			try {
+				buffer = Marshal.AllocHGlobal (PATHMAX);
+				var result = realpath (path, buffer);
+				return result == IntPtr.Zero ? "" : Marshal.PtrToStringAuto (buffer);
+			} finally {
+				if (buffer != IntPtr.Zero)
+					Marshal.FreeHGlobal (buffer);
+			}
+		}
+
+		public static bool FileNameEquals (string file1, string file2)
+		{
+			if (file1 == null)
+				return file2 == null;
+
+			if (file2 == null)
+				return false;
+
+			if (PathComparer.Compare (file1, file2) == 0)
+				return true;
+
+			var rfile1 = ResolveFullPath (file1);
+			var rfile2 = ResolveFullPath (file2);
+
+			return PathComparer.Compare (rfile1, rfile2) == 0;
+		}
+		
+		internal bool EnableBreakEvent (BreakEvent be, bool enabled)
+		{
+			if (IsReadOnly)
+				return false;
+
+			OnChanged ();
+			EventHandler<BreakEventArgs> evnt = BreakEventEnableStatusChanged;
+			if (evnt != null)
+				evnt (this, new BreakEventArgs (be));
+			NotifyStatusChanged (be);
+
+			return true;
+		}
+		
+		void OnBreakEventAdded (BreakEvent be)
+		{
+			OnChanged ();
+			EventHandler<BreakEventArgs> breakEventAdded = BreakEventAdded;
+			if (breakEventAdded != null)
+				breakEventAdded (this, new BreakEventArgs ((BreakEvent)be));
+			if (be is Breakpoint) {
+				EventHandler<BreakpointEventArgs> breakpointAdded = BreakpointAdded;
+				if (breakpointAdded != null)
+					breakpointAdded (this, new BreakpointEventArgs ((Breakpoint)be));
+			} else if (be is Catchpoint) {
+				EventHandler<CatchpointEventArgs> catchpointAdded = CatchpointAdded;
+				if (catchpointAdded != null)
+					catchpointAdded (this, new CatchpointEventArgs ((Catchpoint)be));
+			}
+		}
+		
+		void OnBreakEventRemoved (BreakEvent be)
+		{
+			OnChanged ();
+			EventHandler<BreakEventArgs> breakEventRemoved = BreakEventRemoved;
+			if (breakEventRemoved != null)
+				breakEventRemoved (this, new BreakEventArgs ((BreakEvent)be));
+			if (be is Breakpoint) {
+				EventHandler<BreakpointEventArgs> breakpointRemoved = BreakpointRemoved;
+				if (breakpointRemoved != null)
+					breakpointRemoved (this, new BreakpointEventArgs ((Breakpoint)be));
+			} else if (be is Catchpoint) {
+				EventHandler<CatchpointEventArgs> catchpointRemoved = CatchpointRemoved;
+				if (catchpointRemoved != null)
+					catchpointRemoved (this, new CatchpointEventArgs ((Catchpoint)be));
+			}
+		}
+		
+		void OnChanged ()
+		{
+			EventHandler changed = Changed;
+			if (changed != null)
+				changed (this, EventArgs.Empty);
+		}
+		
+		internal void NotifyStatusChanged (BreakEvent be)
+		{
+			try {
+				EventHandler<BreakEventArgs> breakEventStatusChanged = BreakEventStatusChanged;
+				if (breakEventStatusChanged != null)
+					breakEventStatusChanged (this, new BreakEventArgs ((BreakEvent)be));
+				if (be is Breakpoint) {
+					EventHandler<BreakpointEventArgs> breakpointStatusChanged = BreakpointStatusChanged;
+					if (breakpointStatusChanged != null)
+						breakpointStatusChanged (this, new BreakpointEventArgs ((Breakpoint)be));
+				} else if (be is Catchpoint) {
+					EventHandler<CatchpointEventArgs > catchpointStatusChanged = CatchpointStatusChanged;
+					if (catchpointStatusChanged != null)
+						catchpointStatusChanged (this, new CatchpointEventArgs ((Catchpoint)be));
+				}
+			} catch {
+				// Ignore
+			}
+		}
+		
+		internal void NotifyBreakEventChanged (BreakEvent be)
+		{
+			try {
+				EventHandler<BreakEventArgs> breakEventModified = BreakEventModified;
+				if (breakEventModified != null)
+					breakEventModified (this, new BreakEventArgs ((BreakEvent)be));
+				if (be is Breakpoint) {
+					EventHandler<BreakpointEventArgs > breakpointModified = BreakpointModified;
+					if (breakpointModified != null)
+						breakpointModified (this, new BreakpointEventArgs ((Breakpoint)be));
+				} else if (be is Catchpoint) {
+					EventHandler<CatchpointEventArgs >  catchpointModified = CatchpointModified;
+					if (catchpointModified != null)
+						catchpointModified (this, new CatchpointEventArgs ((Catchpoint)be));
+				}
+				OnChanged ();
+			} catch {
+				// Ignore
+			}
+		}
+		
+		internal void NotifyBreakEventUpdated (BreakEvent be)
+		{
+			try {
+				EventHandler<BreakEventArgs> breakEventUpdated = BreakEventUpdated;
+				if (breakEventUpdated != null)
+					breakEventUpdated (this, new BreakEventArgs ((BreakEvent)be));
+				if (be is Breakpoint) {
+					EventHandler<BreakpointEventArgs> breakpointUpdated = BreakpointUpdated;
+					if (breakpointUpdated != null)
+						breakpointUpdated (this, new BreakpointEventArgs ((Breakpoint)be));
+				} else if (be is Catchpoint) {
+					EventHandler<CatchpointEventArgs>  catchpointUpdated = CatchpointUpdated;
+					if (catchpointUpdated != null)
+						catchpointUpdated (this, new CatchpointEventArgs ((Catchpoint)be));
+				}
+			} catch {
+				// Ignore
+			}
+		}
+		
+		public event EventHandler<BreakpointEventArgs> BreakpointAdded;
+		public event EventHandler<BreakpointEventArgs> BreakpointRemoved;
+		public event EventHandler<BreakpointEventArgs> BreakpointStatusChanged;
+		public event EventHandler<BreakpointEventArgs> BreakpointModified;
+		public event EventHandler<BreakpointEventArgs> BreakpointUpdated;
+		public event EventHandler<CatchpointEventArgs> CatchpointAdded;
+		public event EventHandler<CatchpointEventArgs> CatchpointRemoved;
+		public event EventHandler<CatchpointEventArgs> CatchpointStatusChanged;
+		public event EventHandler<CatchpointEventArgs> CatchpointModified;
+		public event EventHandler<CatchpointEventArgs> CatchpointUpdated;
+		public event EventHandler<BreakEventArgs> BreakEventAdded;
+		public event EventHandler<BreakEventArgs> BreakEventRemoved;
+		public event EventHandler<BreakEventArgs> BreakEventStatusChanged;
+		public event EventHandler<BreakEventArgs> BreakEventModified;
+		public event EventHandler<BreakEventArgs> BreakEventUpdated;
+		public event EventHandler Changed;
+		public event EventHandler<ReadOnlyCheckEventArgs> CheckingReadOnly;
+		
+		internal event EventHandler<BreakEventArgs> BreakEventEnableStatusChanged;
+	}
+	
+	public class ReadOnlyCheckEventArgs: EventArgs
+	{
+		internal bool IsReadOnly;
+		
+		public void SetReadOnly (bool isReadOnly)
+		{
+			IsReadOnly = IsReadOnly || isReadOnly;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/Catchpoint.cs b/Mono.Debugging/Mono.Debugging.Client/Catchpoint.cs
new file mode 100644
index 0000000..0e0f2a1
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/Catchpoint.cs
@@ -0,0 +1,81 @@
+// Catchpoint.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Xml;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class Catchpoint: BreakEvent
+	{
+		string exceptionName;
+		bool includeSubclasses;
+		
+		public Catchpoint (string exceptionName) : this (exceptionName, true)
+		{
+		}
+
+		public Catchpoint (string exceptionName, bool includeSubclasses)
+		{
+			this.exceptionName = exceptionName;
+			this.includeSubclasses = includeSubclasses;
+		}
+		
+		internal Catchpoint (XmlElement elem): base (elem)
+		{
+			exceptionName = elem.GetAttribute ("exceptionName");
+			includeSubclasses = Boolean.Parse (elem.GetAttribute ("includeSubclasses"));
+		}
+
+		internal override XmlElement ToXml (XmlDocument doc)
+		{
+			XmlElement elem = base.ToXml (doc);
+			elem.SetAttribute ("exceptionName", exceptionName);
+			elem.SetAttribute ("includeSubclasses", includeSubclasses.ToString ());
+			return elem;
+		}
+
+		
+		public string ExceptionName {
+			get { return exceptionName; }
+		}
+
+		public bool IncludeSubclasses {
+			get { return includeSubclasses; }
+		}
+		
+		public override void CopyFrom (BreakEvent ev)
+		{
+			base.CopyFrom (ev);
+			Catchpoint cp = (Catchpoint) ev;
+			exceptionName = cp.exceptionName;
+			includeSubclasses = cp.includeSubclasses;
+		}
+
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/CatchpointEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/CatchpointEventArgs.cs
new file mode 100644
index 0000000..68abf67
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/CatchpointEventArgs.cs
@@ -0,0 +1,45 @@
+// CatchpointEventArgs.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	public class CatchpointEventArgs: EventArgs
+	{
+		Catchpoint cp;
+		
+		public CatchpointEventArgs (Catchpoint cp)
+		{
+			this.cp = cp;
+		}
+		
+		public Catchpoint Catchpoint {
+			get { return cp; }
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/CompletionData.cs b/Mono.Debugging/Mono.Debugging.Client/CompletionData.cs
new file mode 100644
index 0000000..32ffc2a
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/CompletionData.cs
@@ -0,0 +1,77 @@
+// CompletionData.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class CompletionData
+	{
+		int expressionLength;
+		List<CompletionItem> items = new List<CompletionItem> ();
+		
+		public int ExpressionLength {
+			get {
+				return expressionLength;
+			}
+			set {
+				expressionLength = value;
+			}
+		}
+		
+		public List<CompletionItem> Items {
+			get { return items; }
+		}
+	}
+	
+	[Serializable]
+	public class CompletionItem
+	{
+		string name;
+		ObjectValueFlags flags;
+		
+		public CompletionItem (string name, ObjectValueFlags flags)
+		{
+			this.name = name;
+			this.flags = flags;
+		}
+		
+		public string Name {
+			get {
+				return name;
+			}
+		}
+		
+		public ObjectValueFlags Flags {
+			get {
+				return flags;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerException.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerException.cs
new file mode 100644
index 0000000..5db7ded
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerException.cs
@@ -0,0 +1,47 @@
+// 
+// DebuggerException.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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.Runtime.Serialization;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class DebuggerException: Exception
+	{
+		public DebuggerException (SerializationInfo info, StreamingContext ctx): base (info, ctx)
+		{
+		}
+		
+		public DebuggerException (string message): base (message)
+		{
+		}
+		
+		public DebuggerException (string message, Exception inner): base (message, inner)
+		{
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerFeatures.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerFeatures.cs
new file mode 100644
index 0000000..2060645
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerFeatures.cs
@@ -0,0 +1,47 @@
+// DebuggerFeatures.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	[Flags]
+	public enum DebuggerFeatures: uint
+	{
+		None = 0,
+		ConditionalBreakpoints = 1,
+		Tracepoints = 1 << 1,
+		Catchpoints = 1 << 2,
+		Attaching = 1 << 3,
+		DebugFile = 1 << 4,
+		Stepping = 1 << 5,
+		Pause = 1 << 6,
+		Breakpoints = 1 << 7,
+		Disassembly = 1 << 8,
+		All = 0xffffffff
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerLoggingService.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerLoggingService.cs
new file mode 100644
index 0000000..22c1662
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerLoggingService.cs
@@ -0,0 +1,71 @@
+// 
+// DebuggerLoggingService.cs
+//  
+// Author:
+//       Michael Hutchinson <mhutchinson at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Client
+{
+	/// <summary>
+	/// This is a simple abstraction so that MD can plug in its own logging service to handle the Mono.Debugging.Soft
+	/// error logging, without Mono.Debugging.Soft depending on MonoDevelop.Core.
+	/// In the absence of a custom logger, it writes to Console.
+	/// </summary>
+	public static class DebuggerLoggingService
+	{
+		public static ICustomLogger CustomLogger { get; set; }
+		
+		public static void LogError (string message, Exception ex)
+		{
+			if (CustomLogger != null)
+				CustomLogger.LogError (message, ex);
+			else
+				Console.WriteLine (message + (ex != null? System.Environment.NewLine + ex.ToString () : string.Empty));
+		}
+
+		public static void LogMessage (string messageFormat, params object[] args)
+		{
+			if (CustomLogger != null)
+				CustomLogger.LogMessage (messageFormat, args);
+			else
+				Console.WriteLine (messageFormat, args);
+		}
+
+		//this is meant to show a GUI if possible
+		public static void LogAndShowException (string message, Exception ex)
+		{
+			if (CustomLogger != null)
+				CustomLogger.LogAndShowException (message, ex);
+			else
+				LogError (message, ex);
+		}
+	}
+	
+	public interface ICustomLogger
+	{
+		void LogError (string message, System.Exception ex);
+		void LogAndShowException (string message, System.Exception ex);
+		void LogMessage (string messageFormat, params object[] args);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerSession.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerSession.cs
new file mode 100644
index 0000000..ecd6bcf
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerSession.cs
@@ -0,0 +1,1538 @@
+// DebuggerSession.cs
+//
+// Author:
+//   Ankit Jain <jankit at novell.com>
+//   Lluis Sanchez Gual <lluis at 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.Threading;
+using System.Collections.Generic;
+
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Client
+{
+	public delegate void TargetEventHandler (object sender, TargetEventArgs args);
+	public delegate void ProcessEventHandler (int processId);
+	public delegate void ThreadEventHandler (int threadId);
+	public delegate bool ExceptionHandler (Exception ex);
+	public delegate string TypeResolverHandler (string identifier, SourceLocation location);
+	public delegate void BreakpointTraceHandler (BreakEvent be, string trace);
+	public delegate IExpressionEvaluator GetExpressionEvaluatorHandler (string extension);
+	public delegate IConnectionDialog ConnectionDialogCreator ();
+	
+	public abstract class DebuggerSession: IDisposable
+	{
+		readonly Dictionary<BreakEvent, BreakEventInfo> breakpoints = new Dictionary<BreakEvent, BreakEventInfo> ();
+		readonly Dictionary<string, string> resolvedExpressionCache = new Dictionary<string, string> ();
+		readonly InternalDebuggerSession frontend;
+		readonly object slock = new object ();
+		readonly object olock = new object ();
+		BreakpointStore breakpointStore;
+		OutputWriterDelegate outputWriter;
+		OutputWriterDelegate logWriter;
+		DebuggerSessionOptions options;
+		ProcessInfo[] currentProcesses;
+		ThreadInfo activeThread;
+		bool ownedBreakpointStore;
+		bool adjustingBreakpoints;
+		bool disposed;
+		bool attached;
+
+		/// <summary>
+		/// Reports a debugger event
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetEvent;
+		
+		/// <summary>
+		/// Raised when the debugger resumes execution after being stopped
+		/// </summary>
+		public event EventHandler TargetStarted;
+		
+		/// <summary>
+		/// Raised when the underlying debugging engine has been initialized and it is ready to start execution.
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetReady;
+		
+		/// <summary>
+		/// Raised when the debugging session is paused
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetStopped;
+		
+		/// <summary>
+		/// Raised when the execution is interrupted by an external event
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetInterrupted;
+		
+		/// <summary>
+		/// Raised when a breakpoint is hit
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetHitBreakpoint;
+		
+		/// <summary>
+		/// Raised when the execution is interrupted due to receiving a signal
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetSignaled;
+		
+		/// <summary>
+		/// Raised when the debugged process exits
+		/// </summary>
+		public event EventHandler TargetExited;
+		
+		/// <summary>
+		/// Raised when an exception for which there is a catchpoint is thrown
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetExceptionThrown;
+		
+		/// <summary>
+		/// Raised when an exception is unhandled
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetUnhandledException;
+		
+		/// <summary>
+		/// Raised when a thread is started in the debugged process
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetThreadStarted;
+		
+		/// <summary>
+		/// Raised when a thread is stopped in the debugged process
+		/// </summary>
+		public event EventHandler<TargetEventArgs> TargetThreadStopped;
+		
+		/// <summary>
+		/// Raised when the 'busy state' of the debugger changes.
+		/// The debugger may switch to busy state if it is in the middle
+		/// of an expression evaluation which can't be aborted.
+		/// </summary>
+		public event EventHandler<BusyStateEventArgs> BusyStateChanged;
+		
+		protected DebuggerSession ()
+		{
+			UseOperationThread = true;
+			frontend = new InternalDebuggerSession (this);
+		}
+		
+		/// <summary>
+		/// Releases all resource used by the <see cref="Mono.Debugging.Client.DebuggerSession"/> object.
+		/// </summary>
+		/// <remarks>
+		/// Call <see cref="Dispose"/> when you are finished using the <see cref="Mono.Debugging.Client.DebuggerSession"/>.
+		/// The <see cref="Dispose"/> method leaves the <see cref="Mono.Debugging.Client.DebuggerSession"/> in an unusable
+		/// state. After calling <see cref="Dispose"/>, you must release all references to the
+		/// <see cref="Mono.Debugging.Client.DebuggerSession"/> so the garbage collector can reclaim the memory that the
+		/// <see cref="Mono.Debugging.Client.DebuggerSession"/> was occupying.
+		/// </remarks>
+		public virtual void Dispose ()
+		{
+			Dispatch (delegate {
+				if (!disposed) {
+					disposed = true;
+					if (!ownedBreakpointStore)
+						Breakpoints = null;
+				}
+			});
+		}
+		
+		/// <summary>
+		/// Gets or sets an exception handler to be invoked when an exception is raised by the debugger engine.
+		/// </summary>
+		/// <remarks>
+		/// Notice that this handler will be used to report exceptions in the debugger, not exceptions raised
+		/// in the debugged process.
+		/// </remarks>
+		public ExceptionHandler ExceptionHandler {
+			get; set;
+		}
+		
+		/// <summary>
+		/// Gets or sets the connection dialog creator callback.
+		/// </summary>
+		public ConnectionDialogCreator ConnectionDialogCreator { get; set; }
+
+		/// <summary>
+		/// Gets or sets the breakpoint trace handler.
+		/// </summary>
+		/// <remarks>
+		/// This handler is invoked when the value of a tracepoint has to be printed
+		/// </remarks>
+		public BreakpointTraceHandler BreakpointTraceHandler { get; set; }
+		
+		/// <summary>
+		/// Gets or sets the type resolver handler.
+		/// </summary>
+		/// <remarks>
+		/// This handler is invoked when the expression evaluator needs to resolve a type name.
+		/// </remarks>
+		public TypeResolverHandler TypeResolverHandler { get; set; }
+		
+		/// <summary>
+		/// Gets or sets the an expression evaluator provider
+		/// </summary>
+		/// <remarks>
+		/// This handler is invoked when the debugger needs to get an evaluator for a specific type of file
+		/// </remarks>
+		public GetExpressionEvaluatorHandler GetExpressionEvaluator { get; set; }		
+
+		/// <summary>
+		/// Gets or sets the custom break event hit handler.
+		/// </summary>
+		/// <remarks>
+		/// This handler is invoked when a custom breakpoint is hit to determine if the debug session should
+		/// continue or stop.
+		/// </remarks>
+		public BreakEventHitHandler CustomBreakEventHitHandler {
+			get; set;
+		}
+		
+		/// <summary>
+		/// Gets or sets the breakpoint store for the debugger session.
+		/// </summary>
+		public BreakpointStore Breakpoints {
+			get {
+				lock (slock) {
+					if (breakpointStore == null) {
+						Breakpoints = new BreakpointStore ();
+						ownedBreakpointStore = true;
+					}
+					return breakpointStore;
+				}
+			}
+			set {
+				lock (slock) {
+					if (breakpointStore != null) {
+						lock (breakpointStore) {
+							foreach (BreakEvent bp in breakpointStore) {
+								RemoveBreakEvent (bp);
+								NotifyBreakEventStatusChanged (bp);
+							}
+						}
+						breakpointStore.BreakEventAdded -= OnBreakpointAdded;
+						breakpointStore.BreakEventRemoved -= OnBreakpointRemoved;
+						breakpointStore.BreakEventModified -= OnBreakpointModified;
+						breakpointStore.BreakEventEnableStatusChanged -= OnBreakpointStatusChanged;
+						breakpointStore.CheckingReadOnly -= BreakpointStoreCheckingReadOnly;
+						breakpointStore.ResetAdjustedBreakpoints ();
+					}
+
+					breakpointStore = value;
+					ownedBreakpointStore = false;
+
+					if (breakpointStore != null) {
+						if (IsConnected) {
+							Dispatch (delegate {
+								if (IsConnected) {
+									lock (breakpointStore) {
+										foreach (BreakEvent bp in breakpointStore)
+											AddBreakEvent (bp);
+									}
+								}
+							});
+						}
+						breakpointStore.BreakEventAdded += OnBreakpointAdded;
+						breakpointStore.BreakEventRemoved += OnBreakpointRemoved;
+						breakpointStore.BreakEventModified += OnBreakpointModified;
+						breakpointStore.BreakEventEnableStatusChanged += OnBreakpointStatusChanged;
+						breakpointStore.CheckingReadOnly += BreakpointStoreCheckingReadOnly;
+					}
+				}
+			}
+		}
+		
+		void Dispatch (Action action)
+		{
+			if (UseOperationThread) {
+				ThreadPool.QueueUserWorkItem (delegate {
+					lock (slock) {
+						action ();
+					}
+				});
+			} else {
+				lock (slock) {
+					action ();
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Starts a debugging session
+		/// </summary>
+		/// <param name='startInfo'>
+		/// Startup information
+		/// </param>
+		/// <param name='options'>
+		/// Session options
+		/// </param>
+		/// <exception cref='ArgumentNullException'>
+		/// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
+		/// </exception>
+		public void Run (DebuggerStartInfo startInfo, DebuggerSessionOptions options)
+		{
+			if (startInfo == null)
+				throw new ArgumentNullException ("startInfo");
+			if (options == null)
+				throw new ArgumentNullException ("options");
+			
+			lock (slock) {
+				this.options = options;
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnRun (startInfo);
+					} catch (Exception ex) {
+						ForceExit ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Starts a debugging session by attaching the debugger to a running process
+		/// </summary>
+		/// <param name='proc'>
+		/// Process information
+		/// </param>
+		/// <param name='options'>
+		/// Debugging options
+		/// </param>
+		/// <exception cref='ArgumentNullException'>
+		/// Is thrown when an argument passed to a method is invalid because it is <see langword="null" /> .
+		/// </exception>
+		public void AttachToProcess (ProcessInfo proc, DebuggerSessionOptions options)
+		{
+			if (proc == null)
+				throw new ArgumentNullException ("proc");
+			if (options == null)
+				throw new ArgumentNullException ("options");
+			
+			lock (slock) {
+				this.options = options;
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnAttachToProcess (proc.Id);
+						attached = true;
+					} catch (Exception ex) {
+						ForceExit ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Detaches this debugging session from the debugged process
+		/// </summary>
+		public void Detach ()
+		{
+			lock (slock) {
+				try {
+					OnDetach ();
+				} catch (Exception ex) {
+					if (!HandleException (ex))
+						throw;
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Gets a value indicating whether this <see cref="Mono.Debugging.Client.DebuggerSession"/> has been attached to a process using the Attach method.
+		/// </summary>
+		/// <value>
+		/// <c>true</c> if attached to process; otherwise, <c>false</c>.
+		/// </value>
+		public bool AttachedToProcess {
+			get { return attached; }
+		}
+		
+		/// <summary>
+		/// Gets or sets the active thread.
+		/// </summary>
+		/// <remarks>
+		/// This property can only be used when the debugger is paused
+		/// </remarks>
+		public ThreadInfo ActiveThread {
+			get {
+				lock (slock) {
+					return activeThread;
+				}
+			}
+			set {
+				lock (slock) {
+					try {
+						activeThread = value;
+						OnSetActiveThread (activeThread.ProcessId, activeThread.Id);
+					} catch (Exception ex) {
+						if (!HandleException (ex))
+							throw;
+					}
+				}
+			}
+		}
+		
+		
+		/// <summary>
+		/// Executes one line of code
+		/// </summary>
+		public void NextLine ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnNextLine ();
+					} catch (Exception ex) {
+						ForceStop ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Executes one line of code, stepping into method invocations
+		/// </summary>
+		public void StepLine ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnStepLine ();
+					} catch (Exception ex) {
+						ForceStop ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Executes one low level instruction
+		/// </summary>
+		public void NextInstruction ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnNextInstruction ();
+					} catch (Exception ex) {
+						ForceStop ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+
+		/// <summary>
+		/// Executes one low level instruction, stepping into method invocations
+		/// </summary>
+		public void StepInstruction ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnStepInstruction ();
+					} catch (Exception ex) {
+						ForceStop ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Resumes the execution of the debugger and stops when the current method is exited
+		/// </summary>
+		public void Finish ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnFinish ();
+					} catch (Exception ex) {
+						ForceExit ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Returns the status of a breakpoint for this debugger session.
+		/// </summary>
+		public BreakEventStatus GetBreakEventStatus (BreakEvent be)
+		{
+			if (IsConnected) {
+				BreakEventInfo binfo;
+				lock (breakpoints) {
+					if (breakpoints.TryGetValue (be, out binfo))
+						return binfo.Status;
+				}
+			}
+			return BreakEventStatus.NotBound;
+		}
+
+		/// <summary>
+		/// Returns a status message of a breakpoint for this debugger session.
+		/// </summary>
+		public string GetBreakEventStatusMessage (BreakEvent be)
+		{
+			if (IsConnected) {
+				BreakEventInfo binfo;
+				lock (breakpoints) {
+					if (breakpoints.TryGetValue (be, out binfo)) {
+						if (binfo.StatusMessage != null)
+							return binfo.StatusMessage;
+						switch (binfo.Status) {
+						case BreakEventStatus.BindError: return "The breakpoint could not be bound";
+						case BreakEventStatus.Bound: return "";
+						case BreakEventStatus.Disconnected: return "";
+						case BreakEventStatus.Invalid: return "The breakpoint location is invalid. Perhaps the source line does " +
+							"not contain any statements, or the source does not correspond to the current binary";
+						case BreakEventStatus.NotBound: return "The breakpoint could not yet be bound to a valid location";
+						}
+					}
+				}
+			}
+			return "The breakpoint will not currently be hit";
+		}
+		
+		void AddBreakEvent (BreakEvent be)
+		{
+			try {
+				var eventInfo = OnInsertBreakEvent (be);
+				if (eventInfo == null)
+					throw new InvalidOperationException ("OnInsertBreakEvent can't return a null value. If the breakpoint can't be bound or is invalid, a BreakEventInfo with the corresponding status must be returned");
+				lock (breakpoints) {
+					breakpoints [be] = eventInfo;
+				}
+				eventInfo.AttachSession (this, be);
+			} catch (Exception ex) {
+				string msg;
+				
+				if (be is FunctionBreakpoint)
+					msg = "Could not set breakpoint at location '" + ((FunctionBreakpoint) be).FunctionName + ":" + ((FunctionBreakpoint) be).Line + "'";
+				else if (be is Breakpoint)
+					msg = "Could not set breakpoint at location '" + ((Breakpoint) be).FileName + ":" + ((Breakpoint) be).Line + "'";
+				else
+					msg = "Could not set catchpoint for exception '" + ((Catchpoint) be).ExceptionName + "'";
+				
+				msg += " (" + ex.Message + ")";
+				OnDebuggerOutput (false, msg + "\n");
+				HandleException (ex);
+			}
+		}
+
+		bool RemoveBreakEvent (BreakEvent be)
+		{
+			lock (breakpoints) {
+				BreakEventInfo binfo;
+				if (breakpoints.TryGetValue (be, out binfo)) {
+					try {
+						OnRemoveBreakEvent (binfo);
+					} catch (Exception ex) {
+						if (IsConnected)
+							OnDebuggerOutput (false, ex.Message);
+						HandleException (ex);
+						return false;
+					}
+					breakpoints.Remove (be);
+				}
+				return true;
+			}
+		}
+		
+		void UpdateBreakEventStatus (BreakEvent be)
+		{
+			lock (breakpoints) {
+				BreakEventInfo binfo;
+				if (breakpoints.TryGetValue (be, out binfo)) {
+					try {
+						OnEnableBreakEvent (binfo, be.Enabled);
+					} catch (Exception ex) {
+						if (IsConnected)
+							OnDebuggerOutput (false, ex.Message);
+						HandleException (ex);
+					}
+				}
+			}
+		}
+		
+		void UpdateBreakEvent (BreakEvent be)
+		{
+			lock (breakpoints) {
+				BreakEventInfo binfo;
+				if (breakpoints.TryGetValue (be, out binfo))
+					OnUpdateBreakEvent (binfo);
+			}
+		}
+		
+		void OnBreakpointAdded (object s, BreakEventArgs args)
+		{
+			if (adjustingBreakpoints)
+				return;
+
+			if (IsConnected) {
+				Dispatch (delegate {
+					if (IsConnected)
+						AddBreakEvent (args.BreakEvent);
+				});
+			}
+		}
+		
+		void OnBreakpointRemoved (object s, BreakEventArgs args)
+		{
+			if (adjustingBreakpoints)
+				return;
+
+			if (IsConnected) {
+				Dispatch (delegate {
+					if (IsConnected)
+						RemoveBreakEvent (args.BreakEvent);
+				});
+			}
+		}
+		
+		void OnBreakpointModified (object s, BreakEventArgs args)
+		{
+			if (IsConnected) {
+				Dispatch (delegate {
+					if (IsConnected)
+						UpdateBreakEvent (args.BreakEvent);
+				});
+			}
+		}
+		
+		void OnBreakpointStatusChanged (object s, BreakEventArgs args)
+		{
+			if (IsConnected) {
+				Dispatch (delegate {
+					if (IsConnected)
+						UpdateBreakEventStatus (args.BreakEvent);
+				});
+			}
+		}
+
+		void BreakpointStoreCheckingReadOnly (object sender, ReadOnlyCheckEventArgs e)
+		{
+			e.SetReadOnly (!AllowBreakEventChanges);
+		}
+		
+		/// <summary>
+		/// Gets the debugger options object
+		/// </summary>
+		public DebuggerSessionOptions Options {
+			get { return options; }
+		}
+		
+		/// <summary>
+		/// Gets or sets the evaluation options.
+		/// </summary>
+		public EvaluationOptions EvaluationOptions {
+			get { return options.EvaluationOptions; }
+			set { options.EvaluationOptions = value; }
+		}
+		
+		/// <summary>
+		/// Resumes the execution of the debugger
+		/// </summary>
+		public void Continue ()
+		{
+			lock (slock) {
+				OnRunning ();
+				Dispatch (delegate {
+					try {
+						OnContinue ();
+					} catch (Exception ex) {
+						ForceStop ();
+						if (!HandleException (ex))
+							throw;
+					}
+				});
+			}
+		}
+		
+		/// <summary>
+		/// Pauses the execution of the debugger
+		/// </summary>
+		public void Stop ()
+		{
+			Dispatch (delegate {
+				try {
+					OnStop ();
+				} catch (Exception ex) {
+					if (!HandleException (ex))
+						throw;
+				}
+			});
+		}
+		
+		/// <summary>
+		/// Stops the execution of the debugger by killing the debugged process
+		/// </summary>
+		public void Exit ()
+		{
+			Dispatch (delegate {
+				try {
+					OnExit ();
+				} catch (Exception ex) {
+					if (!HandleException (ex))
+						throw;
+				}
+			});
+		}
+
+		/// <summary>
+		/// Gets a value indicating whether the debuggee is currently connected
+		/// </summary>
+		public bool IsConnected {
+			get; private set;
+		}
+		
+		/// <summary>
+		/// Gets a value indicating whether the debuggee is currently running (not paused by the debugger)
+		/// </summary>
+		public bool IsRunning {
+			get; private set;
+		}
+
+		/// <summary>
+		/// Gets a value indicating whether the debuggee has exited.
+		/// </summary>
+		public bool HasExited {
+			get; protected set;
+		}
+		
+		/// <summary>
+		/// Gets a list of all processes
+		/// </summary>
+		/// <remarks>
+		/// This method can only be used when the debuggee is stopped by the debugger
+		/// </remarks>
+		public ProcessInfo[] GetProcesses ()
+		{
+			lock (slock) {
+				if (currentProcesses == null) {
+					currentProcesses = OnGetProcesses ();
+					foreach (ProcessInfo p in currentProcesses)
+						p.Attach (this);
+				}
+				return currentProcesses;
+			}
+		}
+		
+		/// <summary>
+		/// Gets or sets the output writer callback.
+		/// </summary>
+		/// <remarks>
+		/// This callback is invoked to print debuggee output
+		/// </remarks>
+		public OutputWriterDelegate OutputWriter {
+			get { return outputWriter; }
+			set {
+				lock (olock) {
+					outputWriter = value;
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Gets or sets the log writer.
+		/// </summary>
+		/// <remarks>
+		/// This callback is invoked to print debugger log messages
+		/// </remarks>
+		public OutputWriterDelegate LogWriter {
+			get { return logWriter; }
+			set {
+				lock (olock) {
+					logWriter = value;
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Gets the disassembly of a source code file
+		/// </summary>
+		/// <returns>
+		/// An array of AssemblyLine, with one element for each source code line that could be disassembled
+		/// </returns>
+		/// <param name='file'>
+		/// The file.
+		/// </param>
+		/// <remarks>
+		/// This method can only be used when the debuggee is stopped by the debugger
+		/// </remarks>
+		public AssemblyLine[] DisassembleFile (string file)
+		{
+			lock (slock) {
+				return OnDisassembleFile (file);
+			}
+		}
+		
+		public string ResolveExpression (string expression, string file, int line, int column)
+		{
+			return ResolveExpression (expression, new SourceLocation (null, file, line, column));
+		}
+		
+		public virtual string ResolveExpression (string expression, SourceLocation location)
+		{
+			string key = expression + " " + location;
+			string resolved;
+			if (!resolvedExpressionCache.TryGetValue (key, out resolved)) {
+				try {
+					resolved = OnResolveExpression (expression, location);
+				} catch (Exception ex) {
+					OnDebuggerOutput (true, "Error while resolving expression: " + ex.Message);
+				}
+				resolvedExpressionCache [key] = resolved;
+			}
+			return resolved ?? expression;
+		}
+		
+		/// <summary>
+		/// Stops the execution of background evaluations being done by the debugger
+		/// </summary>
+		/// <remarks>
+		/// This method can only be used when the debuggee is stopped by the debugger
+		/// </remarks>
+		public void CancelAsyncEvaluations ()
+		{
+			if (UseOperationThread) {
+				ThreadPool.QueueUserWorkItem (delegate {
+					OnCancelAsyncEvaluations ();
+				});
+			} else
+				OnCancelAsyncEvaluations ();
+		}
+
+		/// <summary>
+		/// Gets a value indicating whether there are background evaluations being done by the debugger
+		/// which can be cancelled.
+		/// </summary>
+		/// <remarks>
+		/// This method can only be used when the debuggee is stopped by the debugger
+		/// </remarks>
+		public virtual bool CanCancelAsyncEvaluations {
+			get { return false; }
+		}
+		
+		/// <summary>
+		/// Override to stop the execution of background evaluations being done by the debugger
+		/// </summary>
+		protected virtual void OnCancelAsyncEvaluations ()
+		{
+		}
+		
+		readonly Mono.Debugging.Evaluation.ExpressionEvaluator defaultResolver = new Mono.Debugging.Evaluation.NRefactoryExpressionEvaluator ();
+		readonly Dictionary <string, IExpressionEvaluator> evaluators = new Dictionary <string, IExpressionEvaluator> ();
+
+		internal IExpressionEvaluator FindExpressionEvaluator (StackFrame frame)
+		{
+			if (GetExpressionEvaluator == null)
+				return null;
+
+			string fn = frame.SourceLocation == null ? null : frame.SourceLocation.FileName;
+			if (String.IsNullOrEmpty (fn))
+				return null;
+
+			fn = System.IO.Path.GetExtension (fn);
+			IExpressionEvaluator result;
+			if (evaluators.TryGetValue (fn, out result))
+				return result;
+
+			result = GetExpressionEvaluator(fn);
+
+			evaluators[fn] = result;
+
+			return result;
+		}
+
+		public Mono.Debugging.Evaluation.ExpressionEvaluator GetEvaluator (StackFrame frame)
+		{
+			IExpressionEvaluator result = FindExpressionEvaluator (frame);
+			if (result == null)
+				return defaultResolver;
+			return result.Evaluator;
+		}
+		
+		
+		/// <summary>
+		/// Called when an expression needs to be resolved
+		/// </summary>
+		/// <param name='expression'>
+		/// The expression
+		/// </param>
+		/// <param name='location'>
+		/// The source code location
+		/// </param>
+		/// <returns>
+		/// The resolved expression
+		/// </returns>
+		protected virtual string OnResolveExpression (string expression, SourceLocation location)
+		{
+			return defaultResolver.Resolve (this, location, expression);
+		}
+		
+		internal protected string ResolveIdentifierAsType (string identifier, SourceLocation location)
+		{
+			if (TypeResolverHandler != null)
+				return TypeResolverHandler (identifier, location);
+
+			return null;
+		}
+		
+		internal ThreadInfo[] GetThreads (long processId)
+		{
+			lock (slock) {
+				ThreadInfo[] threads = OnGetThreads (processId);
+				foreach (ThreadInfo t in threads)
+					t.Attach (this);
+				return threads;
+			}
+		}
+		
+		internal Backtrace GetBacktrace (long processId, long threadId)
+		{
+			lock (slock) {
+				Backtrace bt = OnGetThreadBacktrace (processId, threadId);
+				if (bt != null)
+					bt.Attach (this);
+				return bt;
+			}
+		}
+		
+		void ForceStop ()
+		{
+			TargetEventArgs args = new TargetEventArgs (TargetEventType.TargetStopped);
+			OnTargetEvent (args);
+		}
+		
+		void ForceExit ()
+		{
+			TargetEventArgs args = new TargetEventArgs (TargetEventType.TargetExited);
+			OnTargetEvent (args);
+		}
+		
+		internal protected void OnTargetEvent (TargetEventArgs args)
+		{
+			currentProcesses = null;
+			
+			if (args.Process != null)
+				args.Process.Attach (this);
+			if (args.Thread != null) {
+				args.Thread.Attach (this);
+				activeThread = args.Thread;
+			}
+			if (args.Backtrace != null)
+				args.Backtrace.Attach (this);
+
+			EventHandler<TargetEventArgs> evnt = null;
+			switch (args.Type) {
+			case TargetEventType.ExceptionThrown:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetExceptionThrown;
+				break;
+			case TargetEventType.TargetExited:
+				lock (slock) {
+					IsRunning = false;
+					IsConnected = false;
+					HasExited = true;
+				}
+				EventHandler handler = TargetExited;
+				if (handler != null)
+					handler (this, args);
+				break;
+			case TargetEventType.TargetHitBreakpoint:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetHitBreakpoint;
+				break;
+			case TargetEventType.TargetInterrupted:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetInterrupted;
+				break;
+			case TargetEventType.TargetSignaled:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetSignaled;
+				break;
+			case TargetEventType.TargetStopped:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetStopped;
+				break;
+			case TargetEventType.UnhandledException:
+				lock (slock) {
+					IsRunning = false;
+					args.IsStopEvent = true;
+				}
+				evnt = TargetUnhandledException;
+				break;
+			case TargetEventType.TargetReady:
+				evnt = TargetReady;
+				break;
+			case TargetEventType.ThreadStarted:
+				evnt = TargetThreadStarted;
+				break;
+			case TargetEventType.ThreadStopped:
+				evnt = TargetThreadStopped;
+				break;
+			}
+
+			if (evnt != null)
+				evnt (this, args);
+
+			EventHandler<TargetEventArgs> targetEvent = TargetEvent;
+			if (targetEvent != null)
+				targetEvent (this, args);
+		}
+		
+		internal void OnRunning ()
+		{
+			IsRunning = true;
+			if (TargetStarted != null)
+				TargetStarted (this, EventArgs.Empty);
+		}
+		
+		internal protected void OnStarted ()
+		{
+			OnStarted (null);
+		}
+		
+		internal protected virtual void OnStarted (ThreadInfo t)
+		{
+			if (HasExited)
+				return;
+
+			OnTargetEvent (new TargetEventArgs (TargetEventType.TargetReady) { Thread = t });
+
+			lock (slock) {
+				if (!HasExited) {
+					IsConnected = true;
+					if (breakpointStore != null) {
+						lock (breakpointStore) {
+							foreach (BreakEvent bp in breakpointStore)
+								AddBreakEvent (bp);
+						}
+					}
+				}
+			}
+		}
+		
+		internal protected void OnTargetOutput (bool isStderr, string text)
+		{
+			lock (olock) {
+				if (outputWriter != null)
+					outputWriter (isStderr, text);
+			}
+		}
+		
+		internal protected void OnDebuggerOutput (bool isStderr, string text)
+		{
+			lock (olock) {
+				if (logWriter != null)
+					logWriter (isStderr, text);
+			}
+		}
+		
+		internal protected void SetBusyState (BusyStateEventArgs args)
+		{
+			if (BusyStateChanged != null)
+				BusyStateChanged (this, args);
+		}
+		
+		/// <summary>
+		/// Tries to bind all unbound breakpoints of a source file
+		/// </summary>
+		/// <param name='fullFilePath'>
+		/// Source file path
+		/// </param>
+		/// <remarks>
+		/// This method can be called by a subclass to ask the debugger session to attempt
+		/// to bind all unbound breakpoints defined on the given file. This method could
+		/// be called, for example, when a new assembly that contains this file is loaded
+		/// into memory. It is not necessary to use this method if the subclass keeps
+		/// track of unbound breakpoints by itself.
+		/// </remarks>
+		internal protected void BindSourceFileBreakpoints (string fullFilePath)
+		{
+			lock (breakpoints) {
+				// Make a copy of the breakpoints table since it can be modified while iterating
+				var breakpointsCopy = new Dictionary<BreakEvent, BreakEventInfo> (breakpoints);
+
+				foreach (KeyValuePair<BreakEvent, BreakEventInfo> bps in breakpointsCopy) {
+					Breakpoint bp = bps.Key as Breakpoint;
+					if (bp != null && bps.Value.Status == BreakEventStatus.NotBound) {
+						StringComparer comparer;
+
+						if (System.IO.Path.DirectorySeparatorChar == '\\')
+							comparer = StringComparer.InvariantCultureIgnoreCase;
+						else
+							comparer = StringComparer.InvariantCulture;
+
+						if (comparer.Compare (System.IO.Path.GetFullPath (bp.FileName), fullFilePath) == 0)
+							RetryEventBind (bps.Value);
+					}
+				}
+			}
+		}
+		
+		void RetryEventBind (BreakEventInfo binfo)
+		{
+			// Try inserting the breakpoint again
+			BreakEvent be = binfo.BreakEvent;
+			try {
+				binfo = OnInsertBreakEvent (be);
+				if (binfo == null)
+					throw new InvalidOperationException ("OnInsertBreakEvent can't return a null value. If the breakpoint can't be bound or is invalid, a BreakEventInfo with the corresponding status must be returned");
+				lock (breakpoints) {
+					breakpoints [be] = binfo;
+				}
+				binfo.AttachSession (this, be);
+			} catch (Exception ex) {
+				Breakpoint bp = be as Breakpoint;
+				if (bp != null)
+					OnDebuggerOutput (false, "Could not set breakpoint at location '" + bp.FileName + ":" + bp.Line + " (" + ex.Message + ")\n");
+				else
+					OnDebuggerOutput (false, "Could not set catchpoint for exception '" + ((Catchpoint)be).ExceptionName + "' (" + ex.Message + ")\n");
+				HandleException (ex);
+			}
+		}
+		
+		/// <summary>
+		/// Unbinds all bound breakpoints of a source file
+		/// </summary>
+		/// <param name='fullFilePath'>
+		/// The source file path
+		/// </param>
+		/// <remarks>
+		/// This method can be called by a subclass to ask the debugger session to
+		/// unbind all bound breakpoints defined on the given file. This method could
+		/// be called, for example, when an assembly that contains this file is unloaded
+		/// from memory. It is not necessary to use this method if the subclass keeps
+		/// track of unbound breakpoints by itself.
+		/// </remarks>
+		internal protected void UnbindSourceFileBreakpoints (string fullFilePath)
+		{
+			var toUpdate = new List<BreakEventInfo> ();
+
+			lock (breakpoints) {
+				// Make a copy of the breakpoints table since it can be modified while iterating
+				var breakpointsCopy = new Dictionary<BreakEvent, BreakEventInfo> (breakpoints);
+
+				foreach (KeyValuePair<BreakEvent, BreakEventInfo> bps in breakpointsCopy) {
+					var bp = bps.Key as Breakpoint;
+					if (bp != null && bps.Value.Status == BreakEventStatus.Bound) {
+						if (System.IO.Path.GetFullPath (bp.FileName) == fullFilePath)
+							toUpdate.Add (bps.Value);
+					}
+				}
+
+				foreach (BreakEventInfo be in toUpdate) {
+					breakpoints.Remove (be.BreakEvent);
+					NotifyBreakEventStatusChanged (be.BreakEvent);
+				}
+			}
+		}
+		
+		internal void NotifyBreakEventStatusChanged (BreakEvent be)
+		{
+			var s = GetBreakEventStatus (be);
+			if (s == BreakEventStatus.BindError || s == BreakEventStatus.Invalid)
+				OnDebuggerOutput (true, GetBreakEventErrorMessage (be) + ": " + GetBreakEventStatusMessage (be) + "\n");
+			Breakpoints.NotifyStatusChanged (be);
+		}
+		
+		static string GetBreakEventErrorMessage (BreakEvent be)
+		{
+			var bp = be as Breakpoint;
+			if (bp != null)
+				return string.Format ("Could not insert breakpoint at '{0}:{1}'", bp.FileName, bp.Line);
+			Catchpoint cp = (Catchpoint) be;
+			return string.Format ("Could not enable catchpoint for exception '{0}'", cp.ExceptionName);
+		}
+		
+		/// <summary>
+		/// Reports an unhandled exception in the debugger
+		/// </summary>
+		/// <returns>
+		/// True if the debugger engine handles the exception. False otherwise.
+		/// </returns>
+		/// <param name='ex'>
+		/// The exception
+		/// </param>
+		/// <remarks>
+		/// This method can be used by subclasses to report errors in the debugger that must be reported
+		/// to the user.
+		/// </remarks>
+		protected virtual bool HandleException (Exception ex)
+		{
+			if (ExceptionHandler != null)
+				return ExceptionHandler (ex);
+
+			return false;
+		}
+		
+		internal void AdjustBreakpointLocation (Breakpoint b, int newLine, int newColumn)
+		{
+			lock (slock) {
+				lock (breakpoints) {
+					try {
+						adjustingBreakpoints = true;
+						Breakpoints.AdjustBreakpointLine (b, newLine, newColumn);
+					} finally {
+						adjustingBreakpoints = false;
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// When set, operations such as OnRun, OnAttachToProcess, OnStepLine, etc, are run in
+		/// a background thread, so it will not block the caller of the corresponding public methods.
+		/// </summary>
+		protected bool UseOperationThread { get; set; }
+		
+		/// <summary>
+		/// Called to start the execution of the debugger
+		/// </summary>
+		/// <param name='startInfo'>
+		/// Startup information
+		/// </param>
+		protected abstract void OnRun (DebuggerStartInfo startInfo);
+		
+		/// <summary>
+		/// Called to attach the debugger to a running process
+		/// </summary>
+		/// <param name='processId'>
+		/// Process identifier.
+		/// </param>
+		protected abstract void OnAttachToProcess (long processId);
+
+		/// <summary>
+		/// Called to detach the debugging session from the running process
+		/// </summary>
+		protected abstract void OnDetach ();
+		
+		/// <summary>
+		/// Called when the active thread has to be changed
+		/// </summary>
+		/// <param name='processId'>
+		/// Process identifier.
+		/// </param>
+		/// <param name='threadId'>
+		/// Thread identifier.
+		/// </param>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnSetActiveThread (long processId, long threadId);
+		
+		/// <summary>
+		/// Called when the debug session has to be paused
+		/// </summary>
+		protected abstract void OnStop ();
+		
+		/// <summary>
+		/// Called when the target process has to be exited
+		/// </summary>
+		protected abstract void OnExit ();
+		
+		
+		/// <summary>
+		/// Called to step one source code line
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnStepLine ();
+
+		/// <summary>
+		/// Called to step one source line, but step over method calls
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnNextLine ();
+
+		/// <summary>
+		/// Called to step one instruction
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnStepInstruction ();
+
+		/// <summary>
+		/// Called to step one instruction, but step over method calls
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnNextInstruction ();
+
+		/// <summary>
+		/// Called to continue execution until leaving the current method
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnFinish ();
+
+		/// <summary>
+		/// Called to resume execution
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract void OnContinue ();
+		
+		//breakpoints etc
+
+		/// <summary>
+		/// Called to insert a new breakpoint or catchpoint
+		/// </summary>
+		/// <param name='breakEvent'>
+		/// The break event.
+		/// </param>
+		/// <remarks>
+		/// Implementations of this method must: (1) create (and return) an instance of BreakEventInfo
+		/// (or a subclass of it). (2) Attempt to activate a breakpoint at the location
+		/// specified in breakEvent. If the breakpoint cannot be activated at the time this
+		/// method is called, it is the responsibility of the DebuggerSession subclass
+		/// to attempt it later on.
+		/// The BreakEventInfo object can be used to change the status of the breakpoint,
+		/// update the hit point, etc.
+		/// </remarks>
+		protected abstract BreakEventInfo OnInsertBreakEvent (BreakEvent breakEvent);
+		
+		/// <summary>
+		/// Called when a breakpoint has been removed.
+		/// </summary>
+		/// <param name='eventInfo'>
+		/// The breakpoint
+		/// </param>
+		/// <remarks>
+		/// Implementations of this method should remove or disable the breakpoint
+		/// in the debugging engine.
+		/// </remarks>
+		protected abstract void OnRemoveBreakEvent (BreakEventInfo eventInfo);
+
+		/// <summary>
+		/// Called when information about a breakpoint has changed
+		/// </summary>
+		/// <param name='eventInfo'>
+		/// The break event
+		/// </param>
+		/// <remarks>
+		/// This method is called when some information about the breakpoint changes.
+		/// Notice that the file and line of a breakpoint or the exception name of
+		/// a catchpoint can't be modified. Changes of the Enabled property are
+		/// notified by calling OnEnableBreakEvent. 
+		/// </remarks>
+		protected abstract void OnUpdateBreakEvent (BreakEventInfo eventInfo);
+		
+		/// <summary>
+		/// Called when a break event is enabled or disabled
+		/// </summary>
+		/// <param name='eventInfo'>
+		/// The break event
+		/// </param>
+		/// <param name='enable'>
+		/// The new status
+		/// </param>
+		protected abstract void OnEnableBreakEvent (BreakEventInfo eventInfo, bool enable);
+		
+		/// <summary>
+		/// Queried when the debugger session has to check if changes in breakpoints are allowed or not
+		/// </summary>
+		/// <value>
+		/// <c>true</c> if break event changes are allowed; otherwise, <c>false</c>.
+		/// </value>
+		/// <remarks>
+		/// This property should return false if at the time it is invoked the debugger engine doesn't support
+		/// adding, removing or doing changes in breakpoints.
+		/// </remarks>
+		protected virtual bool AllowBreakEventChanges { get { return true; } }
+		
+		/// <summary>
+		/// Called to get a list of the threads of a process
+		/// </summary>
+		/// <param name='processId'>
+		/// Process identifier.
+		/// </param>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract ThreadInfo[] OnGetThreads (long processId);
+		
+		/// <summary>
+		/// Called to get a list of all debugee processes
+		/// </summary>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract ProcessInfo[] OnGetProcesses ();
+		
+		/// <summary>
+		/// Called to get the backtrace of a thread
+		/// </summary>
+		/// <param name='processId'>
+		/// Process identifier.
+		/// </param>
+		/// <param name='threadId'>
+		/// Thread identifier.
+		/// </param>
+		/// <remarks>
+		/// This method can only be called when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected abstract Backtrace OnGetThreadBacktrace (long processId, long threadId);
+		
+		/// <summary>
+		/// Called to gets the disassembly of a source code file
+		/// </summary>
+		/// <returns>
+		/// An array of AssemblyLine, with one element for each source code line that could be disassembled
+		/// </returns>
+		/// <param name='file'>
+		/// The file.
+		/// </param>
+		/// <remarks>
+		/// This method can only be used when the debuggee is stopped by the debugger
+		/// </remarks>
+		protected virtual AssemblyLine[] OnDisassembleFile (string file)
+		{
+			return null;
+		}
+
+		internal T WrapDebuggerObject<T> (T obj) where T:class,IDebuggerBackendObject
+		{
+			return obj != null ? OnWrapDebuggerObject (obj) : null;
+		}
+
+		/// <summary>
+		/// Called for every object that is obtained from the debugger engine.
+		/// Subclasses may want to create wrappers for some of those objects
+		/// </summary>
+		protected virtual T OnWrapDebuggerObject<T> (T obj) where T:class,IDebuggerBackendObject
+		{
+			return obj;
+		}
+
+		protected IDebuggerSessionFrontend Frontend {
+			get {
+				return frontend;
+			}
+		}
+	}
+	
+	class InternalDebuggerSession: IDebuggerSessionFrontend
+	{
+		readonly DebuggerSession session;
+		
+		public InternalDebuggerSession (DebuggerSession session)
+		{
+			this.session = session;
+		}
+		
+		public void NotifyTargetEvent (TargetEventArgs args)
+		{
+			session.OnTargetEvent (args);
+		}
+
+		public void NotifyTargetOutput (bool isStderr, string text)
+		{
+			session.OnTargetOutput (isStderr, text);
+		}
+		
+		public void NotifyDebuggerOutput (bool isStderr, string text)
+		{
+			session.OnDebuggerOutput (isStderr, text);
+		}
+		
+		public void NotifyStarted (ThreadInfo t)
+		{
+			session.OnStarted (t);
+		}
+		
+		public void NotifyStarted ()
+		{
+			session.OnStarted ();
+		}
+		
+		public void BindSourceFileBreakpoints (string fullFilePath)
+		{
+			session.BindSourceFileBreakpoints (fullFilePath);
+		}
+
+		public void UnbindSourceFileBreakpoints (string fullFilePath)
+		{
+			session.UnbindSourceFileBreakpoints (fullFilePath);
+		}
+	}
+
+	public delegate void OutputWriterDelegate (bool isStderr, string text);
+
+	public class BusyStateEventArgs: EventArgs
+	{
+		public bool IsBusy { get; internal set; }
+		
+		public string Description { get; internal set; }
+	}
+	
+	public interface IConnectionDialog : IDisposable
+	{
+		event EventHandler UserCancelled;
+		
+		//message may be null in which case the dialog should construct a default
+		void SetMessage (DebuggerStartInfo dsi, string message, bool listening, int attemptNumber);
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerSessionOptions.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerSessionOptions.cs
new file mode 100644
index 0000000..695d009
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerSessionOptions.cs
@@ -0,0 +1,38 @@
+// 
+// DebuggerSessionOptions.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Client
+{
+	[Serializable]
+	public class DebuggerSessionOptions
+	{
+		public EvaluationOptions EvaluationOptions { get; set; }
+		public bool StepOverPropertiesAndOperators { get; set; }
+		public bool ProjectAssembliesOnly { get; set; }
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/DebuggerStartInfo.cs b/Mono.Debugging/Mono.Debugging.Client/DebuggerStartInfo.cs
new file mode 100644
index 0000000..21f6ca1
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/DebuggerStartInfo.cs
@@ -0,0 +1,80 @@
+// DebuggerStartInfo.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class DebuggerStartInfo
+	{
+		string command;
+		string arguments;
+		string workingDirectory;
+		Dictionary<string, string> environmentVariables;
+		
+		public string Command {
+			get {
+				return command;
+			}
+			set {
+				command = value;
+			}
+		}
+
+		public string Arguments {
+			get {
+				return arguments;
+			}
+			set {
+				arguments = value;
+			}
+		}
+
+		public string WorkingDirectory {
+			get {
+				return workingDirectory;
+			}
+			set {
+				workingDirectory = value;
+			}
+		}
+
+		public Dictionary<string, string> EnvironmentVariables {
+			get {
+				if (environmentVariables == null)
+					environmentVariables = new Dictionary<string,string> ();
+				return environmentVariables;
+			}
+		}
+		
+		public bool UseExternalConsole { get; set; }
+		
+		public bool CloseExternalConsoleOnExit { get; set; }
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/EvaluationOptions.cs b/Mono.Debugging/Mono.Debugging.Client/EvaluationOptions.cs
new file mode 100644
index 0000000..04e543d
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/EvaluationOptions.cs
@@ -0,0 +1,117 @@
+// 
+// EvaluationOptions.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Client
+{
+	[Serializable]
+	public class EvaluationOptions
+	{
+		bool allowMethodEvaluation;
+		bool allowToStringCalls;
+		
+		public static readonly char Ellipsis = '…';
+		
+		public static EvaluationOptions DefaultOptions {
+			get {
+				EvaluationOptions ops = new EvaluationOptions ();
+				ops.EvaluationTimeout = 1000;
+				ops.MemberEvaluationTimeout = 5000;
+				ops.AllowTargetInvoke = true;
+				ops.AllowMethodEvaluation = true;
+				ops.AllowToStringCalls = true;
+				ops.FlattenHierarchy = true;
+				ops.GroupPrivateMembers = true;
+				ops.GroupStaticMembers = true;
+				ops.GroupUserPrivateMembers = false;
+				ops.UseExternalTypeResolver = true;
+				ops.IntegerDisplayFormat = IntegerDisplayFormat.Decimal;
+				ops.CurrentExceptionTag = "$exception";
+				ops.EllipsizeStrings = true;
+				ops.EllipsizedLength = 100;
+				ops.ChunkRawStrings = false;
+				return ops;
+			}
+		}
+		
+		public EvaluationOptions Clone ()
+		{
+			return (EvaluationOptions) MemberwiseClone ();
+		}
+		
+		public bool ChunkRawStrings { get; set; }
+		
+		public bool EllipsizeStrings { get; set; }
+		public int EllipsizedLength { get; set; }
+		
+		public int EvaluationTimeout { get; set; }
+		public int MemberEvaluationTimeout { get; set; }
+		public bool AllowTargetInvoke { get; set; }
+		
+		public bool AllowMethodEvaluation {
+			get { return allowMethodEvaluation && AllowTargetInvoke; }
+			set { allowMethodEvaluation = value; }
+		}
+		
+		public bool AllowToStringCalls {
+			get { return allowToStringCalls && AllowTargetInvoke; }
+			set { allowToStringCalls = value; }
+		}
+		
+		public bool AllowDisplayStringEvaluation {
+			get { return AllowTargetInvoke; }
+		}
+		
+		public bool AllowDebuggerProxy {
+			get { return AllowTargetInvoke; }
+		}
+		
+		public bool FlattenHierarchy { get; set; }
+		
+		public bool GroupPrivateMembers { get; set; }
+
+		[Obsolete ("I don't see a point in even having this property")]
+		public bool GroupUserPrivateMembers { get; set; }
+		
+		public bool GroupStaticMembers { get; set; }
+		
+		public bool UseExternalTypeResolver { get; set; }
+
+		[Obsolete ("Use the type's BeforeFieldInit attribute instead")]
+		public bool AllowImplicitTypeLoading { get { return true; } set { } }
+		
+		public IntegerDisplayFormat IntegerDisplayFormat { get; set; }
+		
+		public string CurrentExceptionTag { get; set; }
+	}
+	
+	public enum IntegerDisplayFormat
+	{
+		Decimal,
+		Hexadecimal
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ExceptionInfo.cs b/Mono.Debugging/Mono.Debugging.Client/ExceptionInfo.cs
new file mode 100644
index 0000000..6745dfc
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ExceptionInfo.cs
@@ -0,0 +1,254 @@
+// 
+// ExceptionInfo.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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.Text;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class ExceptionInfo
+	{
+		ObjectValue exception;
+		ObjectValue messageObject;
+
+		[NonSerialized]
+		ExceptionStackFrame[] frames;
+		
+		[NonSerialized]
+		ExceptionInfo innerException;
+		
+		/// <summary>
+		/// The provided value can have the following members:
+		/// Type of the object: type of the exception
+		/// Message: Message of the exception
+		/// Instance: Raw instance of the exception
+		/// StackTrace: an array of frames. Each frame must have:
+		///     Value of the object: display text of the frame
+		///     File: name of the file
+		///     Line: line
+		///     Col: column
+		/// InnerException: inner exception, following the same format described above.
+		/// </summary>
+		public ExceptionInfo (ObjectValue exception)
+		{
+			this.exception = exception;
+			if (exception.IsEvaluating || exception.IsEvaluatingGroup)
+				exception.ValueChanged += HandleExceptionValueChanged;
+		}
+
+		void LoadMessage ()
+		{
+			if (messageObject == null) {
+				messageObject = exception.GetChild ("Message");
+				if (messageObject != null && messageObject.IsEvaluating)
+					messageObject.ValueChanged += HandleMessageValueChanged;
+			}
+		}
+
+		void HandleMessageValueChanged (object sender, EventArgs e)
+		{
+			frames = null;
+			NotifyChanged ();
+		}
+
+		void HandleExceptionValueChanged (object sender, EventArgs e)
+		{
+			frames = null;
+			if (exception.IsEvaluatingGroup)
+				exception = exception.GetArrayItem (0);
+			LoadMessage ();
+			NotifyChanged ();
+		}
+
+		void NotifyChanged ()
+		{
+			EventHandler evnt = Changed;
+			if (evnt != null)
+				evnt (this, EventArgs.Empty);
+		}
+		
+		public string Type {
+			get { return exception.TypeName; }
+		}
+
+		public string Message {
+			get {
+				LoadMessage ();
+				if (messageObject != null && messageObject.IsEvaluating)
+					return "Loading...";
+				return messageObject != null ? messageObject.Value : null;
+			}
+		}
+
+		public ObjectValue Instance {
+			get {
+				return exception.GetChild ("Instance");
+			}
+		}
+		
+		public bool IsEvaluating {
+			get { return exception.IsEvaluating || exception.IsEvaluatingGroup; }
+		}
+
+		public bool StackIsEvaluating {
+			get {
+				ObjectValue stackTrace = exception.GetChild ("StackTrace");
+				if (stackTrace != null)
+					return stackTrace.IsEvaluating;
+				else
+					return false;
+			}
+		}
+
+		public ExceptionStackFrame[] StackTrace {
+			get {
+				if (frames != null)
+					return frames;
+				
+				ObjectValue stackTrace = exception.GetChild ("StackTrace");
+				if (stackTrace == null)
+					return frames = new ExceptionStackFrame [0];
+				
+				if (stackTrace.IsEvaluating) {
+					frames = new ExceptionStackFrame [0];
+					stackTrace.ValueChanged += HandleExceptionValueChanged;
+					return frames;
+				}
+				List<ExceptionStackFrame> list = new List<ExceptionStackFrame> ();
+				foreach (ObjectValue val in stackTrace.GetAllChildren ())
+					list.Add (new ExceptionStackFrame (val));
+				frames = list.ToArray ();
+				return frames;
+			}
+		}
+		
+		public ExceptionInfo InnerException {
+			get {
+				if (innerException == null) {
+					ObjectValue innerVal = exception.GetChild ("InnerException");
+					if (innerVal == null || innerVal.IsError || innerVal.IsUnknown)
+						return null;
+					if (innerVal.IsEvaluating) {
+						innerVal.ValueChanged += delegate { NotifyChanged (); };
+						return null;
+					}
+					innerException = new ExceptionInfo (innerVal);
+					innerException.Changed += delegate {
+						NotifyChanged ();
+					};
+				}
+				return innerException;
+			}
+		}
+		
+		public event EventHandler Changed;
+		
+		internal void ConnectCallback (StackFrame parentFrame)
+		{
+			ObjectValue.ConnectCallbacks (parentFrame, exception);
+		}
+
+		public override string ToString ()
+		{
+			StringBuilder sb = new StringBuilder ();
+			var chain = new List<ExceptionInfo> ();
+			ExceptionInfo e = this;
+			while (e != null) {
+				chain.Insert (0, e);
+				if (sb.Length > 0)
+					sb.Append (" ---> ");
+				sb.Append (e.Type).Append (": ").Append (e.Message);
+				e = e.InnerException;
+			}
+			sb.AppendLine ();
+			foreach (var ex in chain) {
+				if (ex != chain[0])
+					sb.AppendLine ("  --- End of inner exception stack trace ---");
+				foreach (var f in ex.StackTrace) {
+					sb.Append ("  at ").Append (f.DisplayText);
+					if (!string.IsNullOrEmpty (f.File))
+						sb.Append (" in ").Append (f.File).Append (":").Append (f.Line);
+					sb.AppendLine ();
+				}
+			}
+			return sb.ToString ();
+		}
+	}
+	
+	public class ExceptionStackFrame
+	{
+		ObjectValue frame;
+		
+		/// <summary>
+		/// The provided value must have a specific structure.
+		/// The Value property is the display text.
+		/// A child "File" member must be the name of the file.
+		/// A child "Line" member must be the line.
+		/// A child "Col" member must be the column.
+		/// </summary>
+		public ExceptionStackFrame (ObjectValue value)
+		{
+			frame = value;
+		}
+
+		public string File {
+			get {
+				ObjectValue file = frame.GetChild ("File");
+				if (file != null)
+					return file.Value;
+
+				return null;
+			}
+		}
+
+		public int Line {
+			get {
+				ObjectValue val = frame.GetChild ("Line");
+				if (val != null)
+					return int.Parse (val.Value);
+
+				return 0;
+			}
+		}
+
+		public int Column {
+			get {
+				ObjectValue val = frame.GetChild ("Column");
+				if (val != null)
+					return int.Parse (val.Value);
+
+				return 0;
+			}
+		}
+
+		public string DisplayText {
+			get { return frame.Value; }
+		}
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Client/FunctionBreakpoint.cs b/Mono.Debugging/Mono.Debugging.Client/FunctionBreakpoint.cs
new file mode 100644
index 0000000..58a0127
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/FunctionBreakpoint.cs
@@ -0,0 +1,189 @@
+// 
+// FunctionBreakpoint.cs
+//  
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2012 Xamarin Inc.
+// 
+// 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.Xml;
+using System.Collections.Generic;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class FunctionBreakpoint : Breakpoint
+	{
+		public FunctionBreakpoint (string functionName, string language) : base (null, 1, 1)
+		{
+			FunctionName = functionName;
+			Language = language;
+		}
+
+		static bool SkipArrayRank (string text, ref int index, int endIndex)
+		{
+			char c;
+
+			while (index < endIndex) {
+				if ((c = text[index++]) == ']')
+					return true;
+
+				if (c != ',' && !char.IsWhiteSpace (c) && !char.IsDigit (c))
+					return false;
+			}
+
+			return false;
+		}
+
+		static bool SkipGenericArgs (string text, ref int index, int endIndex)
+		{
+			char c;
+
+			while (index < endIndex) {
+				if ((c = text[index++]) == '>')
+					return true;
+
+				if (c == '<') {
+					if (!SkipGenericArgs (text, ref index, endIndex))
+						return false;
+
+					while (index < endIndex && !char.IsWhiteSpace (text[index]))
+						index++;
+
+					// the only chars allowed after a '>' are: '>', '[', and ','
+					if (">[,".IndexOf (text[index]) == -1)
+						return false;
+				} else if (c == '[') {
+					if (!SkipArrayRank (text, ref index, endIndex))
+						return false;
+
+					while (index < endIndex && !char.IsWhiteSpace (text[index]))
+						index++;
+
+					// the only chars allowed after a ']' are: '>', '[', and ','
+					if (">[,".IndexOf (text[index]) == -1)
+						return false;
+				} else if (c != '.' && c != '+' && c != ',' && !char.IsWhiteSpace (c) && !char.IsLetterOrDigit (c)) {
+					return false;
+				}
+			}
+
+			return false;
+		}
+
+		public static bool TryParseParameters (string text, int startIndex, int endIndex, out string[] paramTypes)
+		{
+			List<string> parsedParamTypes = new List<string> ();
+			int index = startIndex;
+			int start;
+			char c;
+
+			paramTypes = null;
+
+			while (index < endIndex) {
+				while (char.IsWhiteSpace (text[index]))
+					index++;
+
+				start = index;
+				while (index < endIndex) {
+					if ((c = text[index]) == ',')
+						break;
+
+					index++;
+
+					if (c == '<') {
+						if (!SkipGenericArgs (text, ref index, endIndex))
+							return false;
+					} else if (c == '[') {
+						if (!SkipArrayRank (text, ref index, endIndex))
+							return false;
+					}
+				}
+
+				parsedParamTypes.Add (text.Substring (start, index - start).TrimEnd ());
+
+				if (index < endIndex)
+					index++;
+			}
+
+			paramTypes = parsedParamTypes.ToArray ();
+
+			return true;
+		}
+		
+		internal FunctionBreakpoint (XmlElement elem) : base (elem)
+		{
+			FunctionName = elem.GetAttribute ("function");
+			
+			string text = elem.GetAttribute ("language");
+			if (string.IsNullOrEmpty (text))
+				Language = "C#";
+			else
+				Language = text;
+
+			if (elem.HasAttribute ("params")) {
+				string[] paramTypes;
+
+				text = elem.GetAttribute ("params").Trim ();
+				if (text.Length > 0 && TryParseParameters (text, 0, text.Length, out paramTypes))
+					ParamTypes = paramTypes;
+				else
+					ParamTypes = new string[0];
+			}
+
+			FileName = null;
+		}
+		
+		internal override XmlElement ToXml (XmlDocument doc)
+		{
+			XmlElement elem = base.ToXml (doc);
+			
+			elem.SetAttribute ("function", FunctionName);
+			elem.SetAttribute ("language", Language);
+			
+			if (ParamTypes != null)
+				elem.SetAttribute ("params", string.Join (", ", ParamTypes));
+			
+			return elem;
+		}
+		
+		public string FunctionName {
+			get; set;
+		}
+		
+		public string Language {
+			get; set;
+		}
+		
+		public string[] ParamTypes {
+			get; set;
+		}
+		
+		public override void CopyFrom (BreakEvent ev)
+		{
+			base.CopyFrom (ev);
+			
+			FunctionBreakpoint bp = (FunctionBreakpoint) ev;
+			FunctionName = bp.FunctionName;
+			ParamTypes = bp.ParamTypes;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/IExpressionEvaluator.cs b/Mono.Debugging/Mono.Debugging.Client/IExpressionEvaluator.cs
new file mode 100644
index 0000000..f88cf68
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/IExpressionEvaluator.cs
@@ -0,0 +1,38 @@
+// 
+// IExpressionEvaluator.cs
+//  
+// Author:
+//	   Carlo kok  <ck at remobjects.com>
+// 
+// Copyright (c) 2010 RemObjects Software
+// 
+// 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 Mono.Debugging.Evaluation;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Client
+{
+	public interface IExpressionEvaluator
+	{
+		ExpressionEvaluator Evaluator { get; }
+		ObjectValue[] GetLocals (StackFrame sf);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ObjectPath.cs b/Mono.Debugging/Mono.Debugging.Client/ObjectPath.cs
new file mode 100644
index 0000000..e9784f4
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ObjectPath.cs
@@ -0,0 +1,101 @@
+// ObjectPath.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public struct ObjectPath
+	{
+		string[] path;
+		
+		public ObjectPath (params string[] path)
+		{
+			this.path = path;
+		}
+		
+		public string this [int n] {
+			get {
+				if (path == null)
+					throw new IndexOutOfRangeException ();
+				return path [n]; 
+			}
+		}
+		
+		public int Length {
+			get { return path != null ? path.Length : 0; }
+		}
+		
+		public IEnumerable GetEnumerator ()
+		{
+			if (path != null)
+				return path;
+			else
+				return new string [0];
+		}
+		
+		public ObjectPath GetSubpath (int start)
+		{
+			if (start == 0)
+				return this;
+			else {
+				string[] newPath = new string [path.Length - start];
+				Array.Copy (path, start, newPath, 0, newPath.Length);
+				return new ObjectPath (newPath);
+			}
+		}
+		
+		public ObjectPath Append (string name)
+		{
+			string[] newPath = new string [path.Length + 1];
+			Array.Copy (path, newPath, path.Length);
+			newPath [path.Length] = name;
+			return new ObjectPath (newPath);
+		}
+		
+		public string LastName {
+			get {
+				if (Length == 0)
+					return "";
+				else
+					return path [path.Length - 1];
+			}
+		}
+		
+		public string Join (string separator)
+		{
+			return string.Join (separator, path);
+		}
+		
+		public override string ToString ()
+		{
+			return Join ("/");
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ObjectValue.cs b/Mono.Debugging/Mono.Debugging.Client/ObjectValue.cs
new file mode 100644
index 0000000..0885869
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ObjectValue.cs
@@ -0,0 +1,787 @@
+// ObjectValue.cs
+//
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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.Text;
+using Mono.Debugging.Backend;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class ObjectValue
+	{
+		ObjectPath path;
+		int arrayCount = -1;
+		bool isNull;
+		string name;
+		string value;
+		string typeName;
+		string displayValue;
+		string childSelector;
+		ObjectValueFlags flags;
+		IObjectValueSource source;
+		IObjectValueUpdater updater;
+		List<ObjectValue> children;
+		ManualResetEvent evaluatedEvent;
+
+		[NonSerialized]
+		UpdateCallback updateCallback;
+		
+		[NonSerialized]
+		EventHandler valueChanged;
+		
+		[NonSerialized]
+		StackFrame parentFrame;
+		
+		static ObjectValue Create (IObjectValueSource source, ObjectPath path, string typeName)
+		{
+			ObjectValue ob = new ObjectValue ();
+			ob.source = source;
+			ob.path = path;
+			ob.typeName = typeName;
+			return ob;
+		}
+		
+		public static ObjectValue CreateObject (IObjectValueSource source, ObjectPath path, string typeName, string value, ObjectValueFlags flags, ObjectValue[] children)
+		{
+			return CreateObject (source, path, typeName, new EvaluationResult (value), flags, children);
+		}
+		
+		public static ObjectValue CreateObject (IObjectValueSource source, ObjectPath path, string typeName, EvaluationResult value, ObjectValueFlags flags, ObjectValue[] children)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.path = path;
+			ob.flags = flags | ObjectValueFlags.Object;
+			ob.value = value.Value;
+			ob.displayValue = value.DisplayValue;
+			if (children != null) {
+				ob.children = new List<ObjectValue> ();
+				ob.children.AddRange (children);
+			}
+			return ob;
+		}
+		
+		public static ObjectValue CreateNullObject (IObjectValueSource source, string name, string typeName, ObjectValueFlags flags)
+		{
+			return CreateNullObject (source, new ObjectPath (name), typeName, flags);
+		}
+		
+		public static ObjectValue CreateNullObject (IObjectValueSource source, ObjectPath path, string typeName, ObjectValueFlags flags)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.flags = flags | ObjectValueFlags.Object;
+			ob.value = "(null)";
+			ob.isNull = true;
+			return ob;
+		}
+		
+		public static ObjectValue CreatePrimitive (IObjectValueSource source, ObjectPath path, string typeName, EvaluationResult value, ObjectValueFlags flags)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.flags = flags | ObjectValueFlags.Primitive;
+			ob.value = value.Value;
+			ob.displayValue = value.DisplayValue;
+			return ob;
+		}
+		
+		public static ObjectValue CreateArray (IObjectValueSource source, ObjectPath path, string typeName, int arrayCount, ObjectValueFlags flags, ObjectValue[] children)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.arrayCount = arrayCount;
+			ob.flags = flags | ObjectValueFlags.Array;
+			ob.value = "[" + arrayCount + "]";
+			if (children != null && children.Length > 0) {
+				ob.children = new List<ObjectValue> ();
+				ob.children.AddRange (children);
+			}
+			return ob;
+		}
+		
+		public static ObjectValue CreateUnknown (IObjectValueSource source, ObjectPath path, string typeName)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.flags = ObjectValueFlags.Unknown | ObjectValueFlags.ReadOnly;
+			return ob;
+		}
+		
+		public static ObjectValue CreateUnknown (string name)
+		{
+			return CreateUnknown (null, new ObjectPath (name), "");
+		}
+		
+		public static ObjectValue CreateError (IObjectValueSource source, ObjectPath path, string typeName, string value, ObjectValueFlags flags)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.flags = flags | ObjectValueFlags.Error;
+			ob.value = value;
+			return ob;
+		}
+		
+		public static ObjectValue CreateImplicitNotSupported (IObjectValueSource source, ObjectPath path, string typeName, ObjectValueFlags flags)
+		{
+			return CreateNotSupported (source, path, typeName, "Implicit evaluation is disabled", flags);
+		}
+		
+		public static ObjectValue CreateNotSupported (IObjectValueSource source, ObjectPath path, string typeName, string message, ObjectValueFlags flags)
+		{
+			ObjectValue ob = Create (source, path, typeName);
+			ob.flags = flags | ObjectValueFlags.NotSupported;
+			ob.value = message;
+			return ob;
+		}
+		
+		public static ObjectValue CreateFatalError (string name, string message, ObjectValueFlags flags)
+		{
+			ObjectValue ob = new ObjectValue ();
+			ob.flags = flags | ObjectValueFlags.Error;
+			ob.value = message;
+			ob.name = name;
+			return ob;
+		}
+		
+		public static ObjectValue CreateEvaluating (IObjectValueUpdater updater, ObjectPath path, ObjectValueFlags flags)
+		{
+			ObjectValue ob = Create (null, path, null);
+			ob.updater = updater;
+			ob.path = path;
+			ob.flags = flags | ObjectValueFlags.Evaluating;
+			return ob;
+		}
+		
+		/// <summary>
+		/// Gets the flags of the value
+		/// </summary>
+		public ObjectValueFlags Flags {
+			get { return flags; }
+		}
+
+		/// <summary>
+		/// Name of the value (for example, the property name)
+		/// </summary>
+		public string Name {
+			get {
+				if (name == null)
+					return path [path.Length - 1];
+
+				return name;
+			}
+			set {
+				name = value;
+			}
+		}
+
+		/// <summary>
+		/// Gets or sets the value of the object
+		/// </summary>
+		/// <value>
+		/// The value.
+		/// </value>
+		/// <exception cref='InvalidOperationException'>
+		/// Is thrown when trying to set a value on a read-only ObjectValue
+		/// </exception>
+		/// <remarks>
+		/// This value is a string representation of the ObjectValue. The content depends on several evaluation
+		/// options. For example, if ToString calls are enabled, this value will be the result of calling
+		/// ToString.
+		/// If the object is a primitive type, in general the Value will be an expression that represents the
+		/// value in the target language. For example, when debugging C#, if the property is an string, the value
+		/// will include the quotation marks and chars like '\' will be properly escaped.
+		/// If you need to get the real CLR value of the object, use GetRawValue.
+		/// </remarks>
+		public virtual string Value {
+			get {
+				return value;
+			}
+			set {
+				if (IsReadOnly || source == null)
+					throw new InvalidOperationException ("Value is not editable");
+				EvaluationResult res = source.SetValue (path, value, null);
+				if (res != null) {
+					this.value = res.Value;
+					displayValue = res.DisplayValue;
+					isNull = value == null;
+				}
+			}
+		}
+
+		/// <summary>
+		/// Gets or sets the display value of this object
+		/// </summary>
+		/// <remarks>
+		/// This method returns a string to be used when showing the value of this object.
+		/// In most cases, the Value and DisplayValue properties return the same text, but there are some cases
+		/// in which DisplayValue may return a more convenient textual representation of the value, which
+		/// may not be a valid target language expression.
+		/// For example in C#, an enum Value includes the full enum type name (e.g. "Gtk.ResponseType.OK"),
+		/// while DisplayValue only has the enum value name ("OK").
+		/// </remarks>
+		public string DisplayValue {
+			get { return displayValue ?? Value; }
+			set { displayValue = value; }
+		}
+		
+		/// <summary>
+		/// Sets the value of this object, using the default evaluation options
+		/// </summary>
+		public void SetValue (string value)
+		{
+			SetValue (value, parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Sets the value of this object, using the specified evaluation options
+		/// </summary>
+		/// <param name='value'>
+		/// The value
+		/// </param>
+		/// <param name='options'>
+		/// The options
+		/// </param>
+		/// <exception cref='InvalidOperationException'>
+		/// Is thrown if the value is read-only
+		/// </exception>
+		public void SetValue (string value, EvaluationOptions options)
+		{
+			if (IsReadOnly || source == null)
+				throw new InvalidOperationException ("Value is not editable");
+			EvaluationResult res = source.SetValue (path, value, options);
+			if (res != null) {
+				this.value = res.Value;
+				displayValue = res.DisplayValue;
+			}
+		}
+		
+		/// <summary>
+		/// Gets the raw value of this object
+		/// </summary>
+		/// <returns>
+		/// The raw value.
+		/// </returns>
+		/// <remarks>
+		/// This method can be used to get the CLR value of the object. For example, if this ObjectValue is
+		/// a property of type String, this method will return the System.String value of the property.
+		/// If this ObjectValue refers to an object instead of a primitive value, then a RawValue object
+		/// will be returned. RawValue can be used to get and set members of an object, and to call methods.
+		/// If this ObjectValue refers to an array, then a RawValueArray object will be returned.
+		/// </remarks>
+		public object GetRawValue ()
+		{
+			EvaluationOptions ops = parentFrame.DebuggerSession.EvaluationOptions.Clone ();
+			ops.EllipsizeStrings = false;
+			
+			return GetRawValue (ops);
+		}
+		
+		/// <summary>
+		/// Gets the raw value of this object
+		/// </summary>
+		/// <param name='options'>
+		/// The evaluation options
+		/// </param>
+		/// <returns>
+		/// The raw value.
+		/// </returns>
+		/// <remarks>
+		/// This method can be used to get the CLR value of the object. For example, if this ObjectValue is
+		/// a property of type String, this method will return the System.String value of the property.
+		/// If this ObjectValue refers to an object instead of a primitive value, then a RawValue object
+		/// will be returned. RawValue can be used to get and set members of an object, and to call methods.
+		/// If this ObjectValue refers to an array, then a RawValueArray object will be returned.
+		/// </remarks>
+		public object GetRawValue (EvaluationOptions options)
+		{
+			object res = source.GetRawValue (path, options);
+			IRawObject val = res as IRawObject;
+			if (val != null)
+				val.Connect (parentFrame.DebuggerSession, options);
+			return res;
+		}
+		
+		/// <summary>
+		/// Sets the raw value of this object
+		/// </summary>
+		/// <param name='value'>
+		/// The value
+		/// </param>
+		/// <remarks>
+		/// The provided value can be a primitive type, a RawValue object or a RawValueArray object.
+		/// </remarks>
+		public void SetRawValue (object value)
+		{
+			SetRawValue (value, parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Sets the raw value of this object
+		/// </summary>
+		/// <param name='value'>
+		/// The value
+		/// </param>
+		/// <param name='options'>
+		/// The evaluation options
+		/// </param>
+		/// <remarks>
+		/// The provided value can be a primitive type, a RawValue object or a RawValueArray object.
+		/// </remarks>
+		public void SetRawValue (object value, EvaluationOptions options)
+		{
+			source.SetRawValue (path, value, options);
+		}
+		
+		/// <summary>
+		/// Full name of the type of the object
+		/// </summary>
+		public string TypeName {
+			get { return typeName; }
+			set { typeName = value; }
+		}
+		
+		/// <summary>
+		/// Gets or sets the child selector.
+		/// </summary>
+		/// <remarks>
+		/// The child selector is an expression which can be concatenated to a parent expression to get this child.
+		/// For example, if this object is a reference to a field named 'foo' of an object, the child
+		/// selector is '.foo'.
+		/// </remarks>
+		public string ChildSelector {
+			get {
+				if (childSelector != null)
+					return childSelector;
+
+				if ((flags & ObjectValueFlags.ArrayElement) != 0)
+					return Name;
+
+				return "." + Name;
+			}
+			set { childSelector = value; }
+		}
+		
+		/// <summary>
+		/// Gets a value indicating whether this object has children.
+		/// </summary>
+		/// <value>
+		/// <c>true</c> if this instance has children; otherwise, <c>false</c>.
+		/// </value>
+		public bool HasChildren {
+			get {
+				if (isNull)
+					return false;
+				if (IsEvaluating)
+					return false;
+				if (children != null)
+					return children.Count > 0;
+				if (source == null)
+					return false;
+				if (IsArray)
+					return arrayCount > 0;
+				if (IsObject)
+					return true;
+				return false;
+			}
+		}
+
+		/// <summary>
+		/// Gets a child value
+		/// </summary>
+		/// <returns>
+		/// The child.
+		/// </returns>
+		/// <param name='name'>
+		/// Name of the member
+		/// </param>
+		/// <remarks>
+		/// This method can be used to get a member of an object (such as a field or property)
+		/// </remarks>
+		public ObjectValue GetChild (string name)
+		{
+			return GetChild (name, parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Gets a child value
+		/// </summary>
+		/// <returns>
+		/// The child.
+		/// </returns>
+		/// <param name='name'>
+		/// Name of the member
+		/// </param>
+		/// <param name='options'>
+		/// Options to be used to evaluate the child
+		/// </param>
+		/// <remarks>
+		/// This method can be used to get a member of an object (such as a field or property)
+		/// </remarks>
+		public ObjectValue GetChild (string name, EvaluationOptions options)
+		{
+			if (IsArray)
+				throw new InvalidOperationException ("Object is an array.");
+			if (IsEvaluating)
+				return null;
+			
+			if (children == null) {
+				children = new List<ObjectValue> ();
+				if (source != null) {
+					try {
+						ObjectValue[] cs = source.GetChildren (path, -1, -1, options);
+						ConnectCallbacks (parentFrame, cs);
+						children.AddRange (cs);
+					} catch (Exception ex) {
+						children = null;
+						return CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly);
+					}
+				}
+			}
+			
+			foreach (ObjectValue ob in children) {
+				if (ob.Name == name)
+					return ob;
+			}
+			
+			return null;
+		}
+		
+		/// <summary>
+		/// Gets all children of the object
+		/// </summary>
+		/// <returns>
+		/// An array of all child values
+		/// </returns>
+		public ObjectValue[] GetAllChildren ()
+		{
+			return GetAllChildren (parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Gets all children of the object
+		/// </summary>
+		/// <returns>
+		/// An array of all child values
+		/// </returns>
+		/// <param name='options'>
+		/// Options to be used to evaluate the children
+		/// </param>
+		public ObjectValue[] GetAllChildren (EvaluationOptions options)
+		{
+			if (IsEvaluating)
+				return new ObjectValue[0];
+			
+			if (IsArray) {
+				GetArrayItem (arrayCount - 1);
+				return children.ToArray ();
+			}
+
+			if (children == null) {
+				children = new List<ObjectValue> ();
+				if (source != null) {
+					try {
+						ObjectValue[] cs = source.GetChildren (path, -1, -1, options);
+						ConnectCallbacks (parentFrame, cs);
+						children.AddRange (cs);
+					} catch (Exception ex) {
+						if (parentFrame != null)
+							parentFrame.DebuggerSession.OnDebuggerOutput (true, ex.ToString ());
+						children.Add (CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly));
+					}
+				}
+			}
+
+			return children.ToArray ();
+		}
+		
+		/// <summary>
+		/// Gets an item of an array
+		/// </summary>
+		/// <returns>
+		/// The array item.
+		/// </returns>
+		/// <param name='index'>
+		/// Item index
+		/// </param>
+		/// <exception cref='InvalidOperationException'>
+		/// Is thrown if this object is not an array (IsArray returns false)
+		/// </exception>
+		public ObjectValue GetArrayItem (int index)
+		{
+			return GetArrayItem (index, parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Gets an item of an array
+		/// </summary>
+		/// <returns>
+		/// The array item.
+		/// </returns>
+		/// <param name='index'>
+		/// Item index
+		/// </param>
+		/// <param name='options'>
+		/// Options to be used to evaluate the item
+		/// </param>
+		/// <exception cref='InvalidOperationException'>
+		/// Is thrown if this object is not an array (IsArray returns false)
+		/// </exception>
+		public ObjectValue GetArrayItem (int index, EvaluationOptions options)
+		{
+			if (!IsArray)
+				throw new InvalidOperationException ("Object is not an array.");
+			if (index >= arrayCount || index < 0 || IsEvaluating)
+				throw new IndexOutOfRangeException ();
+			
+			if (children == null)
+				children = new List<ObjectValue> ();
+			if (index >= children.Count) {
+				int nc = (index + 50);
+				if (nc > arrayCount) nc = arrayCount;
+				nc = nc - children.Count;
+				try {
+					ObjectValue[] items = source.GetChildren (path, children.Count, nc, options);
+					ConnectCallbacks (parentFrame, items);
+					children.AddRange (items);
+				} catch (Exception ex) {
+					return CreateFatalError ("", ex.Message, ObjectValueFlags.ArrayElement | ObjectValueFlags.ReadOnly);
+				}
+			}
+			return children [index];
+		}
+		
+		/// <summary>
+		/// Gets the number of items of an array
+		/// </summary>
+		/// <exception cref='InvalidOperationException'>
+		/// Is thrown if this object is not an array (IsArray returns false)
+		/// </exception>
+		public int ArrayCount {
+			get {
+				if (!IsArray)
+					throw new InvalidOperationException ("Object is not an array.");
+				if (IsEvaluating)
+					return 0;
+				return arrayCount; 
+			}
+		}
+
+		public bool IsReadOnly {
+			get { return HasFlag (ObjectValueFlags.ReadOnly); }
+		}
+		
+		public bool IsArray {
+			get { return HasFlag (ObjectValueFlags.Array); }
+		}
+		
+		public bool IsObject {
+			get { return HasFlag (ObjectValueFlags.Object); }
+		}
+		
+		public bool IsPrimitive {
+			get { return HasFlag (ObjectValueFlags.Primitive); }
+		}
+		
+		public bool IsUnknown {
+			get { return HasFlag (ObjectValueFlags.Unknown); }
+		}
+		
+		public bool IsNotSupported {
+			get { return HasFlag (ObjectValueFlags.NotSupported); }
+		}
+		
+		public bool IsError {
+			get { return HasFlag (ObjectValueFlags.Error); }
+		}
+		
+		public bool IsEvaluating {
+			get { return HasFlag (ObjectValueFlags.Evaluating); }
+		}
+		
+		public bool IsEvaluatingGroup {
+			get { return HasFlag (ObjectValueFlags.EvaluatingGroup); }
+		}
+		
+		public bool CanRefresh {
+			get { return source != null && !HasFlag (ObjectValueFlags.NoRefresh); }
+		}
+		
+		public bool HasFlag (ObjectValueFlags flag)
+		{
+			return (flags & flag) != 0;
+		}
+
+		public event EventHandler ValueChanged {
+			add {
+				lock (this) {
+					if (IsEvaluating)
+						valueChanged += value;
+					else
+						value (this, EventArgs.Empty);
+				}
+			}
+			remove {
+				lock (this) {
+					valueChanged -= value;
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Refreshes the value of this object
+		/// </summary>
+		/// <remarks>
+		/// This method can be called to get a more up-to-date value for this object.
+		/// </remarks>
+		public void Refresh ()
+		{
+			Refresh (parentFrame.DebuggerSession.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Refreshes the value of this object
+		/// </summary>
+		/// <remarks>
+		/// This method can be called to get a more up-to-date value for this object.
+		/// </remarks>
+		public void Refresh (EvaluationOptions options)
+		{
+			if (!CanRefresh)
+				return;
+			ObjectValue val = source.GetValue (path, options);
+			UpdateFrom (val, false);
+		}
+
+		/// <summary>
+		/// Gets a wait handle which can be used to wait for the evaluation of this object to end
+		/// </summary>
+		/// <value>
+		/// The wait handle.
+		/// </value>
+		public WaitHandle WaitHandle {
+			get {
+				lock (this) {
+					if (evaluatedEvent == null)
+						evaluatedEvent = new ManualResetEvent (!IsEvaluating);
+					return evaluatedEvent;
+				}
+			}
+		}
+
+		internal IObjectValueUpdater Updater {
+			get { return updater; }
+		}
+
+		internal void UpdateFrom (ObjectValue val, bool notify)
+		{
+			lock (this) {
+				arrayCount = val.arrayCount;
+				if (val.name != null)
+					name = val.name;
+				value = val.value;
+				displayValue = val.displayValue;
+				typeName = val.typeName;
+				flags = val.flags;
+				source = val.source;
+				children = val.children;
+				path = val.path;
+				updater = val.updater;
+				ConnectCallbacks (parentFrame, this);
+				if (evaluatedEvent != null)
+					evaluatedEvent.Set ();
+				if (notify && valueChanged != null)
+					valueChanged (this, EventArgs.Empty);
+			}
+		}
+
+		internal UpdateCallback GetUpdateCallback ()
+		{
+			if (IsEvaluating) {
+				if (updateCallback == null)
+					updateCallback = new UpdateCallback (new UpdateCallbackProxy (this), path);
+				return updateCallback;
+			}
+
+			return null;
+		}
+
+		~ObjectValue ()
+		{
+			if (updateCallback != null)
+				System.Runtime.Remoting.RemotingServices.Disconnect ((UpdateCallbackProxy)updateCallback.Callback);
+		}
+		
+		internal static void ConnectCallbacks (StackFrame parentFrame, params ObjectValue[] values)
+		{
+			Dictionary<IObjectValueUpdater, List<UpdateCallback>> callbacks = null;
+			List<ObjectValue> valueList = new List<ObjectValue> (values);
+			for (int n=0; n<valueList.Count; n++) {
+				ObjectValue val = valueList [n];
+				val.source = parentFrame.DebuggerSession.WrapDebuggerObject (val.source);
+				val.updater = parentFrame.DebuggerSession.WrapDebuggerObject (val.updater);
+				val.parentFrame = parentFrame;
+				UpdateCallback cb = val.GetUpdateCallback ();
+				if (cb != null) {
+					if (callbacks == null)
+						callbacks = new Dictionary<IObjectValueUpdater, List<UpdateCallback>> ();
+					List<UpdateCallback> list;
+					if (!callbacks.TryGetValue (val.Updater, out list)) {
+						list = new List<UpdateCallback> ();
+						callbacks [val.Updater] = list;
+					}
+					list.Add (cb);
+				}
+				if (val.children != null)
+					valueList.AddRange (val.children);
+			}
+			if (callbacks != null) {
+				// Do the callback connection in a background thread
+				ThreadPool.QueueUserWorkItem (delegate {
+					foreach (KeyValuePair<IObjectValueUpdater, List<UpdateCallback>> cbs in callbacks) {
+						cbs.Key.RegisterUpdateCallbacks (cbs.Value.ToArray ());
+					}
+				});
+			}
+		}
+	}
+
+	class UpdateCallbackProxy: MarshalByRefObject, IObjectValueUpdateCallback
+	{
+		readonly WeakReference valRef;
+		
+		public void UpdateValue (ObjectValue newValue)
+		{
+			ObjectValue val = valRef.Target as ObjectValue;
+			if (val != null)
+				val.UpdateFrom (newValue, true);
+		}
+		
+		public UpdateCallbackProxy (ObjectValue val)
+		{
+			valRef = new WeakReference (val);
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ObjectValueFlags.cs b/Mono.Debugging/Mono.Debugging.Client/ObjectValueFlags.cs
new file mode 100644
index 0000000..9157e26
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ObjectValueFlags.cs
@@ -0,0 +1,71 @@
+// ObjectValueKind.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	[Flags]
+	public enum ObjectValueFlags: uint {
+		None = 0,
+		Object = 1,             // The value is an object
+		Array = 1 << 1,         // The value is an array
+		Primitive = 1 << 2,     // The value is a primitive value
+		Unknown = 1 << 3,       // The evaluated identifier is unknown
+		Error = 1 << 4,         // The expression evaluation returned an error
+		NotSupported = 1 << 5,  // The expression is valid but its evaluation is not supported
+		Evaluating = 1 << 6,    // The expression is being evaluated. The value will be updated when done.
+		KindMask = 0x000000ff,
+		
+		Field = 1 << 8,
+		Property = 1 << 9,
+		Parameter = 1 << 10,
+		Variable = 1 << 11,
+		ArrayElement = 1 << 12,
+		Method = 1 << 13,
+		Literal = 1 << 14,
+		Type = 1 << 15,
+		Namespace = 1 << 16,
+		Group = 1 << 17,
+		OriginMask = 0x0003ff00,
+		
+		Global = 1 << 18,	// For fields, it means static
+		ReadOnly = 1 << 19,
+		NoRefresh = 1 << 20, // When set, this value can't be refreshed
+		EvaluatingGroup = 1 << 21, // When set, this value represents a set of values being evaluated
+		                           // When evaluation ends, the value is updated, and the children are the
+		                           // values represented by this group
+		
+		// For field and property
+		Public = 1 << 24,
+		Protected = 1 << 25,
+		Internal = 1 << 26,
+		Private = 1 << 27,
+		InternalProtected = Internal | Protected,
+		AccessMask = Public | Protected | Internal | Private
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ProcessEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/ProcessEventArgs.cs
new file mode 100644
index 0000000..7c9aec8
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ProcessEventArgs.cs
@@ -0,0 +1,47 @@
+// ProcessEventArgs.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	public class ProcessEventArgs: EventArgs
+	{
+		int processId;
+		
+		public int ProcessId {
+			get {
+				return processId;
+			}
+		}
+		
+		public ProcessEventArgs (int processId)
+		{
+			this.processId = processId;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ProcessInfo.cs b/Mono.Debugging/Mono.Debugging.Client/ProcessInfo.cs
new file mode 100644
index 0000000..a972965
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ProcessInfo.cs
@@ -0,0 +1,78 @@
+// ProcessInfo.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	[Serializable]
+	public class ProcessInfo
+	{
+		long id;
+		string name;
+		
+		[NonSerialized]
+		ThreadInfo[] currentThreads;
+		
+		[NonSerialized]
+		DebuggerSession session;
+		
+		internal void Attach (DebuggerSession session)
+		{
+			this.session = session;
+			if (currentThreads != null) {
+				foreach (ThreadInfo t in currentThreads)
+					t.Attach (session);
+			}
+		}
+		
+		public long Id {
+			get {
+				return id;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+
+		public ProcessInfo (long id, string name)
+		{
+			this.id = id;
+			this.name = name;
+		}
+		
+		public ThreadInfo[] GetThreads ()
+		{
+			if (currentThreads == null)
+				currentThreads = session.GetThreads (id);
+			return currentThreads;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/RawValue.cs b/Mono.Debugging/Mono.Debugging.Client/RawValue.cs
new file mode 100644
index 0000000..b74a403
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/RawValue.cs
@@ -0,0 +1,280 @@
+// 
+// RawValue.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Client
+{
+	/// <summary>
+	/// Represents an object in the process being debugged
+	/// </summary>
+	[Serializable]
+	public class RawValue: IRawObject
+	{
+		IRawValue source;
+		EvaluationOptions options;
+		
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValue"/> class.
+		/// </summary>
+		/// <param name='source'>
+		/// Value source
+		/// </param>
+		public RawValue (IRawValue source)
+		{
+			this.source = source;
+		}
+		
+		void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
+		{
+			this.options = options;
+			source = session.WrapDebuggerObject (source);
+		}
+
+		internal IRawValue Source {
+			get { return this.source; }
+		}
+
+		/// <summary>
+		/// Full name of the type of the object
+		/// </summary>
+		public string TypeName { get; set; }
+		
+		/// <summary>
+		/// Invokes a method on the object
+		/// </summary>
+		/// <returns>
+		/// The result of the invocation
+		/// </returns>
+		/// <param name='methodName'>
+		/// The name of the method
+		/// </param>
+		/// <param name='parameters'>
+		/// The parameters (primitive type values, RawValue instances or RawValueArray instances)
+		/// </param>
+		public object CallMethod (string methodName, params object[] parameters)
+		{
+			object res = source.CallMethod (methodName, parameters, options);
+			RawValue val = res as RawValue;
+			if (val != null)
+				val.options = options;
+			return res;
+		}
+		
+		/// <summary>
+		/// Gets the value of a field or property
+		/// </summary>
+		/// <returns>
+		/// The value (a primitive type value, a RawValue instance or a RawValueArray instance)
+		/// </returns>
+		/// <param name='name'>
+		/// Name of the field or property
+		/// </param>
+		public object GetMemberValue (string name)
+		{
+			object res = source.GetMemberValue (name, options);
+			RawValue val = res as RawValue;
+			if (val != null)
+				val.options = options;
+			return res;
+		}
+		
+		/// <summary>
+		/// Sets the value of a field or property
+		/// </summary>
+		/// <param name='name'>
+		/// Name of the field or property
+		/// </param>
+		/// <param name='value'>
+		/// The value (a primitive type value, a RawValue instance or a RawValueArray instance)
+		/// </param>
+		public void SetMemberValue (string name, object value)
+		{
+			source.SetMemberValue (name, value, options);
+		}
+	}
+	
+	/// <summary>
+	/// Represents an array of objects in the process being debugged
+	/// </summary>
+	[Serializable]
+	public class RawValueArray: IRawObject
+	{
+		IRawValueArray source;
+		int[] dimensions;
+		
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValueArray"/> class.
+		/// </summary>
+		/// <param name='source'>
+		/// Value source.
+		/// </param>
+		public RawValueArray (IRawValueArray source)
+		{
+			this.source = source;
+		}
+		
+		void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
+		{
+			source = session.WrapDebuggerObject (source);
+		}
+
+		internal IRawValueArray Source {
+			get { return this.source; }
+		}
+
+		/// <summary>
+		/// Full type name of the array items
+		/// </summary>
+		public string ElementTypeName { get; set; }
+
+		/// <summary>
+		/// Gets or sets the item at the specified index.
+		/// </summary>
+		/// <param name='index'>
+		/// The index
+		/// </param>
+		/// <remarks>
+		/// The item value can be a primitive type value, a RawValue instance or a RawValueArray instance.
+		/// </remarks>
+		public object this [int index] {
+			get {
+				return source.GetValue (new int[] { index });
+			}
+			set {
+				source.SetValue (new int[] { index }, value);
+			}
+		}
+
+		/// <summary>
+		/// Gets the values.
+		/// </summary>
+		/// <returns>The items.</returns>
+		/// <param name="index">The index.</param>
+		/// <param name="count">The number of items to get.</param>
+		/// <remarks>
+		/// This method is useful for incrementally fetching an array in order to avoid
+		/// long waiting periods when the array is too large for ToArray().
+		/// </remarks>
+		public Array GetValues (int index, int count)
+		{
+			return source.GetValues (new int[] { index }, count);
+		}
+		
+		/// <summary>
+		/// Returns an array with all items of the RawValueArray
+		/// </summary>
+		/// <remarks>
+		/// This method is useful to avoid unnecessary debugger-debuggee roundtrips
+		/// when processing all items of an array. For example, if a RawValueArray
+		/// represents an image encoded in a byte[], getting the values one by one
+		/// using the indexer is very slow. The ToArray() will return the whole byte[]
+		/// in a single call.
+		/// </remarks>
+		public Array ToArray ()
+		{
+			return source.ToArray ();
+		}
+
+		/// <summary>
+		/// Gets the length of the array
+		/// </summary>
+		public int Length {
+			get {
+				if (dimensions == null)
+					dimensions = source.Dimensions;
+				return dimensions[0];
+			}
+		}
+	}
+	
+	/// <summary>
+	/// Represents a string object in the process being debugged
+	/// </summary>
+	[Serializable]
+	public class RawValueString: IRawObject
+	{
+		IRawValueString source;
+		
+		/// <summary>
+		/// Initializes a new instance of the <see cref="Mono.Debugging.Client.RawValueString"/> class.
+		/// </summary>
+		/// <param name='source'>
+		/// Value source.
+		/// </param>
+		public RawValueString (IRawValueString source)
+		{
+			this.source = source;
+		}
+		
+		void IRawObject.Connect (DebuggerSession session, EvaluationOptions options)
+		{
+			source = session.WrapDebuggerObject (source);
+		}
+
+		internal IRawValueString Source {
+			get { return this.source; }
+		}
+
+		/// <summary>
+		/// Gets the length of the string
+		/// </summary>
+		public int Length {
+			get { return source.Length; }
+		}
+		
+		/// <summary>
+		/// Gets a substring of the string
+		/// </summary>
+		/// <param name='index'>
+		/// The starting index of the requested substring.
+		/// </param>
+		/// <param name='length'>
+		/// The length of the requested substring.
+		/// </param>
+		public string Substring (int index, int length)
+		{
+			return source.Substring (index, length);
+		}
+		
+		/// <summary>
+		/// Gets the value.
+		/// </summary>
+		/// <value>
+		/// The value.
+		/// </value>
+		public string Value {
+			get { return source.Value; }
+		}
+	}
+
+	internal interface IRawObject
+	{
+		void Connect (DebuggerSession session, EvaluationOptions options);
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Client/SourceLocation.cs b/Mono.Debugging/Mono.Debugging.Client/SourceLocation.cs
new file mode 100644
index 0000000..717eb9b
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/SourceLocation.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class SourceLocation
+	{
+		public string MethodName { get; private set; }
+		public string FileName { get; private set; }
+		public int Line { get; private set; }
+		public int Column { get; private set; }
+
+		public SourceLocation (string methodName, string fileName, int line)
+			: this (methodName, fileName, line, -1)
+		{
+		}
+
+		public SourceLocation (string methodName, string fileName, int line, int column)
+		{
+			this.MethodName = methodName;
+			this.FileName = fileName;
+			this.Line = line;
+			this.Column = column;
+		}
+		
+		public override string ToString ()
+		{
+			return string.Format("[SourceLocation Method={0}, Filename={1}, Line={2}, Column={3}]", MethodName, FileName, Line, Column);
+		}
+
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/StackFrame.cs b/Mono.Debugging/Mono.Debugging.Client/StackFrame.cs
new file mode 100644
index 0000000..b1e16ad
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/StackFrame.cs
@@ -0,0 +1,313 @@
+using System;
+using Mono.Debugging.Backend;
+using System.Collections.Generic;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class StackFrame
+	{
+		long address;
+		string addressSpace;
+		SourceLocation location;
+		IBacktrace sourceBacktrace;
+		string language;
+		int index;
+		bool isExternalCode;
+		bool isDebuggerHidden;
+		bool hasDebugInfo;
+		string fullModuleName;
+		string fullTypeName;
+		
+		[NonSerialized]
+		DebuggerSession session;
+
+		public StackFrame (long address, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, bool isDebuggerHidden, string fullModuleName, string fullTypeName)
+		{
+			this.address = address;
+			this.addressSpace = addressSpace;
+			this.location = location;
+			this.language = language;
+			this.isExternalCode = isExternalCode;
+			this.isDebuggerHidden = isDebuggerHidden;
+			this.hasDebugInfo = hasDebugInfo;
+			this.fullModuleName = fullModuleName;
+			this.fullTypeName = fullTypeName;
+		}
+
+		public StackFrame (long address, string addressSpace, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo, string fullModuleName, string fullTypeName)
+			: this (address, addressSpace, location, language, isExternalCode, hasDebugInfo, false, fullModuleName, fullTypeName)
+		{
+		}
+		
+		public StackFrame (long address, string addressSpace, SourceLocation location, string language)
+			: this (address, addressSpace, location, language, string.IsNullOrEmpty (location.FileName), true, "", "")
+		{
+		}
+
+		public StackFrame (long address, string addressSpace, string module, string method, string filename, int line, string language)
+			: this (address, addressSpace, new SourceLocation (method, filename, line), language)
+		{
+		}
+
+		public StackFrame (long address, SourceLocation location, string language, bool isExternalCode, bool hasDebugInfo)
+			: this (address, "", location, language, string.IsNullOrEmpty (location.FileName), true, "", "")
+		{
+		}
+		
+		public StackFrame (long address, SourceLocation location, string language)
+			: this (address, "", location, language, string.IsNullOrEmpty (location.FileName), true, "", "")
+		{
+		}
+
+		internal void Attach (DebuggerSession session)
+		{
+			this.session = session;
+		}
+		
+		public DebuggerSession DebuggerSession {
+			get { return session; }
+		}
+		
+		public SourceLocation SourceLocation
+		{
+			get { return location; }
+		}
+
+		public long Address
+		{
+			get { return address; }
+		}
+		
+		public string AddressSpace {
+			get { return addressSpace; }
+		}
+
+		internal IBacktrace SourceBacktrace {
+			get { return sourceBacktrace; }
+			set { sourceBacktrace = value; }
+		}
+
+		public int Index {
+			get { return index; }
+			internal set { index = value; }
+		}
+
+		public string Language {
+			get {
+				return language;
+			}
+		}
+		
+		public bool IsExternalCode {
+			get { return isExternalCode; }
+		}
+
+		public bool IsDebuggerHidden {
+			get { return isDebuggerHidden; }
+		}
+		
+		public bool HasDebugInfo {
+			get { return this.hasDebugInfo; }
+		}
+		
+		public string FullModuleName {
+			get { return this.fullModuleName; }
+		}
+		
+		public string FullTypeName {
+			get { return this.fullTypeName; }
+		}
+		
+		public ObjectValue[] GetLocalVariables ()
+		{
+			return GetLocalVariables (session.EvaluationOptions);
+		}
+		
+		public ObjectValue[] GetLocalVariables (EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return new ObjectValue [0];
+			ObjectValue[] values = sourceBacktrace.GetLocalVariables (index, options);
+			ObjectValue.ConnectCallbacks (this, values);
+			return values;
+		}
+		
+		public ObjectValue[] GetParameters ()
+		{
+			return GetParameters (session.EvaluationOptions);
+		}
+		
+		public ObjectValue[] GetParameters (EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return new ObjectValue [0];
+			ObjectValue[] values = sourceBacktrace.GetParameters (index, options);
+			ObjectValue.ConnectCallbacks (this, values);
+			return values;
+		}
+		
+		public ObjectValue[] GetAllLocals ()
+		{
+			if (!hasDebugInfo)
+				return new ObjectValue [0];
+			IExpressionEvaluator evaluator = session.FindExpressionEvaluator (this);
+			if (evaluator != null)
+				return evaluator.GetLocals (this);
+			return GetAllLocals (session.EvaluationOptions);
+		}
+		
+		public ObjectValue[] GetAllLocals (EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return new ObjectValue [0];
+			ObjectValue[] values = sourceBacktrace.GetAllLocals (index, options);
+			ObjectValue.ConnectCallbacks (this, values);
+			return values;
+		}
+		
+		public ObjectValue GetThisReference ()
+		{
+			return GetThisReference (session.EvaluationOptions);
+		}
+		
+		public ObjectValue GetThisReference (EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return null;
+			ObjectValue value = sourceBacktrace.GetThisReference (index, options);
+			if (value != null)
+				ObjectValue.ConnectCallbacks (this, value);
+			return value;
+		}
+		
+		public ExceptionInfo GetException ()
+		{
+			return GetException (session.EvaluationOptions);
+		}
+		
+		public ExceptionInfo GetException (EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return null;
+			ExceptionInfo value = sourceBacktrace.GetException (index, options);
+			if (value != null)
+				value.ConnectCallback (this);
+			return value;
+		}
+		
+		public string ResolveExpression (string exp)
+		{
+			return session.ResolveExpression (exp, location);
+		}
+		
+		public ObjectValue[] GetExpressionValues (string[] expressions, bool evaluateMethods)
+		{
+			EvaluationOptions options = session.EvaluationOptions.Clone ();
+			options.AllowMethodEvaluation = evaluateMethods;
+			return GetExpressionValues (expressions, options);
+		}
+		
+		public ObjectValue[] GetExpressionValues (string[] expressions, EvaluationOptions options)
+		{
+			if (!hasDebugInfo) {
+				ObjectValue[] vals = new ObjectValue [expressions.Length];
+				for (int n=0; n<expressions.Length; n++)
+					vals [n] = ObjectValue.CreateUnknown (expressions [n]);
+				return vals;
+			}
+			if (options.UseExternalTypeResolver) {
+				string[] resolved = new string [expressions.Length];
+				for (int n=0; n<expressions.Length; n++)
+					resolved [n] = ResolveExpression (expressions [n]);
+				expressions = resolved;
+			}
+			ObjectValue[] values = sourceBacktrace.GetExpressionValues (index, expressions, options);
+			ObjectValue.ConnectCallbacks (this, values);
+			return values;
+		}
+		
+		public ObjectValue GetExpressionValue (string expression, bool evaluateMethods)
+		{
+			EvaluationOptions options = session.EvaluationOptions.Clone ();
+			options.AllowMethodEvaluation = evaluateMethods;
+			return GetExpressionValue (expression, options);
+		}
+		
+		public ObjectValue GetExpressionValue (string expression, EvaluationOptions options)
+		{
+			if (!hasDebugInfo)
+				return ObjectValue.CreateUnknown (expression);
+			if (options.UseExternalTypeResolver)
+				expression = ResolveExpression (expression);
+			ObjectValue[] values = sourceBacktrace.GetExpressionValues (index, new string[] { expression }, options);
+			ObjectValue.ConnectCallbacks (this, values);
+			return values [0];
+		}
+		
+		/// <summary>
+		/// Returns True if the expression is valid and can be evaluated for this frame.
+		/// </summary>
+		public bool ValidateExpression (string expression)
+		{
+			return ValidateExpression (expression, session.EvaluationOptions);
+		}
+		
+		/// <summary>
+		/// Returns True if the expression is valid and can be evaluated for this frame.
+		/// </summary>
+		public ValidationResult ValidateExpression (string expression, EvaluationOptions options)
+		{
+			if (options.UseExternalTypeResolver)
+				expression = ResolveExpression (expression);
+			return sourceBacktrace.ValidateExpression (index, expression, options);
+		}
+		
+		public CompletionData GetExpressionCompletionData (string exp)
+		{
+			if (!hasDebugInfo)
+				return null;
+			return sourceBacktrace.GetExpressionCompletionData (index, exp);
+		}
+		
+		// Returns disassembled code for this stack frame.
+		// firstLine is the relative code line. It can be negative.
+		public AssemblyLine[] Disassemble (int firstLine, int count)
+		{
+			return sourceBacktrace.Disassemble (index, firstLine, count);
+		}
+
+		public override string ToString()
+		{
+			string loc;
+			if (location.Line != -1 && !string.IsNullOrEmpty (location.FileName))
+				loc = " at " + location.FileName + ":" + location.Line;
+			else if (!string.IsNullOrEmpty (location.FileName))
+				loc = " at " + location.FileName;
+			else
+				loc = "";
+			return String.Format("0x{0:X} in {1}{2}", address, location.MethodName, loc);
+		}
+	}
+	
+	[Serializable]
+	public struct ValidationResult
+	{
+		readonly string message;
+		readonly bool isValid;
+		
+		public ValidationResult (bool isValid, string message)
+		{
+			this.isValid = isValid;
+			this.message = message;
+		}
+		
+		public bool IsValid { get { return isValid; } }
+		public string Message { get { return message; } }
+		
+		public static implicit operator bool (ValidationResult result)
+		{
+			return result.isValid;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/TargetEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/TargetEventArgs.cs
new file mode 100644
index 0000000..f025dab
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/TargetEventArgs.cs
@@ -0,0 +1,57 @@
+using System;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public class TargetEventArgs: EventArgs
+	{
+		TargetEventType type;
+		Backtrace backtrace;
+		ProcessInfo process;
+		ThreadInfo thread;
+
+		public TargetEventArgs (TargetEventType type)
+		{
+			this.type = type;
+		}
+
+		public TargetEventType Type
+		{
+			get { return type; }
+			set { type = value; }
+		}
+
+		public Backtrace Backtrace
+		{
+			get { return backtrace; }
+			set { backtrace = value; }
+		}
+
+		public ThreadInfo Thread {
+			get {
+				return thread;
+			}
+			set {
+				thread = value;
+			}
+		}
+
+		public ProcessInfo Process {
+			get {
+				return process;
+			}
+			set {
+				process = value;
+			}
+		}
+		
+		public bool IsStopEvent {
+			get; set;
+		}
+
+		public BreakEvent BreakEvent {
+			get; set;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/TargetEventType.cs b/Mono.Debugging/Mono.Debugging.Client/TargetEventType.cs
new file mode 100644
index 0000000..f93a6cf
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/TargetEventType.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Mono.Debugging.Client
+{
+	[Serializable]
+	public enum TargetEventType
+	{
+		TargetReady,
+		TargetStopped,
+		TargetInterrupted,
+		TargetHitBreakpoint,
+		TargetSignaled,
+		TargetExited,
+		ExceptionThrown,
+		UnhandledException,
+		ThreadStarted,
+		ThreadStopped
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ThreadEventArgs.cs b/Mono.Debugging/Mono.Debugging.Client/ThreadEventArgs.cs
new file mode 100644
index 0000000..f1d8eb9
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ThreadEventArgs.cs
@@ -0,0 +1,47 @@
+// ThreadEventArgs.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	public class ThreadEventArgs: EventArgs
+	{
+		int threadId;
+		
+		public int ThreadId {
+			get {
+				return threadId;
+			}
+		}
+		
+		public ThreadEventArgs (int threadId)
+		{
+			this.threadId = threadId;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Client/ThreadInfo.cs b/Mono.Debugging/Mono.Debugging.Client/ThreadInfo.cs
new file mode 100644
index 0000000..78cd0bc
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Client/ThreadInfo.cs
@@ -0,0 +1,135 @@
+// ThreadInfo.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client
+{
+	[Serializable]
+	public class ThreadInfo
+	{
+		long id;
+		string name;
+		long processId;
+		string location;
+		Backtrace backtrace;
+		
+		[NonSerialized]
+		DebuggerSession session;
+		
+		internal void Attach (DebuggerSession session)
+		{
+			this.session = session;
+		}
+		
+		public long Id {
+			get {
+				return id;
+			}
+		}
+
+		public string Name {
+			get {
+				return name;
+			}
+		}
+		
+		public string Location {
+			get {
+				if (location == null) {
+					Backtrace bt = Backtrace;
+					if (bt != null && bt.FrameCount > 0)
+						location = bt.GetFrame (0).ToString ();
+				}
+				return location;
+			}
+		}
+		
+		internal long ProcessId {
+			get { return processId; }
+		}
+
+		public Backtrace Backtrace {
+			get {
+				if (backtrace == null)
+					backtrace = session.GetBacktrace (processId, id);
+				return backtrace;
+			}
+		}
+		
+		public void SetActive ()
+		{
+			session.ActiveThread = this;
+		}
+		
+		public ThreadInfo (long processId, long id, string name, string location): this (processId, id, name, location, null)
+		{
+		}
+		
+		public ThreadInfo (long processId, long id, string name, string location, Backtrace backtrace)
+		{
+			this.id = id;
+			this.name = name;
+			this.processId = processId;
+			this.location = location;
+			this.backtrace = backtrace;
+		}
+		
+		public override bool Equals (object obj)
+		{
+			ThreadInfo ot = obj as ThreadInfo;
+			if (ot == null)
+				return false;
+			return id == ot.id && processId == ot.processId;
+		}
+		
+		public override int GetHashCode ()
+		{
+			unchecked {
+				return (int) (id + processId*1000);
+			}
+		}
+		
+		public static bool operator == (ThreadInfo t1, ThreadInfo t2)
+		{
+			if (object.ReferenceEquals (t1, t2))
+				return true;
+			if ((object)t1 == null || (object)t2 == null)
+				return false;
+			return t1.Equals (t2);
+		}
+		
+		public static bool operator != (ThreadInfo t1, ThreadInfo t2)
+		{
+			if (object.ReferenceEquals (t1, t2))
+				return false;
+			if ((object)t1 == null || (object)t2 == null)
+				return true;
+			return !t1.Equals (t2);
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ArrayElementGroup.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ArrayElementGroup.cs
new file mode 100644
index 0000000..a7b95ed
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ArrayElementGroup.cs
@@ -0,0 +1,359 @@
+// ArrayElementGroup.cs
+//
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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.Text;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class ArrayElementGroup: RemoteFrameObject, IObjectValueSource
+	{
+		EvaluationContext ctx;
+		int[] baseIndices;
+		int firstIndex;
+		int lastIndex;
+		int[] bounds;
+		ICollectionAdaptor array;
+		
+		const int MaxChildCount = 150;
+
+		public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array)
+			: this (ctx, array, new int [0])
+		{
+		}
+
+		public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array, int[] baseIndices)
+			: this (ctx, array, baseIndices, 0, -1)
+		{
+		}
+
+		public ArrayElementGroup (EvaluationContext ctx, ICollectionAdaptor array, int[] baseIndices, int firstIndex, int lastIndex)
+		{
+			this.array = array;
+			this.ctx = ctx;
+			this.bounds = array.GetDimensions ();
+			this.baseIndices = baseIndices;
+			this.firstIndex = firstIndex;
+			this.lastIndex = lastIndex;
+		}
+		
+		public bool IsRange {
+			get { return lastIndex != -1; }
+		}
+		
+		public ObjectValue CreateObjectValue ()
+		{
+			Connect ();
+			StringBuilder sb = new StringBuilder ("[");
+			for (int n=0; n<baseIndices.Length; n++) {
+				if (n > 0)
+					sb.Append (", ");
+				sb.Append (baseIndices [n].ToString ());
+			}
+			if (IsRange) {
+				if (baseIndices.Length > 0)
+					sb.Append (", ");
+				sb.Append (firstIndex.ToString ()).Append ("..").Append (lastIndex.ToString ());
+			}
+			if (bounds.Length > 1 && baseIndices.Length < bounds.Length)
+				sb.Append (", ...");
+			
+			sb.Append ("]");
+			
+			ObjectValue res = ObjectValue.CreateObject (this, new ObjectPath (sb.ToString ()), "", "", ObjectValueFlags.ArrayElement|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
+			res.ChildSelector = "";
+			return res;
+		}
+
+		public ObjectValue[] GetChildren (EvaluationOptions options)
+		{
+			return GetChildren (new ObjectPath ("this"), -1, -1, options);
+		}
+		
+		public ObjectValue[] GetChildren (ObjectPath path, int firstItemIndex, int count, EvaluationOptions options)
+		{
+			EvaluationContext cctx = ctx.WithOptions (options);
+			if (path.Length > 1) {
+				// Looking for children of an array element
+				int[] idx = StringToIndices (path [1]);
+				object obj = array.GetElement (idx);
+				return cctx.Adapter.GetObjectValueChildren (cctx, new ArrayObjectSource (array, path[1]), obj, firstItemIndex, count);
+			}
+			
+			int lowerBound;
+			int upperBound;
+			bool isLastDimension;
+			
+			if (bounds.Length > 1) {
+				int rank = baseIndices.Length;
+				lowerBound = 0;
+				upperBound = bounds [rank] - 1;
+				isLastDimension = rank == bounds.Length - 1;
+			} else {
+				lowerBound = 0;
+				upperBound = bounds [0] - 1;
+				isLastDimension = true;
+			}
+			
+			int len;
+			int initalIndex;
+			
+			if (!IsRange) {
+				initalIndex = lowerBound;
+				len = upperBound + 1;
+			}
+			else {
+				initalIndex = firstIndex;
+				len = lastIndex - firstIndex + 1;
+			}
+			
+			if (firstItemIndex == -1) {
+				firstItemIndex = 0;
+				count = len;
+			}
+			
+			// Make sure the group doesn't have too many elements. If so, divide
+			int div = 1;
+			while (len / div > MaxChildCount)
+				div *= 10;
+			
+			if (div == 1 && isLastDimension) {
+				// Return array elements
+				
+				ObjectValue[] values = new ObjectValue [count];
+				ObjectPath newPath = new ObjectPath ("this");
+				
+				int[] curIndex = new int [baseIndices.Length + 1];
+				Array.Copy (baseIndices, curIndex, baseIndices.Length);
+				string curIndexStr = IndicesToString (baseIndices);
+				if (baseIndices.Length > 0) curIndexStr += ",";
+				
+				for (int n=0; n < values.Length; n++) {
+					int index = n + initalIndex + firstItemIndex;
+					string sidx = curIndexStr + index.ToString ();
+					ObjectValue val;
+					string ename = "[" + sidx.Replace (",",", ") + "]";
+					if (index > upperBound)
+						val = ObjectValue.CreateUnknown (sidx);
+					else {
+						curIndex [curIndex.Length - 1] = index;
+						object elem = array.GetElement (curIndex);
+						val = cctx.Adapter.CreateObjectValue (cctx, this, newPath.Append (sidx), elem, ObjectValueFlags.ArrayElement);
+						if (elem != null && !cctx.Adapter.IsNull (cctx, elem)) {
+							TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elem));
+							if (!string.IsNullOrEmpty (tdata.NameDisplayString))
+								ename = cctx.Adapter.EvaluateDisplayString (cctx, elem, tdata.NameDisplayString);
+						}
+					}
+					val.Name = ename;
+					values [n] = val;
+				}
+				return values;
+			}
+			else if (!isLastDimension && div == 1) {
+				// Return an array element group for each index
+				
+				List<ObjectValue> list = new List<ObjectValue> ();
+				for (int i=0; i<count; i++) {
+					int index = i + initalIndex + firstItemIndex;
+					ObjectValue val;
+					
+					// This array must be created at every call to avoid sharing
+					// changes with all array groups
+					int[] curIndex = new int [baseIndices.Length + 1];
+					Array.Copy (baseIndices, curIndex, baseIndices.Length);
+					curIndex [curIndex.Length - 1] = index;
+					
+					if (index > upperBound)
+						val = ObjectValue.CreateUnknown ("");
+					else {
+						ArrayElementGroup grp = new ArrayElementGroup (cctx, array, curIndex);
+						val = grp.CreateObjectValue ();
+					}
+					list.Add (val);
+				}
+				return list.ToArray ();
+			}
+			else {
+				// Too many elements. Split the array.
+				
+				// Don't make divisions of 10 elements, min is 100
+				if (div == 10)
+					div = 100;
+				
+				// Create the child groups
+				int i = initalIndex + firstItemIndex;
+				len += i;
+				List<ObjectValue> list = new List<ObjectValue> ();
+				while (i < len) {
+					int end = i + div - 1;
+					if (end > len)
+						end = len - 1;
+					ArrayElementGroup grp = new ArrayElementGroup (cctx, array, baseIndices, i, end);
+					list.Add (grp.CreateObjectValue ());
+					i += div;
+				}
+				return list.ToArray ();
+			}
+		}
+		
+		internal static string IndicesToString (int[] indices)
+		{
+			StringBuilder sb = new StringBuilder ();
+			for (int n=0; n<indices.Length; n++) {
+				if (n > 0)
+					sb.Append (',');
+				sb.Append (indices [n].ToString ());
+			}
+			return sb.ToString ();
+		}
+		
+		internal static int[] StringToIndices (string str)
+		{
+			string[] sidx = str.Split (',');
+			int[] idx = new int [sidx.Length];
+			for (int n=0; n<sidx.Length; n++)
+				idx [n] = int.Parse (sidx [n]);
+			return idx;
+		}
+		
+		public static string GetArrayDescription (int[] bounds)
+		{
+			if (bounds.Length == 0)
+				return "[...]";
+
+			StringBuilder sb = new StringBuilder ("[");
+			for (int n=0; n<bounds.Length; n++) {
+				if (n > 0)
+					sb.Append (", ");
+				sb.Append (bounds [n].ToString ());
+			}
+			sb.Append ("]");
+			return sb.ToString ();
+		}
+		
+		public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			if (path.Length != 2)
+				throw new NotSupportedException ();
+			
+			int[] idx = StringToIndices (path [1]);
+			
+			object val;
+			try {
+				EvaluationContext cctx = ctx.Clone ();
+				EvaluationOptions ops = options ?? cctx.Options;
+				ops.AllowMethodEvaluation = true;
+				ops.AllowTargetInvoke = true;
+				cctx.Options = ops;
+				ValueReference var = ctx.Evaluator.Evaluate (ctx, value, array.ElementType);
+				val = var.Value;
+				val = ctx.Adapter.Convert (ctx, val, array.ElementType);
+				array.SetElement (idx, val);
+			} catch {
+				val = array.GetElement (idx);
+			}
+			try {
+				return ctx.Evaluator.TargetObjectToExpression (ctx, val);
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				return new EvaluationResult ("? (" + ex.Message + ")");
+			}
+		}
+		
+		public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			if (path.Length != 2)
+				throw new NotSupportedException ();
+			
+			int[] idx = StringToIndices (path [1]);
+			object elem = array.GetElement (idx);
+			EvaluationContext cctx = ctx.WithOptions (options);
+			ObjectValue val = cctx.Adapter.CreateObjectValue (cctx, this, path, elem, ObjectValueFlags.ArrayElement);
+			if (elem != null && !cctx.Adapter.IsNull (cctx, elem)) {
+				TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elem));
+				if (!string.IsNullOrEmpty (tdata.NameDisplayString))
+					val.Name = cctx.Adapter.EvaluateDisplayString (cctx, elem, tdata.NameDisplayString);
+			}
+			return val;
+		}
+		
+		public object GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			if (path.Length != 2)
+				throw new NotSupportedException ();
+			
+			int[] idx = StringToIndices (path [1]);
+			object elem = array.GetElement (idx);
+			EvaluationContext cctx = ctx.WithOptions (options);
+			return cctx.Adapter.ToRawValue (cctx, new ArrayObjectSource (array, idx), elem);
+		}
+		
+		public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			if (path.Length != 2)
+				throw new NotSupportedException ();
+			
+			int[] idx = StringToIndices (path [1]);
+			
+			EvaluationContext cctx = ctx.WithOptions (options);
+			object val = cctx.Adapter.FromRawValue (cctx, value);
+			array.SetElement (idx, val);
+		}
+	}
+	
+	class ArrayObjectSource: IObjectSource
+	{
+		ICollectionAdaptor source;
+		string path;
+		
+		public ArrayObjectSource (ICollectionAdaptor source, string path)
+		{
+			this.source = source;
+			this.path = path;
+		}
+		
+		public ArrayObjectSource (ICollectionAdaptor source, int[] index)
+		{
+			this.source = source;
+			this.path = ArrayElementGroup.IndicesToString (index);
+		}
+		
+		public object Value {
+			get {
+				return source.GetElement (ArrayElementGroup.StringToIndices (path));
+			}
+			set {
+				source.SetElement (ArrayElementGroup.StringToIndices (path), value);
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ArrayValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ArrayValueReference.cs
new file mode 100644
index 0000000..58eb286
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ArrayValueReference.cs
@@ -0,0 +1,79 @@
+// ArrayValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Text;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class ArrayValueReference: ValueReference
+	{
+		readonly ICollectionAdaptor adaptor;
+		readonly int[] indices;
+
+		public ArrayValueReference (EvaluationContext ctx, object arr, int[] indices) : base (ctx)
+		{
+			this.indices = indices;
+			adaptor = ctx.Adapter.CreateArrayAdaptor (ctx, arr);
+		}
+
+		public override object Value {
+			get {
+				return adaptor.GetElement (indices);
+			}
+			set {
+				adaptor.SetElement (indices, value);
+			}
+		}
+		
+		public override string Name {
+			get {
+				StringBuilder sb = new StringBuilder ();
+				sb.Append ('[');
+				for (int n=0; n<indices.Length; n++) {
+					if (n > 0) sb.Append (", ");
+					sb.Append (indices [n]);
+				}
+				sb.Append (']');
+				return sb.ToString ();
+			}
+		}
+		
+		public override object Type {
+			get {
+				return adaptor.ElementType;
+			}
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.ArrayElement;
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs b/Mono.Debugging/Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs
new file mode 100644
index 0000000..40c568e
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/AsyncEvaluationTracker.cs
@@ -0,0 +1,147 @@
+// AsyncEvaluationTracker.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public delegate ObjectValue ObjectEvaluatorDelegate ();
+	
+	/// <summary>
+	/// This class can be used to generate an ObjectValue using a provided evaluation delegate.
+	/// The value is initialy evaluated synchronously (blocking the caller). If no result
+	/// is obtained after a short period (provided in the WaitTime property), evaluation
+	/// will then be made asynchronous and the Run method will immediately return an ObjectValue
+	/// with the Evaluating state.
+	/// </summary>
+	public class AsyncEvaluationTracker: RemoteFrameObject, IObjectValueUpdater, IDisposable
+	{
+		Dictionary<string, UpdateCallback> asyncCallbacks = new Dictionary<string, UpdateCallback> ();
+		Dictionary<string, ObjectValue> asyncResults = new Dictionary<string, ObjectValue> ();
+		int asyncCounter = 0;
+		int cancelTimestamp = 0;
+		TimedEvaluator runner = new TimedEvaluator ();
+		
+		public int WaitTime {
+			get { return runner.RunTimeout; }
+			set { runner.RunTimeout = value; }
+		}
+		
+		public bool IsEvaluating {
+			get { return runner.IsEvaluating; }
+		}
+
+		public ObjectValue Run (string name, ObjectValueFlags flags, ObjectEvaluatorDelegate evaluator)
+		{
+			string id;
+			int tid;
+			lock (asyncCallbacks) {
+				tid = asyncCounter++;
+				id = tid.ToString ();
+			}
+			
+			ObjectValue val = null;
+			bool done = runner.Run (delegate {
+					if (tid >= cancelTimestamp)
+						val = evaluator ();
+			},
+			delegate {
+				if (tid >= cancelTimestamp)
+					OnEvaluationDone (id, val);
+			});
+			
+			if (done)
+				return val ?? ObjectValue.CreateUnknown (name);
+			    // 'val' may be null if the timed evaluator is disposed while evaluating
+			else
+				return ObjectValue.CreateEvaluating (this, new ObjectPath (id, name), flags);
+		}
+		
+		public void Dispose ()
+		{
+			runner.Dispose ();
+		}
+
+
+		public void Stop ()
+		{
+			lock (asyncCallbacks) {
+				cancelTimestamp = asyncCounter;
+				runner.CancelAll ();
+				foreach (var cb in asyncCallbacks.Values) {
+					try {
+						cb.UpdateValue (ObjectValue.CreateFatalError ("", "Canceled", ObjectValueFlags.None));
+					} catch {
+					}
+				}
+				asyncCallbacks.Clear ();
+				asyncResults.Clear ();
+			}
+		}
+
+		public void WaitForStopped ()
+		{
+			runner.WaitForStopped ();
+		}
+
+		void OnEvaluationDone (string id, ObjectValue val)
+		{
+			if (val == null)
+				val = ObjectValue.CreateUnknown (null);
+			UpdateCallback cb = null;
+			lock (asyncCallbacks) {
+				if (asyncCallbacks.TryGetValue (id, out cb)) {
+					try {
+						cb.UpdateValue (val);
+					} catch {}
+					asyncCallbacks.Remove (id);
+				}
+				else
+					asyncResults [id] = val;
+			}
+		}
+		
+		void IObjectValueUpdater.RegisterUpdateCallbacks (UpdateCallback[] callbacks)
+		{
+			foreach (UpdateCallback c in callbacks) {
+				lock (asyncCallbacks) {
+					ObjectValue val;
+					string id = c.Path[0];
+					if (asyncResults.TryGetValue (id, out val)) {
+						c.UpdateValue (val);
+						asyncResults.Remove (id);
+					} else {
+						asyncCallbacks [id] = c;
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/AsyncOperationManager.cs b/Mono.Debugging/Mono.Debugging.Evaluation/AsyncOperationManager.cs
new file mode 100644
index 0000000..ea69b74
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/AsyncOperationManager.cs
@@ -0,0 +1,241 @@
+// RuntimeInvokeManager.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 ST = System.Threading;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class AsyncOperationManager: IDisposable
+	{
+		List<AsyncOperation> operationsToCancel = new List<AsyncOperation> ();
+		internal bool Disposing;
+
+		public void Invoke (AsyncOperation methodCall, int timeout)
+		{
+			methodCall.Aborted = false;
+			methodCall.Manager = this;
+
+			lock (operationsToCancel) {
+				operationsToCancel.Add (methodCall);
+				methodCall.Invoke ();
+			}
+
+			if (timeout > 0) {
+				if (!methodCall.WaitForCompleted (timeout)) {
+					bool wasAborted = methodCall.Aborted;
+					methodCall.InternalAbort ();
+					lock (operationsToCancel) {
+						operationsToCancel.Remove (methodCall);
+						ST.Monitor.PulseAll (operationsToCancel);
+					}
+					if (wasAborted)
+						throw new EvaluatorAbortedException ();
+					else
+						throw new TimeOutException ();
+				}
+			}
+			else {
+				methodCall.WaitForCompleted (System.Threading.Timeout.Infinite);
+			}
+
+			lock (operationsToCancel) {
+				operationsToCancel.Remove (methodCall);
+				ST.Monitor.PulseAll (operationsToCancel);
+				if (methodCall.Aborted) {
+					throw new EvaluatorAbortedException ();
+				}
+			}
+
+			if (!string.IsNullOrEmpty (methodCall.ExceptionMessage)) {
+				throw new Exception (methodCall.ExceptionMessage);
+			}
+		}
+		
+		public void Dispose ()
+		{
+			Disposing = true;
+			lock (operationsToCancel) {
+				foreach (AsyncOperation op in operationsToCancel) {
+					op.InternalShutdown ();
+				}
+				operationsToCancel.Clear ();
+			}
+		}
+
+		public void AbortAll ()
+		{
+			lock (operationsToCancel) {
+				foreach (AsyncOperation op in operationsToCancel)
+					op.InternalAbort ();
+			}
+		}
+		
+		public void EnterBusyState (AsyncOperation oper)
+		{
+			BusyStateEventArgs args = new BusyStateEventArgs ();
+			args.IsBusy = true;
+			args.Description = oper.Description;
+			if (BusyStateChanged != null)
+				BusyStateChanged (this, args);
+		}
+		
+		public void LeaveBusyState (AsyncOperation oper)
+		{
+			BusyStateEventArgs args = new BusyStateEventArgs ();
+			args.IsBusy = false;
+			args.Description = oper.Description;
+			if (BusyStateChanged != null)
+				BusyStateChanged (this, args);
+		}
+		
+		public event EventHandler<BusyStateEventArgs> BusyStateChanged;
+	}
+
+	public abstract class AsyncOperation
+	{
+		internal bool Aborted;
+		internal AsyncOperationManager Manager;
+		
+		public bool Aborting { get; internal set; }
+		
+		internal void InternalAbort ()
+		{
+			ST.Monitor.Enter (this);
+			if (Aborted) {
+				ST.Monitor.Exit (this);
+				return;
+			}
+			
+			if (Aborting) {
+				// Somebody else is aborting this. Just wait for it to finish.
+				ST.Monitor.Exit (this);
+				WaitForCompleted (ST.Timeout.Infinite);
+				return;
+			}
+			
+			Aborting = true;
+			
+			int abortState = 0;
+			int abortRetryWait = 100;
+			bool abortRequested = false;
+			
+			do {
+				if (abortState > 0)
+					ST.Monitor.Enter (this);
+				
+				try {
+					if (!Aborted && !abortRequested) {
+						// The Abort() call doesn't block. WaitForCompleted is used below to wait for the abort to succeed
+						Abort ();
+						abortRequested = true;
+					}
+					// Short wait for the Abort to finish. If this wait is not enough, it will wait again in the next loop
+					if (WaitForCompleted (100)) {
+						ST.Monitor.Exit (this);
+						break;
+					}
+				} catch {
+					// If abort fails, try again after a short wait
+				}
+				abortState++;
+				if (abortState == 6) {
+					// Several abort calls have failed. Inform the user that the debugger is busy
+					abortRetryWait = 500;
+					try {
+						Manager.EnterBusyState (this);
+					} catch (Exception ex) {
+						Console.WriteLine (ex);
+					}
+				}
+				ST.Monitor.Exit (this);
+			} while (!Aborted && !WaitForCompleted (abortRetryWait) && !Manager.Disposing);
+			
+			if (Manager.Disposing) {
+				InternalShutdown ();
+			}
+			else {
+				lock (this) {
+					Aborted = true;
+					if (abortState >= 6)
+						Manager.LeaveBusyState (this);
+				}
+			}
+		}
+		
+		internal void InternalShutdown ()
+		{
+			lock (this) {
+				if (Aborted)
+					return;
+				try {
+					Aborted = true;
+					Shutdown ();
+				} catch {
+					// Ignore
+				}
+			}
+		}
+		
+		/// <summary>
+		/// Message of the exception, if the execution failed. 
+		/// </summary>
+		public string ExceptionMessage { get; set; }
+
+		/// <summary>
+		/// Returns a short description of the operation, to be shown in the Debugger Busy Dialog
+		/// when it blocks the execution of the debugger. 
+		/// </summary>
+		public abstract string Description { get; }
+		
+		/// <summary>
+		/// Called to invoke the operation. The execution must be asynchronous (it must return immediatelly).
+		/// </summary>
+		public abstract void Invoke ( );
+
+		/// <summary>
+		/// Called to abort the execution of the operation. It has to throw an exception
+		/// if the operation can't be aborted. This operation must not block. The engine
+		/// will wait for the operation to be aborted by calling WaitForCompleted.
+		/// </summary>
+		public abstract void Abort ();
+
+		/// <summary>
+		/// Waits until the operation has been completed or aborted.
+		/// </summary>
+		public abstract bool WaitForCompleted (int timeout);
+		
+		/// <summary>
+		/// Called when the debugging session has been disposed.
+		/// I must cause any call to WaitForCompleted to exit, even if the operation
+		/// has not been completed or can't be aborted.
+		/// </summary>
+		public abstract void Shutdown ();
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/BaseBacktrace.cs b/Mono.Debugging/Mono.Debugging.Evaluation/BaseBacktrace.cs
new file mode 100644
index 0000000..07a5dc1
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/BaseBacktrace.cs
@@ -0,0 +1,245 @@
+// 
+// Backtrace.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public abstract class BaseBacktrace: RemoteFrameObject, IBacktrace
+	{
+		Dictionary<int, FrameInfo> frameInfo = new Dictionary<int, FrameInfo> ();
+		
+		public BaseBacktrace (ObjectValueAdaptor adaptor)
+		{
+			Adaptor = adaptor;
+		}
+		
+		public abstract StackFrame[] GetStackFrames (int firstIndex, int lastIndex);
+		
+		public ObjectValueAdaptor Adaptor { get; set; }
+		
+		protected abstract EvaluationContext GetEvaluationContext (int frameIndex, EvaluationOptions options);
+		
+		public abstract int FrameCount { get; }
+	
+		public virtual ObjectValue[] GetLocalVariables (int frameIndex, EvaluationOptions options)
+		{
+			FrameInfo frame = GetFrameInfo (frameIndex, options, false);
+			List<ObjectValue> list = new List<ObjectValue> ();
+			
+			if (frame == null) {
+				ObjectValue val = Adaptor.CreateObjectValueAsync ("Local Variables", ObjectValueFlags.EvaluatingGroup, delegate {
+					frame = GetFrameInfo (frameIndex, options, true);
+					foreach (ValueReference var in frame.LocalVariables)
+						list.Add (var.CreateObjectValue (false, options));
+					return ObjectValue.CreateArray (null, new ObjectPath ("Local Variables"), "", list.Count, ObjectValueFlags.EvaluatingGroup, list.ToArray ());
+				});
+				return new ObjectValue [] { val };
+			}
+			
+			foreach (ValueReference var in frame.LocalVariables)
+				list.Add (var.CreateObjectValue (true, options));
+			return list.ToArray ();
+		}
+		
+		public virtual ObjectValue[] GetParameters (int frameIndex, EvaluationOptions options)
+		{
+			List<ObjectValue> vars = new List<ObjectValue> ();
+			
+			FrameInfo frame = GetFrameInfo (frameIndex, options, false);
+			if (frame == null) {
+				ObjectValue val = Adaptor.CreateObjectValueAsync ("Parameters", ObjectValueFlags.EvaluatingGroup, delegate {
+					frame = GetFrameInfo (frameIndex, options, true);
+					foreach (ValueReference var in frame.Parameters)
+						vars.Add (var.CreateObjectValue (false, options));
+					return ObjectValue.CreateArray (null, new ObjectPath ("Parameters"), "", vars.Count, ObjectValueFlags.EvaluatingGroup, vars.ToArray ());
+				});
+				return new ObjectValue [] { val };
+			}
+			
+			foreach (ValueReference var in frame.Parameters)
+				vars.Add (var.CreateObjectValue (true, options));
+			return vars.ToArray ();
+		}
+		
+		public virtual ObjectValue GetThisReference (int frameIndex, EvaluationOptions options)
+		{
+			FrameInfo frame = GetFrameInfo (frameIndex, options, false);
+			if (frame == null) {
+				return Adaptor.CreateObjectValueAsync ("this", ObjectValueFlags.EvaluatingGroup, delegate {
+					frame = GetFrameInfo (frameIndex, options, true);
+					ObjectValue[] vals;
+					if (frame.This != null)
+						vals = new ObjectValue[] { frame.This.CreateObjectValue (false, options) };
+					else
+						vals = new ObjectValue [0];
+					return ObjectValue.CreateArray (null, new ObjectPath ("this"), "", vals.Length, ObjectValueFlags.EvaluatingGroup, vals);
+				});
+			}
+			if (frame.This != null)
+				return frame.This.CreateObjectValue (true, options);
+			else
+				return null;
+		}
+		
+		public virtual ExceptionInfo GetException (int frameIndex, EvaluationOptions options)
+		{
+			FrameInfo frame = GetFrameInfo (frameIndex, options, false);
+			ObjectValue val;
+			if (frame == null) {
+				val = Adaptor.CreateObjectValueAsync (options.CurrentExceptionTag, ObjectValueFlags.EvaluatingGroup, delegate {
+					frame = GetFrameInfo (frameIndex, options, true);
+					ObjectValue[] vals;
+					if (frame.Exception != null)
+						vals = new ObjectValue[] { frame.Exception.CreateObjectValue (false, options) };
+					else
+						vals = new ObjectValue [0];
+					return ObjectValue.CreateArray (null, new ObjectPath (options.CurrentExceptionTag), "", vals.Length, ObjectValueFlags.EvaluatingGroup, vals);
+				});
+			}
+			else if (frame.Exception != null)
+				val = frame.Exception.CreateObjectValue (true, options);
+			else
+				return null;
+			return new ExceptionInfo (val);
+		}
+		
+		public virtual ObjectValue GetExceptionInstance (int frameIndex, EvaluationOptions options)
+		{
+			FrameInfo frame = GetFrameInfo (frameIndex, options, false);
+			if (frame == null) {
+				return Adaptor.CreateObjectValueAsync (options.CurrentExceptionTag, ObjectValueFlags.EvaluatingGroup, delegate {
+					frame = GetFrameInfo (frameIndex, options, true);
+					ObjectValue[] vals;
+					if (frame.Exception != null)
+						vals = new ObjectValue[] { frame.Exception.Exception.CreateObjectValue (false, options) };
+					else
+						vals = new ObjectValue [0];
+					return ObjectValue.CreateArray (null, new ObjectPath (options.CurrentExceptionTag), "", vals.Length, ObjectValueFlags.EvaluatingGroup, vals);
+				});
+			}
+			else if (frame.Exception != null)
+				return frame.Exception.Exception.CreateObjectValue (true, options);
+			else
+				return null;
+		}
+		
+		public virtual ObjectValue[] GetAllLocals (int frameIndex, EvaluationOptions options)
+		{
+			List<ObjectValue> locals = new List<ObjectValue> ();
+			
+			ObjectValue excObj = GetExceptionInstance (frameIndex, options);
+			if (excObj != null)
+				locals.Insert (0, excObj);
+			
+			locals.AddRange (GetLocalVariables (frameIndex, options));
+			locals.AddRange (GetParameters (frameIndex, options));
+			
+			locals.Sort (delegate (ObjectValue v1, ObjectValue v2) {
+				return v1.Name.CompareTo (v2.Name);
+			});
+
+			ObjectValue thisObj = GetThisReference (frameIndex, options);
+			if (thisObj != null)
+				locals.Insert (0, thisObj);
+			
+			return locals.ToArray ();
+		}
+		
+		public virtual ObjectValue[] GetExpressionValues (int frameIndex, string[] expressions, EvaluationOptions options)
+		{
+			if (Adaptor.IsEvaluating) {
+				List<ObjectValue> vals = new List<ObjectValue> ();
+				foreach (string exp in expressions) {
+					string tmpExp = exp;
+					ObjectValue val = Adaptor.CreateObjectValueAsync (tmpExp, ObjectValueFlags.Field, delegate {
+						EvaluationContext cctx = GetEvaluationContext (frameIndex, options);
+						return Adaptor.GetExpressionValue (cctx, tmpExp);
+					});
+					vals.Add (val);
+				}
+				return vals.ToArray ();
+			}
+			EvaluationContext ctx = GetEvaluationContext (frameIndex, options);
+			return ctx.Adapter.GetExpressionValuesAsync (ctx, expressions);
+		}
+		
+		public virtual CompletionData GetExpressionCompletionData (int frameIndex, string exp)
+		{
+			EvaluationContext ctx = GetEvaluationContext (frameIndex, EvaluationOptions.DefaultOptions);
+			return ctx.Adapter.GetExpressionCompletionData (ctx, exp);
+		}
+		
+		public virtual AssemblyLine[] Disassemble (int frameIndex, int firstLine, int count)
+		{
+			throw new System.NotImplementedException();
+		}
+		
+		public virtual ValidationResult ValidateExpression (int frameIndex, string expression, EvaluationOptions options)
+		{
+			EvaluationContext ctx = GetEvaluationContext (frameIndex, options);
+			return Adaptor.ValidateExpression (ctx, expression);
+		}
+		
+		FrameInfo GetFrameInfo (int frameIndex, EvaluationOptions options, bool ignoreEvalStatus)
+		{
+			FrameInfo finfo;
+			if (frameInfo.TryGetValue (frameIndex, out finfo))
+				return finfo;
+			
+			if (!ignoreEvalStatus && Adaptor.IsEvaluating)
+				return null;
+			
+			EvaluationContext ctx = GetEvaluationContext (frameIndex, options);
+			if (ctx == null)
+				return null;
+			
+			finfo = new FrameInfo ();
+			finfo.Context = ctx;
+			finfo.LocalVariables.AddRange (ctx.Adapter.GetLocalVariables (ctx));
+			finfo.Parameters.AddRange (ctx.Adapter.GetParameters (ctx));
+			finfo.This = ctx.Adapter.GetThisReference (ctx);
+			
+			ValueReference exp = ctx.Adapter.GetCurrentException (ctx);
+			if (exp != null)
+				finfo.Exception = new ExceptionInfoSource (ctx, exp);
+			frameInfo [frameIndex] = finfo;
+			return finfo;
+		}
+	}
+	
+	class FrameInfo
+	{
+		public EvaluationContext Context;
+		public List<ValueReference> LocalVariables = new List<ValueReference> ();
+		public List<ValueReference> Parameters = new List<ValueReference> ();
+		public ValueReference This;
+		public ExceptionInfoSource Exception;
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/BaseTypeViewSource.cs b/Mono.Debugging/Mono.Debugging.Evaluation/BaseTypeViewSource.cs
new file mode 100644
index 0000000..fd871e9
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/BaseTypeViewSource.cs
@@ -0,0 +1,89 @@
+// 
+// BaseTypeViewSource.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Backend;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class BaseTypeViewSource: RemoteFrameObject, IObjectValueSource
+	{
+		EvaluationContext ctx;
+		object type;
+		object obj;
+		IObjectSource objectSource;
+		
+		public BaseTypeViewSource (EvaluationContext ctx, IObjectSource objectSource, object type, object obj)
+		{
+			this.ctx = ctx;
+			this.type = type;
+			this.obj = obj;
+			this.objectSource = objectSource;
+		}
+		
+		public static ObjectValue CreateBaseTypeView (EvaluationContext ctx, IObjectSource objectSource, object type, object obj)
+		{
+			BaseTypeViewSource src = new BaseTypeViewSource (ctx, objectSource, type, obj);
+			src.Connect ();
+			string tname = ctx.Adapter.GetDisplayTypeName (ctx, type);
+			ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath ("base"), tname, "{" + tname + "}", ObjectValueFlags.Type|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
+			val.ChildSelector = "";
+			return val;
+		}
+		
+		#region IObjectValueSource implementation
+
+		public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			EvaluationContext cctx = ctx.WithOptions (options);
+			return cctx.Adapter.GetObjectValueChildren (cctx, objectSource, type, obj, index, count, false);
+		}
+
+		public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+
+		public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+		
+		public object GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		#endregion
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/EvaluationContext.cs b/Mono.Debugging/Mono.Debugging.Evaluation/EvaluationContext.cs
new file mode 100644
index 0000000..d7e0ac0
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/EvaluationContext.cs
@@ -0,0 +1,145 @@
+// EvaluationContext.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class EvaluationContext
+	{
+		EvaluationOptions options;
+
+		public ExpressionEvaluator Evaluator { get; set; }
+		public ObjectValueAdaptor Adapter { get; set; }
+		
+		public EvaluationOptions Options {
+			get { return options; }
+			set { options = value; }
+		}
+		
+		public bool CaseSensitive {
+			get { return Evaluator.CaseSensitive; }
+		}
+		
+		public virtual void WriteDebuggerError (Exception ex)
+		{
+		}
+
+		public virtual void WriteDebuggerOutput (string message, params object[] values)
+		{
+		}
+
+		public void WaitRuntimeInvokes ()
+		{
+		}
+		
+		public void AssertTargetInvokeAllowed ()
+		{
+			if (!Options.AllowTargetInvoke)
+				throw new ImplicitEvaluationDisabledException ();
+		}
+		
+		public EvaluationContext (EvaluationOptions options)
+		{
+			this.options = options;
+		}
+
+		public EvaluationContext Clone ()
+		{
+			EvaluationContext clone = (EvaluationContext) MemberwiseClone ();
+			clone.CopyFrom (this);
+			return clone;
+		}
+
+		public EvaluationContext WithOptions (EvaluationOptions options)
+		{
+			if (options == null || this.options == options)
+				return this;
+			else {
+				EvaluationContext clone = Clone ();
+				clone.options = options;
+				return clone;
+			}
+		}
+
+		public virtual void CopyFrom (EvaluationContext ctx)
+		{
+			options = ctx.options.Clone ();
+			Evaluator = ctx.Evaluator;
+			Adapter = ctx.Adapter;
+		}
+		
+		ExpressionValueSource expressionValueSource;
+		internal ExpressionValueSource ExpressionValueSource {
+			get {
+				if (expressionValueSource == null)
+					expressionValueSource = new ExpressionValueSource (this);
+				return expressionValueSource;
+			}
+		}
+	}
+	
+	class ExpressionValueSource: RemoteFrameObject, IObjectValueSource
+	{
+		EvaluationContext ctx;
+		
+		public ExpressionValueSource (EvaluationContext ctx)
+		{
+			this.ctx = ctx;
+			Connect ();
+		}
+		
+		public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			throw new System.NotImplementedException();
+		}
+		
+		public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			throw new System.NotImplementedException();
+		}
+		
+		public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			EvaluationContext c = ctx.WithOptions (options);
+			ObjectValue[] vals = c.Adapter.GetExpressionValuesAsync (c, new string[] { path.LastName });
+			return vals[0];
+		}
+		
+		public object GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new System.NotImplementedException ();
+		}
+		
+		public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			throw new System.NotImplementedException ();
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ExceptionInfoSource.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ExceptionInfoSource.cs
new file mode 100644
index 0000000..ca3360e
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ExceptionInfoSource.cs
@@ -0,0 +1,160 @@
+// 
+// ExceptionInfoSource.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class ExceptionInfoSource
+	{
+		ValueReference exception;
+		EvaluationContext ctx;
+		
+		public ExceptionInfoSource (EvaluationContext ctx, ValueReference exception)
+		{
+			this.exception = exception;
+			this.ctx = ctx;
+		}
+		
+		public ValueReference Exception {
+			get { return this.exception; }
+		}
+		
+		public ObjectValue CreateObjectValue (bool withTimeout, EvaluationOptions options)
+		{
+			string type = ctx.Adapter.GetTypeName (ctx, exception.Type);
+			
+			ObjectValue excInstance = exception.CreateObjectValue (withTimeout, options);
+			excInstance.Name = "Instance";
+			
+			ObjectValue messageValue = null;
+			
+			// Get the message
+			
+			if (withTimeout) {
+				messageValue = ctx.Adapter.CreateObjectValueAsync ("Message", ObjectValueFlags.None, delegate {
+					ValueReference mref = exception.GetChild ("Message", options);
+					if (mref != null) {
+						string val = (string) mref.ObjectValue;
+						return ObjectValue.CreatePrimitive (null, new ObjectPath ("Message"), "System.String", new EvaluationResult (val), ObjectValueFlags.Literal);
+					}
+					else
+						return ObjectValue.CreateUnknown ("Message");
+				});
+			} else {
+				ValueReference mref = exception.GetChild ("Message", options);
+				if (mref != null) {
+					string val = (string) mref.ObjectValue;
+					messageValue = ObjectValue.CreatePrimitive (null, new ObjectPath ("Message"), "System.String", new EvaluationResult (val), ObjectValueFlags.Literal);
+				}
+			}
+			if (messageValue == null)
+				messageValue = ObjectValue.CreateUnknown ("Message");
+			
+			messageValue.Name = "Message";
+
+			// Inner exception
+			
+			ObjectValue childExceptionValue = null;
+			
+			if (withTimeout) {
+				childExceptionValue = ctx.Adapter.CreateObjectValueAsync ("InnerException", ObjectValueFlags.None, delegate {
+					ValueReference inner = exception.GetChild ("InnerException", options);
+					if (inner != null && !ctx.Adapter.IsNull (ctx, inner.Value)) {
+						//Console.WriteLine ("pp got child:" + type);
+						ExceptionInfoSource innerSource = new ExceptionInfoSource (ctx, inner);
+						ObjectValue res = innerSource.CreateObjectValue (false, options);
+						return res;
+					}
+					else
+						return ObjectValue.CreateUnknown ("InnerException");
+				});
+			} else {
+				ValueReference inner = exception.GetChild ("InnerException", options);
+				if (inner != null && !ctx.Adapter.IsNull (ctx, inner.Value)) {
+					//Console.WriteLine ("pp got child:" + type);
+					ExceptionInfoSource innerSource = new ExceptionInfoSource (ctx, inner);
+					childExceptionValue = innerSource.CreateObjectValue (false, options);
+					childExceptionValue.Name = "InnerException";
+				}
+			}
+			if (childExceptionValue == null)
+				childExceptionValue = ObjectValue.CreateUnknown ("InnerException");
+			
+			// Stack trace
+			
+			ObjectValue stackTraceValue;
+			if (withTimeout) {
+				stackTraceValue = ctx.Adapter.CreateObjectValueAsync ("StackTrace", ObjectValueFlags.None, delegate {
+					return GetStackTrace (options);
+				});
+			} else
+				stackTraceValue = GetStackTrace (options);
+			
+			ObjectValue[] children = new ObjectValue [] { excInstance, messageValue, stackTraceValue, childExceptionValue };
+			return ObjectValue.CreateObject (null, new ObjectPath ("InnerException"), type, "", ObjectValueFlags.None, children);
+		}
+		
+		ObjectValue GetStackTrace (EvaluationOptions options)
+		{
+			ValueReference st = exception.GetChild ("StackTrace", options);
+			if (st == null)
+				return ObjectValue.CreateUnknown ("StackTrace");
+			string trace = st.ObjectValue as string;
+			if (trace == null)
+				return ObjectValue.CreateUnknown ("StackTrace");
+			
+			List<ObjectValue> frames = new List<ObjectValue> ();
+
+			var regex = new Regex ("at (.*) in (.*):(.*)");
+			
+			foreach (string sframe in trace.Split ('\n')) {
+				string txt = sframe.Trim (' ', '\r','\n');
+				string file = "";
+				int line = 0;
+				int col = 0;
+				var match = regex.Match (sframe);
+				if (match.Success) {
+					txt = match.Groups [1].ToString ();
+					file = match.Groups [2].ToString ();
+					int.TryParse (match.Groups [3].ToString (), out line);
+				}
+				ObjectValue fileVal = ObjectValue.CreatePrimitive (null, new ObjectPath("File"), "", new EvaluationResult (file), ObjectValueFlags.None);
+				ObjectValue lineVal = ObjectValue.CreatePrimitive (null, new ObjectPath("Line"), "", new EvaluationResult (line.ToString ()), ObjectValueFlags.None);
+				ObjectValue colVal = ObjectValue.CreatePrimitive (null, new ObjectPath("Column"), "", new EvaluationResult (col.ToString ()), ObjectValueFlags.None);
+				ObjectValue[] children = new ObjectValue[] { fileVal, lineVal, colVal };
+				ObjectValue frame = ObjectValue.CreateObject (null, new ObjectPath (), "", new EvaluationResult (txt), ObjectValueFlags.None, children);
+				frames.Add (frame);
+			}
+			return ObjectValue.CreateArray (null, new ObjectPath ("StackTrace"), "", frames.Count,ObjectValueFlags.None, frames.ToArray ());
+		}
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ExpressionEvaluator.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ExpressionEvaluator.cs
new file mode 100644
index 0000000..87bf9dd
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ExpressionEvaluator.cs
@@ -0,0 +1,232 @@
+// IExpressionEvaluator.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Text;
+using System.Globalization;
+using System.Runtime.Serialization;
+
+using Mono.Debugging.Backend;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public abstract class ExpressionEvaluator
+	{
+		public ValueReference Evaluate (EvaluationContext ctx, string exp)
+		{
+			return Evaluate (ctx, exp, null);
+		}
+		
+		public virtual ValueReference Evaluate (EvaluationContext ctx, string exp, object expectedType)
+		{
+			foreach (ValueReference var in ctx.Adapter.GetLocalVariables (ctx))
+				if (var.Name == exp)
+					return var;
+
+			foreach (ValueReference var in ctx.Adapter.GetParameters (ctx))
+				if (var.Name == exp)
+					return var;
+
+			ValueReference thisVar = ctx.Adapter.GetThisReference (ctx);
+			if (thisVar != null) {
+				if (thisVar.Name == exp)
+					return thisVar;
+				foreach (ValueReference cv in thisVar.GetChildReferences (ctx.Options))
+					if (cv.Name == exp)
+						return cv;
+			}
+			throw new EvaluatorException ("Invalid Expression: '{0}'", exp);
+		}
+		
+		public virtual ValidationResult ValidateExpression (EvaluationContext ctx, string expression)
+		{
+			return new ValidationResult (true, null);
+		}
+
+		public string TargetObjectToString (EvaluationContext ctx, object obj)
+		{
+			object res = ctx.Adapter.TargetObjectToObject (ctx, obj);
+			if (res == null)
+				return null;
+			
+			if (res is EvaluationResult)
+				return ((EvaluationResult) res).DisplayValue;
+			else
+				return res.ToString ();
+		}
+
+		public EvaluationResult TargetObjectToExpression (EvaluationContext ctx, object obj)
+		{
+			return ToExpression (ctx, ctx.Adapter.TargetObjectToObject (ctx, obj));
+		}
+		
+		public virtual EvaluationResult ToExpression (EvaluationContext ctx, object obj)
+		{
+			if (obj == null)
+				return new EvaluationResult ("null");
+			else if (obj is IntPtr) {
+				IntPtr p = (IntPtr) obj;
+				return new EvaluationResult ("0x" + p.ToInt64 ().ToString ("x"));
+			} else if (obj is char) {
+				char c = (char) obj;
+				string str;
+				if (c == '\'')
+					str = @"'\''";
+				else if (c == '"')
+					str = "'\"'";
+				else
+					str = EscapeString ("'" + c + "'");
+				return new EvaluationResult (str, ((int) c) + " " + str);
+			}
+			else if (obj is string)
+				return new EvaluationResult ("\"" + EscapeString ((string)obj) + "\"");
+			else if (obj is bool)
+				return new EvaluationResult (((bool)obj) ? "true" : "false");
+			else if (obj is decimal)
+				return new EvaluationResult (((decimal)obj).ToString (System.Globalization.CultureInfo.InvariantCulture));
+			else if (obj is EvaluationResult)
+				return (EvaluationResult) obj;
+			
+			if (ctx.Options.IntegerDisplayFormat == IntegerDisplayFormat.Hexadecimal) {
+				string fval = null;
+				if (obj is sbyte)
+					fval = ((sbyte)obj).ToString ("x2");
+				else if (obj is int)
+					fval = ((int)obj).ToString ("x4");
+				else if (obj is short)
+					fval = ((short)obj).ToString ("x8");
+				else if (obj is long)
+					fval = ((long)obj).ToString ("x16");
+				else if (obj is byte)
+					fval = ((byte)obj).ToString ("x2");
+				else if (obj is uint)
+					fval = ((uint)obj).ToString ("x4");
+				else if (obj is ushort)
+					fval = ((ushort)obj).ToString ("x8");
+				else if (obj is ulong)
+					fval = ((ulong)obj).ToString ("x16");
+				
+				if (fval != null)
+					return new EvaluationResult ("0x" + fval);
+			}
+			
+			return new EvaluationResult (obj.ToString ());
+		}
+
+		public static string EscapeString (string text)
+		{
+			StringBuilder sb = new StringBuilder ();
+			for (int i = 0; i < text.Length; i++) {
+				char c = text[i];
+				string txt;
+				switch (c) {
+				case '"': txt = "\\\""; break;
+				case '\0': txt = @"\0"; break;
+				case '\\': txt = @"\\"; break;
+				case '\a': txt = @"\a"; break;
+				case '\b': txt = @"\b"; break;
+				case '\f': txt = @"\f"; break;
+				case '\v': txt = @"\v"; break;
+				case '\n': txt = @"\n"; break;
+				case '\r': txt = @"\r"; break;
+				case '\t': txt = @"\t"; break;
+				default:
+					if (char.GetUnicodeCategory (c) == UnicodeCategory.OtherNotAssigned) {
+						sb.AppendFormat ("\\u{0:x4}", (int) c);
+					} else {
+						sb.Append (c);
+					}
+					continue;
+				}
+				sb.Append (txt);
+			}
+			return sb.ToString ();
+		}
+		
+		public virtual bool CaseSensitive {
+			get { return true; }
+		}
+
+		public abstract string Resolve (DebuggerSession session, SourceLocation location, string exp);
+	}
+	
+	[Serializable]
+	public class EvaluatorException: Exception
+	{
+		protected EvaluatorException (SerializationInfo info, StreamingContext context)
+			: base (info, context)
+		{
+		}
+		
+		public EvaluatorException (string msg, params object[] args): base (string.Format (msg, args))
+		{
+		}
+	}
+
+	[Serializable]
+	public class EvaluatorAbortedException: EvaluatorException
+	{
+		protected EvaluatorAbortedException (SerializationInfo info, StreamingContext context)
+			: base (info, context)
+		{
+		}
+
+		public EvaluatorAbortedException ()
+			: base ("Aborted.")
+		{
+		}
+	}
+
+	[Serializable]
+	public class NotSupportedExpressionException: EvaluatorException
+	{
+		protected NotSupportedExpressionException (SerializationInfo info, StreamingContext context)
+			: base (info, context)
+		{
+		}
+		
+		public NotSupportedExpressionException ()
+			: base ("Expression not supported.")
+		{
+		}
+	}
+
+	[Serializable]
+	public class ImplicitEvaluationDisabledException: EvaluatorException
+	{
+		protected ImplicitEvaluationDisabledException (SerializationInfo info, StreamingContext context)
+			: base (info, context)
+		{
+		}
+		
+		public ImplicitEvaluationDisabledException ( )
+			: base ("Implicit property and method evaluation is disabled.")
+		{
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/FilteredMembersSource.cs b/Mono.Debugging/Mono.Debugging.Evaluation/FilteredMembersSource.cs
new file mode 100644
index 0000000..b45028b
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/FilteredMembersSource.cs
@@ -0,0 +1,123 @@
+// 
+// FilteredMembersSource.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2009 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.Linq;
+using System.Text;
+using System.Reflection;
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+using System.Diagnostics;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class FilteredMembersSource: RemoteFrameObject, IObjectValueSource
+	{
+		object obj;
+		object type;
+		EvaluationContext ctx;
+		BindingFlags bindingFlags;
+		IObjectSource objectSource;
+
+		public FilteredMembersSource (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
+		{
+			this.ctx = ctx;
+			this.obj = obj;
+			this.type = type;
+			this.bindingFlags = bindingFlags;
+			this.objectSource = objectSource;
+		}
+
+		public static ObjectValue CreateNonPublicsNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
+		{
+			return CreateNode (ctx, objectSource, type, obj, bindingFlags, "Non-public members");
+		}
+		
+		public static ObjectValue CreateStaticsNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags)
+		{
+			return CreateNode (ctx, objectSource, type, obj, bindingFlags, "Static members");
+		}
+		
+		static ObjectValue CreateNode (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, BindingFlags bindingFlags, string label)
+		{
+			FilteredMembersSource src = new FilteredMembersSource (ctx, objectSource, type, obj, bindingFlags);
+			src.Connect ();
+			ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath (label), "", "", ObjectValueFlags.Group|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
+			val.ChildSelector = "";
+			return val;
+		}
+
+		public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			EvaluationContext cctx = ctx.WithOptions (options);
+			var names = new ObjectValueNameTracker (cctx);
+			object tdataType = null;
+			TypeDisplayData tdata = null;
+			List<ObjectValue> list = new List<ObjectValue> ();
+			foreach (ValueReference val in cctx.Adapter.GetMembersSorted (cctx, objectSource, type, obj, bindingFlags)) {
+				object decType = val.DeclaringType;
+				if (decType != null && decType != tdataType) {
+					tdataType = decType;
+					tdata = cctx.Adapter.GetTypeDisplayData (cctx, decType);
+				}
+				DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name);
+				if (state == DebuggerBrowsableState.Never)
+					continue;
+				ObjectValue oval = val.CreateObjectValue (options);
+				names.Disambiguate (val, oval);
+				list.Add (oval);
+			}
+			if ((bindingFlags & BindingFlags.NonPublic) == 0) {
+				BindingFlags newFlags = bindingFlags | BindingFlags.NonPublic;
+				newFlags &= ~BindingFlags.Public;
+				list.Add (CreateNonPublicsNode (cctx, objectSource, type, obj, newFlags));
+			}
+			return list.ToArray ();
+		}
+		
+		public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+
+		public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+		
+		public object GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ICollectionAdaptor.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ICollectionAdaptor.cs
new file mode 100644
index 0000000..aed8aed
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ICollectionAdaptor.cs
@@ -0,0 +1,41 @@
+// ICollectionAdaptor.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public interface ICollectionAdaptor
+	{
+		int[] GetDimensions ();
+		object GetElement (int[] indices);
+		Array GetElements (int[] indices, int count);
+		object ElementType { get; }
+		void SetElement (int[] indices, object val);
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/IObjectSource.cs b/Mono.Debugging/Mono.Debugging.Evaluation/IObjectSource.cs
new file mode 100644
index 0000000..6ed8487
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/IObjectSource.cs
@@ -0,0 +1,35 @@
+// 
+// IObjectSource.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Evaluation
+{
+	public interface IObjectSource
+	{
+		object Value { get; set; }
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/IStringAdaptor.cs b/Mono.Debugging/Mono.Debugging.Evaluation/IStringAdaptor.cs
new file mode 100644
index 0000000..7950d29
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/IStringAdaptor.cs
@@ -0,0 +1,37 @@
+// 
+// IStringAdaptor.cs
+//  
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+// 
+// Copyright (c) 2012 Xamarin Inc.
+// 
+// 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public interface IStringAdaptor
+	{
+		string Substring (int index, int length);
+		string Value { get; }
+		int Length { get; }
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/LiteralValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/LiteralValueReference.cs
new file mode 100644
index 0000000..b7658e1
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/LiteralValueReference.cs
@@ -0,0 +1,181 @@
+// LiteralValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class LiteralValueReference: ValueReference
+	{
+		bool isVoidReturn;
+		bool objLiteral;
+		bool objCreated;
+		object objValue;
+		object value;
+		object type;
+		string name;
+
+		LiteralValueReference (EvaluationContext ctx): base (ctx)
+		{
+		}
+
+		public static LiteralValueReference CreateTargetBaseObjectLiteral (EvaluationContext ctx, string name, object value)
+		{
+			LiteralValueReference val = new LiteralValueReference (ctx);
+			var type = ctx.Adapter.GetValueType (ctx, value);
+			val.name = name;
+			val.value = value;
+			val.type = ctx.Adapter.GetBaseType (ctx, type);
+			val.objCreated = true;
+			return val;
+		}
+
+		public static LiteralValueReference CreateTargetObjectLiteral (EvaluationContext ctx, string name, object value)
+		{
+			LiteralValueReference val = new LiteralValueReference (ctx);
+			val.name = name;
+			val.value = value;
+			val.type = ctx.Adapter.GetValueType (ctx, value);
+			val.objCreated = true;
+			return val;
+		}
+		
+		public static LiteralValueReference CreateObjectLiteral (EvaluationContext ctx, string name, object value)
+		{
+			LiteralValueReference val = new LiteralValueReference (ctx);
+			val.name = name;
+			val.objValue = value;
+			val.objLiteral = true;
+			return val;
+		}
+		
+		public static LiteralValueReference CreateVoidReturnLiteral (EvaluationContext ctx, string name)
+		{
+			LiteralValueReference val = new LiteralValueReference (ctx);
+			val.value = val.objValue = new EvaluationResult ("No return value.");
+			val.type = typeof (EvaluationResult);
+			val.isVoidReturn = true;
+			val.objLiteral = true;
+			val.objCreated = true;
+			val.name = name;
+			return val;
+		}
+		
+		void EnsureValueAndType ()
+		{
+			if (!objCreated && objLiteral) {
+				value = Context.Adapter.CreateValue (Context, objValue);
+				type = Context.Adapter.GetValueType (Context, value);
+				objCreated = true;
+			}
+		}
+		
+		public override object ObjectValue {
+			get {
+				if (objLiteral)
+					return objValue;
+
+				return base.ObjectValue;
+			}
+		}
+
+		public override object Value {
+			get {
+				EnsureValueAndType ();
+				return value;
+			}
+			set {
+				throw new NotSupportedException ();
+			}
+		}
+		
+		public override string Name {
+			get {
+				return name;
+			}
+		}
+		
+		public override object Type {
+			get {
+				EnsureValueAndType ();
+				return type;
+			}
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Field | ObjectValueFlags.ReadOnly;
+			}
+		}
+
+		protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
+		{
+			if (ObjectValue is EvaluationResult) {
+				EvaluationResult exp = (EvaluationResult) ObjectValue;
+				return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "", exp, Flags, null);
+			} else
+				return base.OnCreateObjectValue (options);
+		}
+
+		public override ValueReference GetChild (string name, EvaluationOptions options)
+		{
+			object obj = Value;
+			
+			if (obj == null)
+				return null;
+
+			if (name [0] == '[' && Context.Adapter.IsArray (Context, obj)) {
+				// Parse the array indices
+				string[] sinds = name.Substring (1, name.Length - 2).Split (',');
+				int[] indices = new int [sinds.Length];
+				for (int n=0; n<sinds.Length; n++)
+					indices [n] = int.Parse (sinds [n]);
+
+				return new ArrayValueReference (Context, obj, indices);
+			}
+
+			if (Context.Adapter.IsClassInstance (Context, obj)) {
+				// Note: This is the only difference with the default ValueReference implementation.
+				// We need this because the user may be requesting a base class's implementation, in
+				// which case 'Type' will be the BaseType instead of the actual type of the variable.
+				return Context.Adapter.GetMember (GetChildrenContext (options), this, Type, obj, name);
+			}
+
+			return null;
+		}
+
+		public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			if (isVoidReturn)
+				return new ObjectValue[0];
+
+			return base.GetChildren (path, index, count, options);
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluator.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluator.cs
new file mode 100644
index 0000000..0f18cf4
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluator.cs
@@ -0,0 +1,242 @@
+//
+// NRefactoryExpressionEvaluator.cs
+//
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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.Linq;
+using System.Collections.Generic;
+
+using Mono.Debugging.Client;
+
+using ICSharpCode.NRefactory.CSharp;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class NRefactoryExpressionEvaluator : ExpressionEvaluator
+	{
+		readonly Dictionary<string, ValueReference> userVariables = new Dictionary<string, ValueReference> ();
+
+		public override ValueReference Evaluate (EvaluationContext ctx, string expression, object expectedType)
+		{
+			expression = expression.TrimStart ();
+
+			if (expression.Length > 0 && expression[0] == '?')
+				expression = expression.Substring (1).Trim ();
+
+			if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3])) {
+				expression = expression.Substring (4).Trim (' ', '\t');
+				string variable = null;
+
+				for (int n = 0; n < expression.Length; n++) {
+					if (!char.IsLetterOrDigit (expression[n]) && expression[n] != '_') {
+						variable = expression.Substring (0, n);
+						if (!expression.Substring (n).Trim (' ', '\t').StartsWith ("=", StringComparison.Ordinal))
+							variable = null;
+						break;
+					}
+
+					if (n == expression.Length - 1) {
+						variable = expression;
+						expression = null;
+						break;
+					}
+				}
+
+				if (!string.IsNullOrEmpty (variable))
+					userVariables[variable] = new UserVariableReference (ctx, variable);
+
+				if (expression == null)
+					return null;
+			}
+
+			expression = ReplaceExceptionTag (expression, ctx.Options.CurrentExceptionTag);
+
+			var expr = new CSharpParser ().ParseExpression (expression);
+			if (expr == null)
+				throw new EvaluatorException ("Could not parse expression '{0}'", expression);
+
+			var evaluator = new NRefactoryExpressionEvaluatorVisitor (ctx, expression, expectedType, userVariables);
+			return expr.AcceptVisitor<ValueReference> (evaluator);
+		}
+
+		public override string Resolve (DebuggerSession session, SourceLocation location, string exp)
+		{
+			return Resolve (session, location, exp, false);
+		}
+
+		string Resolve (DebuggerSession session, SourceLocation location, string expression, bool tryTypeOf)
+		{
+			expression = expression.TrimStart ();
+
+			if (expression.Length > 0 && expression[0] == '?')
+				return "?" + Resolve (session, location, expression.Substring (1).Trim ());
+
+			if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3]))
+				return "var " + Resolve (session, location, expression.Substring (4).Trim (' ', '\t'));
+
+			expression = ReplaceExceptionTag (expression, session.Options.EvaluationOptions.CurrentExceptionTag);
+
+			Expression expr = new CSharpParser ().ParseExpression (expression);
+			if (expr == null)
+				return expression;
+
+			var resolver = new NRefactoryExpressionResolverVisitor (session, location, expression);
+			expr.AcceptVisitor (resolver);
+
+			string resolved = resolver.GetResolvedExpression ();
+			if (resolved == expression && !tryTypeOf && (expr is BinaryOperatorExpression) && IsTypeName (expression)) {
+				// This is a hack to be able to parse expressions such as "List<string>". The NRefactory parser
+				// can parse a single type name, so a solution is to wrap it around a typeof(). We do it if
+				// the evaluation fails.
+				string res = Resolve (session, location, "typeof(" + expression + ")", true);
+				return res.Substring (7, res.Length - 8);
+			}
+
+			return resolved;
+		}
+
+		public override ValidationResult ValidateExpression (EvaluationContext ctx, string expression)
+		{
+			expression = expression.TrimStart ();
+
+			if (expression.Length > 0 && expression[0] == '?')
+				expression = expression.Substring (1).Trim ();
+
+			if (expression.Length > 3 && expression.StartsWith ("var", StringComparison.Ordinal) && char.IsWhiteSpace (expression[3]))
+				expression = expression.Substring (4).Trim ();
+
+			expression = ReplaceExceptionTag (expression, ctx.Options.CurrentExceptionTag);
+
+			// Required as a workaround for a bug in the parser (it won't parse simple expressions like numbers)
+			if (!expression.EndsWith (";", StringComparison.Ordinal))
+				expression += ";";
+
+			var parser = new CSharpParser ();
+			parser.ParseExpression (expression);
+
+			if (parser.HasErrors)
+				return new ValidationResult (false, parser.Errors.First ().Message);
+
+			return new ValidationResult (true, null);
+		}
+
+		string ReplaceExceptionTag (string exp, string tag)
+		{
+			// FIXME: Don't replace inside string literals
+			return exp.Replace (tag, "__EXCEPTION_OBJECT__");
+		}
+
+		bool IsTypeName (string name)
+		{
+			int pos = 0;
+			bool res = ParseTypeName (name + "$", ref pos);
+			return res && pos >= name.Length;
+		}
+
+		bool ParseTypeName (string name, ref int pos)
+		{
+			EatSpaces (name, ref pos);
+			if (!ParseName (name, ref pos))
+				return false;
+
+			EatSpaces (name, ref pos);
+			if (!ParseGenericArgs (name, ref pos))
+				return false;
+
+			EatSpaces (name, ref pos);
+			if (!ParseIndexer (name, ref pos))
+				return false;
+
+			EatSpaces (name, ref pos);
+			return true;
+		}
+
+		void EatSpaces (string name, ref int pos)
+		{
+			while (char.IsWhiteSpace (name[pos]))
+				pos++;
+		}
+
+		bool ParseName (string name, ref int pos)
+		{
+			if (name[0] == 'g' && pos < name.Length - 8 && name.Substring (pos, 8) == "global::")
+				pos += 8;
+
+			do {
+				int oldp = pos;
+				while (char.IsLetterOrDigit (name[pos]))
+					pos++;
+
+				if (oldp == pos)
+					return false;
+
+				if (name[pos] != '.')
+					return true;
+
+				pos++;
+			}
+			while (true);
+		}
+
+		bool ParseGenericArgs (string name, ref int pos)
+		{
+			if (name [pos] != '<')
+				return true;
+
+			pos++;
+			EatSpaces (name, ref pos);
+
+			while (true) {
+				if (!ParseTypeName (name, ref pos))
+					return false;
+
+				EatSpaces (name, ref pos);
+				char c = name [pos++];
+
+				if (c == '>')
+					return true;
+
+				if (c == ',')
+					continue;
+
+				return false;
+			}
+		}
+
+		bool ParseIndexer (string name, ref int pos)
+		{
+			if (name [pos] != '[')
+				return true;
+
+			do {
+				pos++;
+				EatSpaces (name, ref pos);
+			} while (name [pos] == ',');
+
+			return name [pos++] == ']';
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluatorVisitor.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluatorVisitor.cs
new file mode 100644
index 0000000..af1e878
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionEvaluatorVisitor.cs
@@ -0,0 +1,1375 @@
+//
+// NRefactoryExpressionEvaluatorVisitor.cs
+//
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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.Runtime.InteropServices;
+using System.Reflection;
+
+using Mono.Debugging.Client;
+
+using ICSharpCode.NRefactory.CSharp;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class NRefactoryExpressionEvaluatorVisitor : IAstVisitor<ValueReference>
+	{
+		readonly Dictionary<string,ValueReference> userVariables;
+		readonly EvaluationOptions options;
+		readonly EvaluationContext ctx;
+		readonly object expectedType;
+		readonly string expression;
+
+		public NRefactoryExpressionEvaluatorVisitor (EvaluationContext ctx, string expression, object expectedType, Dictionary<string,ValueReference> userVariables)
+		{
+			this.ctx = ctx;
+			this.expression = expression;
+			this.expectedType = expectedType;
+			this.userVariables = userVariables;
+			this.options = ctx.Options;
+		}
+
+		static Exception ParseError (string message, params object[] args)
+		{
+			return new EvaluatorException (message, args);
+		}
+
+		static Exception NotSupported ()
+		{
+			return new NotSupportedExpressionException ();
+		}
+
+		static string ResolveTypeName (AstType type)
+		{
+			string name = type.ToString ();
+			if (name.StartsWith ("global::", StringComparison.Ordinal))
+				name = name.Substring ("global::".Length);
+			return name;
+		}
+
+		static long GetInteger (object val)
+		{
+			try {
+				return Convert.ToInt64 (val);
+			} catch {
+				throw ParseError ("Expected integer value.");
+			}
+		}
+
+		static string GetCommonOperationType (object v1, object v2)
+		{
+			if (v1 is double || v2 is double)
+				return "System.Double";
+
+			if (v1 is float || v2 is float)
+				return "System.Double";
+
+			return "System.Int64";
+		}
+
+		static Type GetCommonType (object v1, object v2)
+		{
+			int s1 = Marshal.SizeOf (v1);
+			if (IsUnsigned (s1))
+				s1 += 8;
+			int s2 = Marshal.SizeOf (v2);
+			if (IsUnsigned (s2))
+				s2 += 8;
+			if (s1 > s2)
+				return v1.GetType ();
+			return v2.GetType ();
+		}
+
+		static bool IsUnsigned (object v)
+		{
+			return (v is byte) || (v is ushort) || (v is uint) || (v is ulong);
+		}
+
+		static object EvaluateOperation (BinaryOperatorType op, double v1, double v2)
+		{
+			switch (op) {
+			case BinaryOperatorType.Add: return v1 + v2;
+			case BinaryOperatorType.Divide: return v1 / v2;
+			case BinaryOperatorType.Multiply: return v1 * v2;
+			case BinaryOperatorType.Subtract: return v1 - v2;
+			case BinaryOperatorType.GreaterThan: return v1 > v2;
+			case BinaryOperatorType.GreaterThanOrEqual: return v1 >= v2;
+			case BinaryOperatorType.LessThan: return v1 < v2;
+			case BinaryOperatorType.LessThanOrEqual: return v1 <= v2;
+			case BinaryOperatorType.Equality: return v1 == v2;
+			case BinaryOperatorType.InEquality: return v1 != v2;
+			default: throw ParseError ("Invalid binary operator.");
+			}
+		}
+
+		static object EvaluateOperation (BinaryOperatorType op, long v1, long v2)
+		{
+			switch (op) {
+			case BinaryOperatorType.Add: return v1 + v2;
+			case BinaryOperatorType.BitwiseAnd: return v1 & v2;
+			case BinaryOperatorType.BitwiseOr: return v1 | v2;
+			case BinaryOperatorType.ExclusiveOr: return v1 ^ v2;
+			case BinaryOperatorType.Divide: return v1 / v2;
+			case BinaryOperatorType.Modulus: return v1 % v2;
+			case BinaryOperatorType.Multiply: return v1 * v2;
+			case BinaryOperatorType.ShiftLeft: return v1 << (int) v2;
+			case BinaryOperatorType.ShiftRight: return v1 >> (int) v2;
+			case BinaryOperatorType.Subtract: return v1 - v2;
+			case BinaryOperatorType.GreaterThan: return v1 > v2;
+			case BinaryOperatorType.GreaterThanOrEqual: return v1 >= v2;
+			case BinaryOperatorType.LessThan: return v1 < v2;
+			case BinaryOperatorType.LessThanOrEqual: return v1 <= v2;
+			case BinaryOperatorType.Equality: return v1 == v2;
+			case BinaryOperatorType.InEquality: return v1 != v2;
+			default: throw ParseError ("Invalid binary operator.");
+			}
+		}
+
+		static object EvaluateStringOperation (BinaryOperatorType op, object v1, object v2)
+		{
+			switch (op) {
+			case BinaryOperatorType.Equality:
+				if (!(v1 == null || v1 is string) || !(v2 == null || v2 is string))
+					throw ParseError ("Invalid operands in binary operator.");
+				return ((string) v1) == ((string) v2);
+			case BinaryOperatorType.InEquality:
+				if (!(v1 == null || v1 is string) || !(v2 == null || v2 is string))
+					throw ParseError ("Invalid operands in binary operator.");
+				return ((string) v1) != ((string) v2);
+			case BinaryOperatorType.Add:
+				if (v1 == null) return v2.ToString ();
+				if (v2 == null) return v1.ToString ();
+				return v1.ToString () + v2.ToString ();
+			default:
+				throw ParseError ("Invalid operands in binary operator.");
+			}
+		}
+
+		static void ConvertValues<T> (EvaluationContext ctx, object actualV1, object actualV2, object toType, out T v1, out T v2)
+		{
+			try {
+				object c1 = ctx.Adapter.Cast (ctx, actualV1, toType);
+				v1 = (T) ctx.Adapter.TargetObjectToObject (ctx, c1);
+
+				object c2 = ctx.Adapter.Cast (ctx, actualV2, toType);
+				v2 = (T) ctx.Adapter.TargetObjectToObject (ctx, c2);
+			} catch {
+				throw ParseError ("Invalid operands in binary operator.");
+			}
+		}
+
+		static bool CheckReferenceEquality (EvaluationContext ctx, object v1, object v2)
+		{
+			if (v1 == null && v2 == null)
+				return true;
+
+			if (v1 == null || v2 == null)
+				return false;
+
+			object objectType = ctx.Adapter.GetType (ctx, "System.Object");
+			object[] argTypes = new object[] {
+				objectType, objectType
+			};
+			object[] args = new object[] {
+				v1, v2
+			};
+
+			object result = ctx.Adapter.RuntimeInvoke (ctx, objectType, null, "ReferenceEquals", argTypes, args);
+			var literal = LiteralValueReference.CreateTargetObjectLiteral (ctx, "result", result);
+
+			return (bool) literal.ObjectValue;
+		}
+
+		static bool CheckEquality (EvaluationContext ctx, bool negate, object v1, object v2)
+		{
+			if (v1 == null && v2 == null)
+				return true;
+
+			if (v1 == null || v2 == null)
+				return false;
+
+			string method = negate ? "op_Inequality" : "op_Equality";
+			object v1type = ctx.Adapter.GetValueType (ctx, v1);
+			object v2type = ctx.Adapter.GetValueType (ctx, v2);
+			object[] argTypes = new object[] { v2type };
+			object target, targetType;
+			object[] args;
+
+			if (ctx.Adapter.HasMethod (ctx, v1type, method, argTypes, BindingFlags.Instance | BindingFlags.Public)) {
+				args = new object[] { v2 };
+				targetType = v1type;
+				negate = false;
+				target = v1;
+			} else {
+				method = ctx.Adapter.IsValueType (v1type) ? "Equals" : "ReferenceEquals";
+				targetType = ctx.Adapter.GetType (ctx, "System.Object");
+				argTypes = new object[] { targetType, targetType };
+				args = new object[] { v1, v2 };
+				target = null;
+			}
+
+			object result = ctx.Adapter.RuntimeInvoke (ctx, targetType, target, method, argTypes, args);
+			var literal = LiteralValueReference.CreateTargetObjectLiteral (ctx, "result", result);
+			bool retval = (bool) literal.ObjectValue;
+
+			return negate ? !retval : retval;
+		}
+
+		ValueReference EvaluateBinaryOperatorExpression (BinaryOperatorType op, ValueReference left, Expression rightExp)
+		{
+			if (op == BinaryOperatorType.ConditionalAnd) {
+				object val = left.ObjectValue;
+				if (!(val is bool))
+					throw ParseError ("Left operand of logical And must be a boolean.");
+				if (!(bool)val)
+					return LiteralValueReference.CreateObjectLiteral (ctx, expression, false);
+				ValueReference vr = rightExp.AcceptVisitor<ValueReference> (this);
+				if (vr == null || ctx.Adapter.GetTypeName (ctx, vr.Type) != "System.Boolean")
+					throw ParseError ("Right operand of logical And must be a boolean.");
+				return vr;
+			}
+
+			if (op == BinaryOperatorType.ConditionalOr) {
+				object val = left.ObjectValue;
+				if (!(val is bool))
+					throw ParseError ("Left operand of logical Or must be a boolean.");
+				if ((bool)val)
+					return LiteralValueReference.CreateObjectLiteral (ctx, expression, true);
+				ValueReference vr = rightExp.AcceptVisitor<ValueReference> (this);
+				if (vr == null || ctx.Adapter.GetTypeName (ctx, vr.Type) != "System.Boolean")
+					throw ParseError ("Right operand of logical Or must be a boolean.");
+				return vr;
+			}
+
+			ValueReference right = rightExp.AcceptVisitor<ValueReference> (this);
+			object targetVal1 = left.Value;
+			object targetVal2 = right.Value;
+			object val1 = left.ObjectValue;
+			object val2 = right.ObjectValue;
+
+			if (op == BinaryOperatorType.Add) {
+				if (val1 is string || val2 is string) {
+					if (!(val1 is string) && val1 != null)
+						val1 = ctx.Adapter.CallToString (ctx, targetVal1);
+					if (!(val2 is string) && val2 != null)
+						val2 = ctx.Adapter.CallToString (ctx, targetVal2);
+					return LiteralValueReference.CreateObjectLiteral (ctx, expression, (string) val1 + (string) val2);
+				}
+			}
+
+			if ((op == BinaryOperatorType.ExclusiveOr) && (val1 is bool) && (val2 is bool))
+				return LiteralValueReference.CreateObjectLiteral (ctx, expression, (bool) val1 ^ (bool) val2);
+
+			if ((val1 == null || !ctx.Adapter.IsPrimitive (ctx, targetVal1)) && (val2 == null || !ctx.Adapter.IsPrimitive (ctx, targetVal2))) {
+				switch (op) {
+				case BinaryOperatorType.Equality:
+					return LiteralValueReference.CreateObjectLiteral (ctx, expression, CheckEquality (ctx, false, targetVal1, targetVal2));
+				case BinaryOperatorType.InEquality:
+					return LiteralValueReference.CreateObjectLiteral (ctx, expression, CheckEquality (ctx, true, targetVal1, targetVal2));
+				}
+			}
+
+			object res;
+
+			if (val1 is string || val2 is string) {
+				res = EvaluateStringOperation (op, val1, val2);
+			} else {
+				if (val1 == null || val2 == null || (val1 is bool) || (val2 is bool))
+					throw ParseError ("Invalid operands in binary operator.");
+
+				string opTypeName = GetCommonOperationType (val1, val2);
+				object opType = ctx.Adapter.GetType (ctx, opTypeName);
+
+				if (opTypeName == "System.Double") {
+					double v1, v2;
+
+					ConvertValues<double> (ctx, targetVal1, targetVal2, opType, out v1, out v2);
+					res = EvaluateOperation (op, v1, v2);
+				} else {
+					long v1, v2;
+
+					ConvertValues<long> (ctx, targetVal1, targetVal2, opType, out v1, out v2);
+					res = EvaluateOperation (op, v1, v2);
+				}
+			}
+
+			if (!(res is bool) && !(res is string)) {
+				if (ctx.Adapter.IsEnum (ctx, targetVal1)) {
+					object tval = ctx.Adapter.Cast (ctx, ctx.Adapter.CreateValue (ctx, res), ctx.Adapter.GetValueType (ctx, targetVal1));
+					return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, tval);
+				}
+
+				if (ctx.Adapter.IsEnum (ctx, targetVal2)) {
+					object tval = ctx.Adapter.Cast (ctx, ctx.Adapter.CreateValue (ctx, res), ctx.Adapter.GetValueType (ctx, targetVal2));
+					return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, tval);
+				}
+
+				res = Convert.ChangeType (res, GetCommonType (val1, val2));
+			}
+
+			return LiteralValueReference.CreateObjectLiteral (ctx, expression, res);
+		}
+
+		static string ResolveType (EvaluationContext ctx, MemberReferenceExpression mre, List<object> args)
+		{
+			string parent, name;
+
+			if (mre.Target is MemberReferenceExpression) {
+				parent = ResolveType (ctx, (MemberReferenceExpression) mre.Target, args);
+			} else if (mre.Target is IdentifierExpression) {
+				parent = ((IdentifierExpression) mre.Target).Identifier;
+			} else {
+				return null;
+			}
+
+			name = parent + "." + mre.MemberName;
+			if (mre.TypeArguments.Count > 0) {
+				name += "`" + mre.TypeArguments.Count;
+				foreach (var arg in mre.TypeArguments) {
+					object resolved = arg.Resolve (ctx);
+
+					if (resolved == null)
+						return null;
+
+					args.Add (resolved);
+				}
+			}
+
+			return name;
+		}
+
+		static object ResolveType (EvaluationContext ctx, MemberReferenceExpression mre)
+		{
+			var args = new List<object> ();
+			var name = ResolveType (ctx, mre, args);
+
+			if (name == null)
+				return null;
+
+			if (args.Count > 0)
+				return ctx.Adapter.GetType (ctx, name, args.ToArray ());
+
+			return ctx.Adapter.GetType (ctx, name);
+		}
+
+		static ValueReference ResolveTypeValueReference (EvaluationContext ctx, MemberReferenceExpression mre)
+		{
+			object resolved = ResolveType (ctx, mre);
+
+			if (resolved != null) {
+				ctx.Adapter.ForceLoadType (ctx, resolved);
+
+				return new TypeValueReference (ctx, resolved);
+			}
+
+			throw ParseError ("Could not resolve type: {0}", mre);
+		}
+
+		static ValueReference ResolveTypeValueReference (EvaluationContext ctx, AstType type)
+		{
+			object resolved = type.Resolve (ctx);
+
+			if (resolved != null) {
+				ctx.Adapter.ForceLoadType (ctx, resolved);
+
+				return new TypeValueReference (ctx, resolved);
+			}
+
+			throw ParseError ("Could not resolve type: {0}", ResolveTypeName (type));
+		}
+
+		#region IAstVisitor implementation
+
+		public ValueReference VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitAsExpression (AsExpression asExpression)
+		{
+			var type = asExpression.Type.AcceptVisitor<ValueReference> (this) as TypeValueReference;
+			if (type == null)
+				throw ParseError ("Invalid type in cast.");
+
+			var val = asExpression.Expression.AcceptVisitor<ValueReference> (this);
+			var result = ctx.Adapter.TryCast (ctx, val.Value, type.Type);
+
+			if (result == null)
+				return new NullValueReference (ctx, type.Type);
+
+			return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, result);
+		}
+
+		public ValueReference VisitAssignmentExpression (AssignmentExpression assignmentExpression)
+		{
+			if (!options.AllowMethodEvaluation)
+				throw NotSupported ();
+
+			var left = assignmentExpression.Left.AcceptVisitor<ValueReference> (this);
+
+			if (assignmentExpression.Operator == AssignmentOperatorType.Assign) {
+				var right = assignmentExpression.Right.AcceptVisitor<ValueReference> (this);
+				left.Value = right.Value;
+			} else {
+				BinaryOperatorType op;
+
+				switch (assignmentExpression.Operator) {
+				case AssignmentOperatorType.Add:         op = BinaryOperatorType.Add; break;
+				case AssignmentOperatorType.Subtract:    op = BinaryOperatorType.Subtract; break;
+				case AssignmentOperatorType.Multiply:    op = BinaryOperatorType.Multiply; break;
+				case AssignmentOperatorType.Divide:      op = BinaryOperatorType.Divide; break;
+				case AssignmentOperatorType.Modulus:     op = BinaryOperatorType.Modulus; break;
+				case AssignmentOperatorType.ShiftLeft:   op = BinaryOperatorType.ShiftLeft; break;
+				case AssignmentOperatorType.ShiftRight:  op = BinaryOperatorType.ShiftRight; break;
+				case AssignmentOperatorType.BitwiseAnd:  op = BinaryOperatorType.BitwiseAnd; break;
+				case AssignmentOperatorType.BitwiseOr:   op = BinaryOperatorType.BitwiseOr; break;
+				case AssignmentOperatorType.ExclusiveOr: op = BinaryOperatorType.ExclusiveOr; break;
+				default: throw ParseError ("Invalid operator in assignment.");
+				}
+
+				var result = EvaluateBinaryOperatorExpression (op, left, assignmentExpression.Right);
+				left.Value = result.Value;
+			}
+
+			return left;
+		}
+
+		public ValueReference VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression)
+		{
+			var self = ctx.Adapter.GetThisReference (ctx);
+
+			if (self != null)
+				return LiteralValueReference.CreateTargetBaseObjectLiteral (ctx, expression, self.Value);
+
+			throw ParseError ("'base' reference not available in static methods.");
+		}
+
+		public ValueReference VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression)
+		{
+			var left = binaryOperatorExpression.Left.AcceptVisitor<ValueReference> (this);
+
+			return EvaluateBinaryOperatorExpression (binaryOperatorExpression.Operator, left, binaryOperatorExpression.Right);
+		}
+
+		public ValueReference VisitCastExpression (CastExpression castExpression)
+		{
+			var type = castExpression.Type.AcceptVisitor<ValueReference> (this) as TypeValueReference;
+			if (type == null)
+				throw ParseError ("Invalid type in cast.");
+
+			var val = castExpression.Expression.AcceptVisitor<ValueReference> (this);
+			object result = ctx.Adapter.TryCast (ctx, val.Value, type.Type);
+			if (result == null)
+				throw ParseError ("Invalid cast.");
+
+			return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, result);
+		}
+
+		public ValueReference VisitCheckedExpression (CheckedExpression checkedExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitConditionalExpression (ConditionalExpression conditionalExpression)
+		{
+			ValueReference val = conditionalExpression.Condition.AcceptVisitor<ValueReference> (this);
+			if (val is TypeValueReference)
+				throw NotSupported ();
+
+			if ((bool) val.ObjectValue)
+				return conditionalExpression.TrueExpression.AcceptVisitor<ValueReference> (this);
+
+			return conditionalExpression.FalseExpression.AcceptVisitor<ValueReference> (this);
+		}
+
+		public ValueReference VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitDirectionExpression (DirectionExpression directionExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitIdentifierExpression (IdentifierExpression identifierExpression)
+		{
+			var name = identifierExpression.Identifier;
+
+			if (name == "__EXCEPTION_OBJECT__")
+				return ctx.Adapter.GetCurrentException (ctx);
+
+			// Look in user defined variables
+
+			ValueReference userVar;
+			if (userVariables.TryGetValue (name, out userVar))
+				return userVar;
+
+			// Look in variables
+
+			ValueReference var = ctx.Adapter.GetLocalVariable (ctx, name);
+			if (var != null)
+				return var;
+
+			// Look in parameters
+
+			var = ctx.Adapter.GetParameter (ctx, name);
+			if (var != null)
+				return var;
+
+			// Look in instance fields and properties
+
+			ValueReference self = ctx.Adapter.GetThisReference (ctx);
+
+			if (self != null) {
+				// check for fields and properties in this instance
+				var = ctx.Adapter.GetMember (ctx, self, self.Type, self.Value, name);
+				if (var != null)
+					return var;
+			}
+
+			// Look in static fields & properties of the enclosing type and all parent types
+
+			object type = ctx.Adapter.GetEnclosingType (ctx);
+			object vtype = type;
+
+			while (vtype != null) {
+				// check for static fields and properties
+				var = ctx.Adapter.GetMember (ctx, null, vtype, null, name);
+				if (var != null)
+					return var;
+
+				vtype = ctx.Adapter.GetParentType (ctx, vtype);
+			}
+
+			// Look in types
+
+			vtype = ctx.Adapter.GetType (ctx, name);
+			if (vtype != null)
+				return new TypeValueReference (ctx, vtype);
+
+			// Look in nested types
+
+			if (type != null) {
+				foreach (object ntype in ctx.Adapter.GetNestedTypes (ctx, type)) {
+					if (TypeValueReference.GetTypeName (ctx.Adapter.GetTypeName (ctx, ntype)) == name)
+						return new TypeValueReference (ctx, ntype);
+				}
+
+				string[] namespaces = ctx.Adapter.GetImportedNamespaces (ctx);
+				if (namespaces.Length > 0) {
+					// Look in namespaces
+					foreach (string ns in namespaces) {
+						string nm = ns + "." + name;
+						vtype = ctx.Adapter.ForceLoadType (ctx, nm);
+						if (vtype != null)
+							return new TypeValueReference (ctx, vtype);
+					}
+
+					foreach (string ns in namespaces) {
+						if (ns == name || ns.StartsWith (name + ".", StringComparison.InvariantCulture))
+							return new NamespaceValueReference (ctx, name);
+					}
+				}
+			}
+
+			if (self == null && ctx.Adapter.HasMember (ctx, type, name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
+				string message = string.Format ("An object reference is required for the non-static field, method, or property '{0}.{1}'.",
+				                                ctx.Adapter.GetDisplayTypeName (ctx, type), name);
+				throw ParseError (message);
+			}
+
+			throw ParseError ("Unknown identifier: {0}", name);
+		}
+
+		public ValueReference VisitIndexerExpression (IndexerExpression indexerExpression)
+		{
+			int n = 0;
+
+			var target = indexerExpression.Target.AcceptVisitor<ValueReference> (this);
+			if (target is TypeValueReference)
+				throw NotSupported ();
+
+			if (ctx.Adapter.IsArray (ctx, target.Value)) {
+				int[] indexes = new int [indexerExpression.Arguments.Count];
+
+				foreach (var arg in indexerExpression.Arguments) {
+					var index = arg.AcceptVisitor<ValueReference> (this);
+					indexes[n++] = (int) Convert.ChangeType (index.ObjectValue, typeof (int));
+				}
+
+				return new ArrayValueReference (ctx, target.Value, indexes);
+			}
+
+			object[] args = new object [indexerExpression.Arguments.Count];
+			foreach (var arg in indexerExpression.Arguments)
+				args[n++] = arg.AcceptVisitor<ValueReference> (this).Value;
+
+			var indexer = ctx.Adapter.GetIndexerReference (ctx, target.Value, args);
+			if (indexer == null)
+				throw NotSupported ();
+
+			return indexer;
+		}
+
+		string ResolveMethodName (MemberReferenceExpression mre, out object[] typeArgs)
+		{
+			if (mre.TypeArguments.Count > 0) {
+				List<object> args = new List<object> ();
+
+				foreach (var arg in mre.TypeArguments) {
+					var type = arg.AcceptVisitor (this);
+					args.Add (type.Type);
+				}
+
+				typeArgs = args.ToArray ();
+			} else {
+				typeArgs = null;
+			}
+
+			return mre.MemberName;
+		}
+
+		public ValueReference VisitInvocationExpression (InvocationExpression invocationExpression)
+		{
+			if (!options.AllowMethodEvaluation)
+				throw NotSupported ();
+
+			bool invokeBaseMethod = false;
+			ValueReference target = null;
+			string methodName;
+
+			object[] types = new object [invocationExpression.Arguments.Count];
+			object[] args = new object [invocationExpression.Arguments.Count];
+			object[] typeArgs = null;
+			int n = 0;
+
+			foreach (var arg in invocationExpression.Arguments) {
+				var vref = arg.AcceptVisitor<ValueReference> (this);
+				args[n] = vref.Value;
+				types[n] = ctx.Adapter.GetValueType (ctx, args[n]);
+				n++;
+			}
+
+			if (invocationExpression.Target is MemberReferenceExpression) {
+				var field = (MemberReferenceExpression) invocationExpression.Target;
+				target = field.Target.AcceptVisitor<ValueReference> (this);
+				if (field.Target is BaseReferenceExpression)
+					invokeBaseMethod = true;
+				methodName = ResolveMethodName (field, out typeArgs);
+			} else if (invocationExpression.Target is IdentifierExpression) {
+				methodName = ((IdentifierExpression) invocationExpression.Target).Identifier;
+				var vref = ctx.Adapter.GetThisReference (ctx);
+
+				if (vref != null && ctx.Adapter.HasMethod (ctx, vref.Type, methodName, BindingFlags.Instance)) {
+					// There is an instance method for 'this', although it may not have an exact signature match. Check it now.
+					if (ctx.Adapter.HasMethod (ctx, vref.Type, methodName, types, BindingFlags.Instance)) {
+						target = vref;
+					} else {
+						// There isn't an instance method with exact signature match.
+						// If there isn't a static method, then use the instance method,
+						// which will report the signature match error when invoked
+						object etype = ctx.Adapter.GetEnclosingType (ctx);
+						if (!ctx.Adapter.HasMethod (ctx, etype, methodName, types, BindingFlags.Static))
+							target = vref;
+					}
+				} else {
+					if (ctx.Adapter.HasMethod (ctx, ctx.Adapter.GetEnclosingType (ctx), methodName, types, BindingFlags.Instance))
+						throw new EvaluatorException ("Cannot invoke an instance method from a static method.");
+					target = null;
+				}
+			} else {
+				throw NotSupported ();
+			}
+
+			object vtype = target != null ? target.Type : ctx.Adapter.GetEnclosingType (ctx);
+			object vtarget = (target is TypeValueReference) || target == null ? null : target.Value;
+
+			if (invokeBaseMethod) {
+				vtype = ctx.Adapter.GetBaseType (ctx, vtype);
+			} else if (target != null && !ctx.Adapter.HasMethod (ctx, vtype, methodName, typeArgs, types, BindingFlags.Instance | BindingFlags.Static)) {
+				// Look for LINQ extension methods...
+				var linq = ctx.Adapter.GetType (ctx, "System.Linq.Enumerable");
+				if (linq != null) {
+					object[] xtypeArgs = typeArgs;
+
+					if (xtypeArgs == null) {
+						// try to infer the generic type arguments from the type of the object...
+						object xtype = vtype;
+						while (xtype != null && !ctx.Adapter.IsGenericType (ctx, xtype))
+							xtype = ctx.Adapter.GetBaseType (ctx, xtype);
+
+						if (xtype != null)
+							xtypeArgs = ctx.Adapter.GetTypeArgs (ctx, xtype);
+					}
+
+					if (xtypeArgs != null) {
+						var xtypes = new object[types.Length + 1];
+						Array.Copy (types, 0, xtypes, 1, types.Length);
+						xtypes[0] = vtype;
+
+						var xargs = new object[args.Length + 1];
+						Array.Copy (args, 0, xargs, 1, args.Length);
+						xargs[0] = vtarget;
+
+						if (ctx.Adapter.HasMethod (ctx, linq, methodName, xtypeArgs, xtypes, BindingFlags.Static)) {
+							vtarget = null;
+							vtype = linq;
+
+							typeArgs = xtypeArgs;
+							types = xtypes;
+							args = xargs;
+						}
+					}
+				}
+			}
+
+			object result = ctx.Adapter.RuntimeInvoke (ctx, vtype, vtarget, methodName, typeArgs, types, args);
+			if (result != null)
+				return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, result);
+
+			return LiteralValueReference.CreateVoidReturnLiteral (ctx, expression);
+		}
+
+		public ValueReference VisitIsExpression (IsExpression isExpression)
+		{
+			// FIXME: we could probably implement this one...
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitLambdaExpression (LambdaExpression lambdaExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression)
+		{
+			if (memberReferenceExpression.TypeArguments.Count > 0)
+				return ResolveTypeValueReference (ctx, memberReferenceExpression);
+
+			var target = memberReferenceExpression.Target.AcceptVisitor<ValueReference> (this);
+			var member = target.GetChild (memberReferenceExpression.MemberName, ctx.Options);
+
+			if (member == null) {
+				if (!(target is TypeValueReference)) {
+					if (ctx.Adapter.IsNull (ctx, target.Value))
+						throw new EvaluatorException ("{0} is null", target.Name);
+				}
+
+				throw ParseError ("Unknown member: {0}", memberReferenceExpression.MemberName);
+			}
+
+			return member;
+		}
+
+		public ValueReference VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitNamedExpression (NamedExpression namedExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression)
+		{
+			var type = objectCreateExpression.Type.AcceptVisitor<ValueReference> (this) as TypeValueReference;
+			var args = new List<object> ();
+
+			foreach (var arg in objectCreateExpression.Arguments) {
+				var val = arg.AcceptVisitor<ValueReference> (this);
+				args.Add (val != null ? val.Value : null);
+			}
+
+			return LiteralValueReference.CreateTargetObjectLiteral (ctx, expression, ctx.Adapter.CreateValue (ctx, type.Type, args.ToArray ()));
+		}
+
+		public ValueReference VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression)
+		{
+			return parenthesizedExpression.Expression.AcceptVisitor<ValueReference> (this);
+		}
+
+		public ValueReference VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitPrimitiveExpression (PrimitiveExpression primitiveExpression)
+		{
+			if (primitiveExpression.Value != null)
+				return LiteralValueReference.CreateObjectLiteral (ctx, expression, primitiveExpression.Value);
+
+			if (expectedType != null)
+				return new NullValueReference (ctx, expectedType);
+
+			return new NullValueReference (ctx, ctx.Adapter.GetType (ctx, "System.Object"));
+		}
+
+		public ValueReference VisitSizeOfExpression (SizeOfExpression sizeOfExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitStackAllocExpression (StackAllocExpression stackAllocExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression)
+		{
+			var self = ctx.Adapter.GetThisReference (ctx);
+
+			if (self == null)
+				throw ParseError ("'this' reference not available in the current evaluation context.");
+
+			return self;
+		}
+
+		public ValueReference VisitTypeOfExpression (TypeOfExpression typeOfExpression)
+		{
+			var name = ResolveTypeName (typeOfExpression.Type);
+			var type = typeOfExpression.Type.Resolve (ctx);
+
+			if (type == null)
+				throw ParseError ("Could not load type: {0}", name);
+
+			object result = ctx.Adapter.CreateTypeObject (ctx, type);
+			if (result == null)
+				throw NotSupported ();
+
+			return LiteralValueReference.CreateTargetObjectLiteral (ctx, name, result);
+		}
+
+		public ValueReference VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression)
+		{
+			var type = typeReferenceExpression.Type.Resolve (ctx);
+
+			if (type != null) {
+				ctx.Adapter.ForceLoadType (ctx, type);
+
+				return new TypeValueReference (ctx, type);
+			}
+
+			var name = ResolveTypeName (typeReferenceExpression.Type);
+
+			// Assume it is a namespace.
+			return new NamespaceValueReference (ctx, name);
+		}
+
+		public ValueReference VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression)
+		{
+			var vref = unaryOperatorExpression.Expression.AcceptVisitor<ValueReference> (this);
+			var val = vref.ObjectValue;
+			object newVal;
+			long num;
+
+			switch (unaryOperatorExpression.Operator) {
+			case UnaryOperatorType.BitNot:
+				num = ~GetInteger (val);
+				val = Convert.ChangeType (num, val.GetType ());
+				break;
+			case UnaryOperatorType.Minus:
+				num = -GetInteger (val);
+				val = Convert.ChangeType (num, val.GetType ());
+				break;
+			case UnaryOperatorType.Not:
+				if (!(val is bool))
+					throw ParseError ("Expected boolean type in Not operator.");
+
+				val = !(bool) val;
+				break;
+			case UnaryOperatorType.PostDecrement:
+				num = GetInteger (val) - 1;
+				newVal = Convert.ChangeType (num, val.GetType ());
+				vref.Value = ctx.Adapter.CreateValue (ctx, newVal);
+				break;
+			case UnaryOperatorType.Decrement:
+				num = GetInteger (val) - 1;
+				val = Convert.ChangeType (num, val.GetType ());
+				vref.Value = ctx.Adapter.CreateValue (ctx, val);
+				break;
+			case UnaryOperatorType.PostIncrement:
+				num = GetInteger (val) + 1;
+				newVal = Convert.ChangeType (num, val.GetType ());
+				vref.Value = ctx.Adapter.CreateValue (ctx, newVal);
+				break;
+			case UnaryOperatorType.Increment:
+				num = GetInteger (val) + 1;
+				val = Convert.ChangeType (num, val.GetType ());
+				vref.Value = ctx.Adapter.CreateValue (ctx, val);
+				break;
+			case UnaryOperatorType.Plus:
+				break;
+			default:
+				throw NotSupported ();
+			}
+
+			return LiteralValueReference.CreateObjectLiteral (ctx, expression, val);
+		}
+
+		public ValueReference VisitUncheckedExpression (UncheckedExpression uncheckedExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitEmptyExpression (EmptyExpression emptyExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryExpression (QueryExpression queryExpression)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryFromClause (QueryFromClause queryFromClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryLetClause (QueryLetClause queryLetClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryWhereClause (QueryWhereClause queryWhereClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryJoinClause (QueryJoinClause queryJoinClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryOrderClause (QueryOrderClause queryOrderClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryOrdering (QueryOrdering queryOrdering)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQuerySelectClause (QuerySelectClause querySelectClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitQueryGroupClause (QueryGroupClause queryGroupClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitAttribute (ICSharpCode.NRefactory.CSharp.Attribute attribute)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitAttributeSection (AttributeSection attributeSection)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitTypeDeclaration (TypeDeclaration typeDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUsingAliasDeclaration (UsingAliasDeclaration usingAliasDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUsingDeclaration (UsingDeclaration usingDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitBlockStatement (BlockStatement blockStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitBreakStatement (BreakStatement breakStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitCheckedStatement (CheckedStatement checkedStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitContinueStatement (ContinueStatement continueStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitDoWhileStatement (DoWhileStatement doWhileStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitEmptyStatement (EmptyStatement emptyStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitExpressionStatement (ExpressionStatement expressionStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitFixedStatement (FixedStatement fixedStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitForeachStatement (ForeachStatement foreachStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitForStatement (ForStatement forStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitGotoStatement (GotoStatement gotoStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitIfElseStatement (IfElseStatement ifElseStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitLabelStatement (LabelStatement labelStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitLockStatement (LockStatement lockStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitReturnStatement (ReturnStatement returnStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitSwitchStatement (SwitchStatement switchStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitSwitchSection (SwitchSection switchSection)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitCaseLabel (CaseLabel caseLabel)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitThrowStatement (ThrowStatement throwStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitTryCatchStatement (TryCatchStatement tryCatchStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitCatchClause (CatchClause catchClause)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUncheckedStatement (UncheckedStatement uncheckedStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUnsafeStatement (UnsafeStatement unsafeStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitUsingStatement (UsingStatement usingStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitWhileStatement (WhileStatement whileStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitAccessor (Accessor accessor)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitConstructorInitializer (ConstructorInitializer constructorInitializer)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitEventDeclaration (EventDeclaration eventDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitCustomEventDeclaration (CustomEventDeclaration customEventDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitFieldDeclaration (FieldDeclaration fieldDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitMethodDeclaration (MethodDeclaration methodDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitParameterDeclaration (ParameterDeclaration parameterDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitVariableInitializer (VariableInitializer variableInitializer)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitSyntaxTree (SyntaxTree syntaxTree)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitSimpleType (SimpleType simpleType)
+		{
+			return ResolveTypeValueReference (ctx, simpleType);
+		}
+
+		public ValueReference VisitMemberType (MemberType memberType)
+		{
+			return ResolveTypeValueReference (ctx, memberType);
+		}
+
+		public ValueReference VisitComposedType (ComposedType composedType)
+		{
+			return ResolveTypeValueReference (ctx, composedType);
+		}
+
+		public ValueReference VisitArraySpecifier (ArraySpecifier arraySpecifier)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitPrimitiveType (PrimitiveType primitiveType)
+		{
+			return ResolveTypeValueReference (ctx, primitiveType);
+		}
+
+		public ValueReference VisitComment (Comment comment)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitWhitespace (WhitespaceNode whitespaceNode)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitText (TextNode textNode)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitNewLine (NewLineNode newLineNode)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitPreProcessorDirective (PreProcessorDirective preProcessorDirective)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitDocumentationReference (DocumentationReference documentationReference)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitConstraint (Constraint constraint)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitCSharpTokenNode (CSharpTokenNode cSharpTokenNode)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitIdentifier (Identifier identifier)
+		{
+			throw NotSupported ();
+		}
+
+		public ValueReference VisitPatternPlaceholder (AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern)
+		{
+			throw NotSupported ();
+		}
+
+		#endregion
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionResolverVisitor.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionResolverVisitor.cs
new file mode 100644
index 0000000..9369de6
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExpressionResolverVisitor.cs
@@ -0,0 +1,131 @@
+//
+// NRefactoryExpressionResolverVisitor.cs
+//
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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.Text;
+using System.Collections.Generic;
+
+using ICSharpCode.NRefactory.CSharp;
+
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	// FIXME: if we passed the DebuggerSession and SourceLocation into the NRefactoryExpressionEvaluatorVisitor,
+	// we wouldn't need to do this resolve step.
+	public class NRefactoryExpressionResolverVisitor : DepthFirstAstVisitor
+	{
+		readonly List<Replacement> replacements = new List<Replacement> ();
+		readonly SourceLocation location;
+		readonly DebuggerSession session;
+		readonly string expression;
+
+		class Replacement
+		{
+			public string NewText;
+			public int Offset;
+			public int Length;
+		}
+
+		public NRefactoryExpressionResolverVisitor (DebuggerSession session, SourceLocation location, string expression)
+		{
+			this.expression = expression.Replace ("\n", "").Replace ("\r", "");
+			this.session = session;
+			this.location = location;
+		}
+
+		internal string GetResolvedExpression ()
+		{
+			if (replacements.Count == 0)
+				return expression;
+
+			replacements.Sort ((Replacement r1, Replacement r2) => r1.Offset.CompareTo (r2.Offset));
+			StringBuilder sb = new StringBuilder ();
+			int i = 0;
+
+			foreach (Replacement r in replacements) {
+				sb.Append (expression, i, r.Offset - i);
+				sb.Append (r.NewText);
+				i = r.Offset + r.Length;
+			}
+
+			Replacement last = replacements [replacements.Count - 1];
+			sb.Append (expression, last.Offset + last.Length, expression.Length - (last.Offset + last.Length));
+
+			return sb.ToString ();
+		}
+
+		void ReplaceType (string name, int offset, int length)
+		{
+			string type = session.ResolveIdentifierAsType (name, location);
+			if (!string.IsNullOrEmpty (type)) {
+				type = "global::" + type;
+				Replacement r = new Replacement () { Offset = offset, Length = length, NewText = type };
+				replacements.Add (r);
+			}
+		}
+
+		void ReplaceType (AstType type)
+		{
+			int length = type.EndLocation.Column - type.StartLocation.Column;
+			int offset = type.StartLocation.Column - 1;
+
+			ReplaceType (type.ToString (), offset, length);
+		}
+
+		public override void VisitIdentifierExpression (IdentifierExpression identifierExpression)
+		{
+			base.VisitIdentifierExpression (identifierExpression);
+
+			int length = identifierExpression.EndLocation.Column - identifierExpression.StartLocation.Column;
+			int offset = identifierExpression.StartLocation.Column - 1;
+
+			ReplaceType (identifierExpression.Identifier, offset, length);
+		}
+
+		public override void VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression)
+		{
+			ReplaceType (typeReferenceExpression.Type);
+		}
+
+		public override void VisitComposedType (ComposedType composedType)
+		{
+			// Note: we specifically do not handle this case because the 'base' implementation will eventually
+			// call VisitMemberType() or VisitSimpleType() on the ComposedType.BaseType which is all we really
+			// care to resolve.
+			base.VisitComposedType (composedType);
+		}
+
+		public override void VisitMemberType (MemberType memberType)
+		{
+			ReplaceType (memberType);
+		}
+
+		public override void VisitSimpleType (SimpleType simpleType)
+		{
+			ReplaceType (simpleType);
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExtensions.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExtensions.cs
new file mode 100644
index 0000000..cb8eb0d
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NRefactoryExtensions.cs
@@ -0,0 +1,182 @@
+//
+// NRefactoryExtensions.cs
+//
+// Author: Jeffrey Stedfast <jeff at xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc.
+//
+// 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 ICSharpCode.NRefactory.CSharp;
+
+namespace Mono.Debugging.Evaluation
+{
+	public static class NRefactoryExtensions
+	{
+		#region AstType
+
+		public static object Resolve (this AstType type, EvaluationContext ctx)
+		{
+			var args = new List<object> ();
+			var name = type.Resolve (ctx, args);
+
+			//if (name.StartsWith ("global::", StringComparison.Ordinal))
+			//	name = name.Substring ("global::".Length);
+
+			if (args.Count > 0)
+				return ctx.Adapter.GetType (ctx, name, args.ToArray ());
+
+			return ctx.Adapter.GetType (ctx, name);
+		}
+
+		static string Resolve (this AstType type, EvaluationContext ctx, List<object> args)
+		{
+			if (type is PrimitiveType)
+				return Resolve ((PrimitiveType) type, ctx, args);
+			else if (type is ComposedType)
+				return Resolve ((ComposedType) type, ctx, args);
+			else if (type is MemberType)
+				return Resolve ((MemberType) type, ctx, args);
+			else if (type is SimpleType)
+				return Resolve ((SimpleType) type, ctx, args);
+
+			return null;
+		}
+
+		#endregion AstType
+
+		#region ComposedType
+
+		static string Resolve (this ComposedType type, EvaluationContext ctx, List<object> args)
+		{
+			string name;
+
+			if (type.HasNullableSpecifier) {
+				args.Insert (0, type.BaseType.Resolve (ctx));
+				name = "System.Nullable`1";
+			} else {
+				name = type.BaseType.Resolve (ctx, args);
+			}
+
+			if (type.PointerRank > 0)
+				name += new string ('*', type.PointerRank);
+
+			if (type.ArraySpecifiers.Count > 0) {
+				foreach (var spec in type.ArraySpecifiers) {
+					if (spec.Dimensions > 1)
+						name += "[" + new string (',', spec.Dimensions - 1) + "]";
+					else
+						name += "[]";
+				}
+			}
+
+			return name;
+		}
+		
+		#endregion ComposedType
+
+		#region MemberType
+
+		static string Resolve (this MemberType type, EvaluationContext ctx, List<object> args)
+		{
+			string name;
+
+			if (!type.IsDoubleColon) {
+				var parent = type.Target.Resolve (ctx, args);
+				name = parent + "." + type.MemberName;
+			} else {
+				name = type.MemberName;
+			}
+
+			if (type.TypeArguments.Count > 0) {
+				name += "`" + type.TypeArguments.Count;
+				foreach (var arg in type.TypeArguments) {
+					object resolved;
+
+					if ((resolved = arg.Resolve (ctx)) == null)
+						return null;
+
+					args.Add (resolved);
+				}
+			}
+
+			return name;
+		}
+
+		#endregion MemberType
+
+		#region PrimitiveType
+
+		public static string Resolve (this PrimitiveType type)
+		{
+			switch (type.Keyword) {
+			case "bool":    return "System.Boolean";
+			case "sbyte":   return "System.SByte";
+			case "byte":    return "System.Byte";
+			case "char":    return "System.Char";
+			case "short":   return "System.Int16";
+			case "ushort":  return "System.UInt16";
+			case "int":     return "System.Int32";
+			case "uint":    return "System.UInt32";
+			case "long":    return "System.Int64";
+			case "ulong":   return "System.UInt64";
+			case "float":   return "System.Single";
+			case "double":  return "System.Double";
+			case "decimal": return "System.Decimal";
+			case "string":  return "System.String";
+			case "object":  return "System.Object";
+			case "void":    return "System.Void";
+			default: return null;
+			}
+		}
+
+		static string Resolve (this PrimitiveType type, EvaluationContext ctx, List<object> args)
+		{
+			return Resolve (type);
+		}
+
+		#endregion PrimitiveType
+
+		#region SimpleType
+
+		static string Resolve (this SimpleType type, EvaluationContext ctx, List<object> args)
+		{
+			string name = type.Identifier;
+
+			if (type.TypeArguments.Count > 0) {
+				name += "`" + type.TypeArguments.Count;
+				foreach (var arg in type.TypeArguments) {
+					object resolved;
+
+					if ((resolved = arg.Resolve (ctx)) == null)
+						return null;
+
+					args.Add (resolved);
+				}
+			}
+
+			return name;
+		}
+
+		#endregion SimpleType
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NamespaceValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NamespaceValueReference.cs
new file mode 100644
index 0000000..5975124
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NamespaceValueReference.cs
@@ -0,0 +1,150 @@
+// NamespaceValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class NamespaceValueReference: ValueReference
+	{
+		readonly string namspace;
+		readonly string name;
+
+		public NamespaceValueReference (EvaluationContext ctx, string name) : base (ctx)
+		{
+			this.namspace = name;
+			int i = namspace.LastIndexOf ('.');
+			if (i != -1)
+				this.name = namspace.Substring (i+1);
+			else
+				this.name = namspace;
+		}
+
+		public override object Value {
+			get {
+				throw new NotSupportedException();
+			}
+			set {
+				throw new NotSupportedException();
+			}
+		}
+
+		
+		public override object Type {
+			get {
+				throw new NotSupportedException();
+			}
+		}
+
+		
+		public override object ObjectValue {
+			get {
+				throw new NotSupportedException ();
+			}
+		}
+
+		
+		public override string Name {
+			get {
+				return name;
+			}
+		}
+
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Namespace;
+			}
+		}
+
+		public override ValueReference GetChild (string name, EvaluationOptions options)
+		{
+			string newNs = namspace + "." + name;
+			
+			EvaluationContext ctx = GetContext (options);
+			object t = ctx.Adapter.GetType (ctx, newNs);
+			if (t != null)
+				return new TypeValueReference (ctx, t);
+			
+			return new NamespaceValueReference (ctx, newNs);
+		}
+
+		public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			List<ObjectValue> obs = new List<ObjectValue> ();
+			foreach (ValueReference val in GetChildReferences (options)) {
+				obs.Add (val.CreateObjectValue (options));
+			}
+			return obs.ToArray ();
+		}
+
+		public override IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
+		{
+			// Child types
+
+			string[] childNamespaces;
+			string[] childTypes;
+
+			EvaluationContext ctx = GetContext (options);
+			ctx.Adapter.GetNamespaceContents (ctx, namspace, out childNamespaces, out childTypes);
+
+			List<ValueReference> list = new List<ValueReference> ();
+			foreach (string typeName in childTypes) {
+				object tt = ctx.Adapter.GetType (ctx, typeName);
+				if (tt != null)
+					list.Add (new TypeValueReference (ctx, tt));
+			}
+			list.Sort (delegate (ValueReference v1, ValueReference v2) {
+				return v1.Name.CompareTo (v2.Name);
+			});
+			
+			// Child namespaces
+			
+			List<ValueReference> listNs = new List<ValueReference> ();
+			foreach (string ns in childNamespaces)
+				listNs.Add (new NamespaceValueReference (ctx, ns));
+			listNs.Sort (delegate (ValueReference v1, ValueReference v2) {
+				return v1.Name.CompareTo (v2.Name);
+			});
+			list.AddRange (listNs);
+			return list;
+		}
+
+		protected override Mono.Debugging.Client.ObjectValue OnCreateObjectValue (EvaluationOptions options)
+		{
+			return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "<namespace>", namspace, Flags, null);
+		}
+
+		public override string CallToString ()
+		{
+			return namspace;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/NullValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/NullValueReference.cs
new file mode 100644
index 0000000..5f67c85
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/NullValueReference.cs
@@ -0,0 +1,97 @@
+// NullValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class NullValueReference: ValueReference
+	{
+		readonly object type;
+		object obj;
+		bool valueCreated;
+
+		public NullValueReference (EvaluationContext ctx, object type) : base (ctx)
+		{
+			this.type = type;
+		}
+	
+		public override object Value {
+			get {
+				if (!valueCreated) {
+					valueCreated = true;
+					obj = Context.Adapter.CreateNullValue (Context, type);
+				}
+				return obj;
+			}
+			set {
+				throw new NotSupportedException();
+			}
+		}
+		
+		public override object Type {
+			get {
+				return type;
+			}
+		}
+		
+		public override object ObjectValue {
+			get {
+				return null;
+			}
+		}
+
+		public override string Name {
+			get {
+				return "null";
+			}
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Literal;
+			}
+		}
+
+		protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
+		{
+			string tn = Context.Adapter.GetTypeName (GetContext (options), Type);
+			return Mono.Debugging.Client.ObjectValue.CreateObject (null, new ObjectPath (Name), tn, "null", Flags, null);
+		}
+
+		public override ValueReference GetChild (string name, EvaluationOptions options)
+		{
+			return null;
+		}
+
+		public override ObjectValue[] GetChildren (Mono.Debugging.Client.ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			return new ObjectValue [0];
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ObjectValueAdaptor.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ObjectValueAdaptor.cs
new file mode 100644
index 0000000..950d2fe
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ObjectValueAdaptor.cs
@@ -0,0 +1,1380 @@
+// 
+// ObjectValueAdaptor.cs
+//  
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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.Linq;
+using System.Text;
+using System.Reflection;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+using Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+
+namespace Mono.Debugging.Evaluation
+{
+	public abstract class ObjectValueAdaptor: IDisposable
+	{
+		readonly Dictionary<string, TypeDisplayData> typeDisplayData = new Dictionary<string, TypeDisplayData> ();
+
+		// Time to wait while evaluating before switching to async mode
+		public int DefaultEvaluationWaitTime { get; set; }
+		
+		public event EventHandler<BusyStateEventArgs> BusyStateChanged;
+
+		static readonly Dictionary<string, string> CSharpTypeNames = new Dictionary<string, string> ();
+		readonly AsyncEvaluationTracker asyncEvaluationTracker = new AsyncEvaluationTracker ();
+		readonly AsyncOperationManager asyncOperationManager = new AsyncOperationManager ();
+
+		static ObjectValueAdaptor ()
+		{
+			CSharpTypeNames["System.Void"]    = "void";
+			CSharpTypeNames["System.Object"]  = "object";
+			CSharpTypeNames["System.Boolean"] = "bool";
+			CSharpTypeNames["System.Byte"]    = "byte";
+			CSharpTypeNames["System.SByte"]   = "sbyte";
+			CSharpTypeNames["System.Char"]    = "char";
+			CSharpTypeNames["System.Enum"]    = "enum";
+			CSharpTypeNames["System.Int16"]   = "short";
+			CSharpTypeNames["System.Int32"]   = "int";
+			CSharpTypeNames["System.Int64"]   = "long";
+			CSharpTypeNames["System.UInt16"]  = "ushort";
+			CSharpTypeNames["System.UInt32"]  = "uint";
+			CSharpTypeNames["System.UInt64"]  = "ulong";
+			CSharpTypeNames["System.Single"]  = "float";
+			CSharpTypeNames["System.Double"]  = "double";
+			CSharpTypeNames["System.Decimal"] = "decimal";
+			CSharpTypeNames["System.String"]  = "string";
+		}
+		
+		protected ObjectValueAdaptor ()
+		{
+			DefaultEvaluationWaitTime = 100;
+			
+			asyncOperationManager.BusyStateChanged += delegate(object sender, BusyStateEventArgs e) {
+				OnBusyStateChanged (e);
+			};
+			asyncEvaluationTracker.WaitTime = DefaultEvaluationWaitTime;
+		}
+		
+		public void Dispose ()
+		{
+			asyncEvaluationTracker.Dispose ();
+			asyncOperationManager.Dispose ();
+		}
+
+		public ObjectValue CreateObjectValue (EvaluationContext ctx, IObjectValueSource source, ObjectPath path, object obj, ObjectValueFlags flags)
+		{
+			try {
+				return CreateObjectValueImpl (ctx, source, path, obj, flags);
+			} catch (EvaluatorAbortedException ex) {
+				return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
+			} catch (EvaluatorException ex) {
+				return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
+			}
+		}
+		
+		public virtual string GetDisplayTypeName (string typeName)
+		{
+			return GetDisplayTypeName (typeName.Replace ('+', '.'), 0, typeName.Length);
+		}
+		
+		public string GetDisplayTypeName (EvaluationContext ctx, object type)
+		{
+			return GetDisplayTypeName (GetTypeName (ctx, type));
+		}
+		
+		string GetDisplayTypeName (string typeName, int startIndex, int endIndex)
+		{
+			// Note: '[' denotes the start of an array
+			//       '`' denotes a generic type
+			//       ',' denotes the start of the assembly name
+			int tokenIndex = typeName.IndexOfAny (new char [] { '[', '`', ',' }, startIndex, endIndex - startIndex);
+			List<string> genericArgs = null;
+			string array = string.Empty;
+			int genericEndIndex = -1;
+			int typeEndIndex;
+			
+		retry:
+			if (tokenIndex == -1) // Simple type
+				return GetShortTypeName (typeName.Substring (startIndex, endIndex - startIndex));
+			
+			if (typeName[tokenIndex] == ',') // Simple type with an assembly name
+				return GetShortTypeName (typeName.Substring (startIndex, tokenIndex - startIndex));
+			
+			// save the index of the end of the type name
+			typeEndIndex = tokenIndex;
+			
+			// decode generic args first, if this is a generic type
+			if (typeName[tokenIndex] == '`') {
+				genericEndIndex = typeName.IndexOf ('[', tokenIndex, endIndex - tokenIndex);
+				if (genericEndIndex == -1) {
+					// Mono's compiler seems to generate non-generic types with '`'s in the name
+					// e.g. __EventHandler`1_FileCopyEventArgs_DelegateFactory_2
+					tokenIndex = typeName.IndexOfAny (new char [] { '[', ',' }, tokenIndex, endIndex - tokenIndex);
+					goto retry;
+				}
+				
+				tokenIndex = genericEndIndex;
+				genericArgs = GetGenericArguments (typeName, ref tokenIndex, endIndex);
+			}
+			
+			// decode array rank info
+			while (tokenIndex < endIndex && typeName[tokenIndex] == '[') {
+				int arrayEndIndex = typeName.IndexOf (']', tokenIndex, endIndex - tokenIndex);
+				if (arrayEndIndex == -1)
+					break;
+				arrayEndIndex++;
+				array += typeName.Substring (tokenIndex, arrayEndIndex - tokenIndex);
+				tokenIndex = arrayEndIndex;
+			}
+			
+			string name = typeName.Substring (startIndex, typeEndIndex - startIndex);
+			
+			if (genericArgs == null)
+				return GetShortTypeName (name) + array;
+			
+			// Use the prettier name for nullable types
+			if (name == "System.Nullable" && genericArgs.Count == 1)
+				return genericArgs[0] + "?" + array;
+			
+			// Insert the generic arguments next to each type.
+			// for example: Foo`1+Bar`1[System.Int32,System.String]
+			// is converted to: Foo<int>.Bar<string>
+			StringBuilder sb = new StringBuilder (name);
+			int i = typeEndIndex + 1;
+			int genericIndex = 0;
+			int argCount, next;
+			
+			while (i < genericEndIndex) {
+				// decode the argument count
+				argCount = 0;
+				while (i < genericEndIndex && char.IsDigit (typeName[i])) {
+					argCount = (argCount * 10) + (typeName[i] - '0');
+					i++;
+				}
+				
+				// insert the argument types
+				sb.Append ('<');
+				while (argCount > 0 && genericIndex < genericArgs.Count) {
+					sb.Append (genericArgs[genericIndex++]);
+					if (--argCount > 0)
+						sb.Append (',');
+				}
+				sb.Append ('>');
+				
+				// Find the end of the next generic type component
+				if ((next = typeName.IndexOf ('`', i, genericEndIndex - i)) == -1)
+					next = genericEndIndex;
+				
+				// Append the next generic type component
+				sb.Append (typeName.Substring (i, next - i));
+				
+				i = next + 1;
+			}
+			
+			return sb.ToString () + array;
+		}
+		
+		List<string> GetGenericArguments (string typeName, ref int i, int endIndex)
+		{
+			// Get a list of the generic arguments.
+			// When returning, i points to the next char after the closing ']'
+			List<string> genericArgs = new List<string> ();
+			i++;
+			while (i < endIndex && typeName [i] != ']') {
+				int pend = FindTypeEnd (typeName, i, endIndex);
+				bool escaped = typeName [i] == '[';
+				genericArgs.Add (GetDisplayTypeName (typeName, escaped ? i + 1 : i, escaped ? pend - 1 : pend));
+				i = pend;
+				if (i < endIndex && typeName[i] == ',')
+					i++;
+			}
+			i++;
+			return genericArgs;
+		}
+		
+		int FindTypeEnd (string s, int i, int endIndex)
+		{
+			int bc = 0;
+			while (i < endIndex) {
+				char c = s[i];
+				if (c == '[')
+					bc++;
+				else if (c == ']') {
+					if (bc > 0)
+						bc--;
+					else
+						return i;
+				}
+				else if (c == ',' && bc == 0)
+					return i;
+				i++;
+			}
+			return i;
+		}
+		
+		public virtual string GetShortTypeName (string typeName)
+		{
+			int star = typeName.IndexOf ('*');
+			string name, ptr, csharp;
+
+			if (star != -1) {
+				name = typeName.Substring (0, star);
+				ptr = typeName.Substring (star);
+			} else {
+				ptr = string.Empty;
+				name = typeName;
+			}
+
+			if (CSharpTypeNames.TryGetValue (name, out csharp))
+				return csharp + ptr;
+
+			return typeName;
+		}
+		
+		public virtual void OnBusyStateChanged (BusyStateEventArgs e)
+		{
+			EventHandler<BusyStateEventArgs> evnt = BusyStateChanged;
+			if (evnt != null)
+				evnt (this, e);
+		}
+
+		public abstract ICollectionAdaptor CreateArrayAdaptor (EvaluationContext ctx, object arr);
+		public abstract IStringAdaptor CreateStringAdaptor (EvaluationContext ctx, object str);
+
+		public abstract bool IsNull (EvaluationContext ctx, object val);
+		public abstract bool IsPrimitive (EvaluationContext ctx, object val);
+		public abstract bool IsPointer (EvaluationContext ctx, object val);
+		public abstract bool IsString (EvaluationContext ctx, object val);
+		public abstract bool IsArray (EvaluationContext ctx, object val);
+		public abstract bool IsEnum (EvaluationContext ctx, object val);
+		public abstract bool IsValueType (object type);
+		public abstract bool IsClass (EvaluationContext ctx, object type);
+		public abstract object TryCast (EvaluationContext ctx, object val, object type);
+
+		public abstract object GetValueType (EvaluationContext ctx, object val);
+		public abstract string GetTypeName (EvaluationContext ctx, object type);
+		public abstract object[] GetTypeArgs (EvaluationContext ctx, object type);
+		public abstract object GetBaseType (EvaluationContext ctx, object type);
+
+		public virtual bool IsGenericType (EvaluationContext ctx, object type)
+		{
+			return type != null && GetTypeName (ctx, type).IndexOf ('`') != -1;
+		}
+
+		public virtual bool IsNullableType (EvaluationContext ctx, object type)
+		{
+			return type != null && GetTypeName (ctx, type).StartsWith ("System.Nullable`1", StringComparison.Ordinal);
+		}
+
+		public virtual bool NullableHasValue (EvaluationContext ctx, object type, object obj)
+		{
+			ValueReference hasValue = GetMember (ctx, type, obj, "HasValue");
+
+			return (bool) hasValue.ObjectValue;
+		}
+
+		public virtual ValueReference NullableGetValue (EvaluationContext ctx, object type, object obj)
+		{
+			return GetMember (ctx, type, obj, "Value");
+		}
+		
+		public virtual bool IsFlagsEnumType (EvaluationContext ctx, object type)
+		{
+			return true;
+		}
+		
+		public virtual IEnumerable<EnumMember> GetEnumMembers (EvaluationContext ctx, object type)
+		{
+			object longType = GetType (ctx, "System.Int64");
+			TypeValueReference tref = new TypeValueReference (ctx, type);
+			foreach (ValueReference cr in tref.GetChildReferences (ctx.Options)) {
+				object c = TryCast (ctx, cr.Value, longType);
+				if (c == null)
+					continue;
+				long val = (long) TargetObjectToObject (ctx, c);
+				EnumMember em = new EnumMember () { Name = cr.Name, Value = val };
+				yield return em;
+			}
+		}
+		
+		public object GetBaseType (EvaluationContext ctx, object type, bool includeObjectClass)
+		{
+			object bt = GetBaseType (ctx, type);
+			string tn = bt != null ? GetTypeName (ctx, bt) : null;
+			if (!includeObjectClass && bt != null && (tn == "System.Object" || tn == "System.ValueType"))
+				return null;
+			else
+				return bt;
+		}
+
+		public virtual bool IsClassInstance (EvaluationContext ctx, object val)
+		{
+			return IsClass (ctx, GetValueType (ctx, val));
+		}
+		
+		public virtual bool IsExternalType (EvaluationContext ctx, object type)
+		{
+			return false;
+		}
+		
+		public object GetType (EvaluationContext ctx, string name)
+		{
+			return GetType (ctx, name, null);
+		}
+
+		public abstract object GetType (EvaluationContext ctx, string name, object[] typeArgs);
+
+		public virtual string GetValueTypeName (EvaluationContext ctx, object val)
+		{
+			return GetTypeName (ctx, GetValueType (ctx, val));
+		}
+
+		public virtual object CreateTypeObject (EvaluationContext ctx, object type)
+		{
+			return default (object);
+		}
+
+		public virtual bool IsTypeLoaded (EvaluationContext ctx, string typeName)
+		{
+			object t = GetType (ctx, typeName);
+
+			if (t == null)
+				return false;
+
+			return IsTypeLoaded (ctx, t);
+		}
+
+		public virtual bool IsTypeLoaded (EvaluationContext ctx, object type)
+		{
+			return true;
+		}
+		
+		public virtual object ForceLoadType (EvaluationContext ctx, string typeName)
+		{
+			object t = GetType (ctx, typeName);
+
+			if (t == null || IsTypeLoaded (ctx, t))
+				return t;
+
+			if (ForceLoadType (ctx, t))
+				return t;
+
+			return null;
+		}
+
+		public virtual bool ForceLoadType (EvaluationContext ctx, object type)
+		{
+			return true;
+		}
+
+		public abstract object CreateValue (EvaluationContext ctx, object value);
+
+		public abstract object CreateValue (EvaluationContext ctx, object type, params object[] args);
+
+		public abstract object CreateNullValue (EvaluationContext ctx, object type);
+
+		public virtual object GetBaseValue (EvaluationContext ctx, object val)
+		{
+			return val;
+		}
+
+		public virtual string[] GetImportedNamespaces (EvaluationContext ctx)
+		{
+			return new string[0];
+		}
+
+		public virtual void GetNamespaceContents (EvaluationContext ctx, string namspace, out string[] childNamespaces, out string[] childTypes)
+		{
+			childTypes = childNamespaces = new string[0];
+		}
+
+		protected virtual ObjectValue CreateObjectValueImpl (EvaluationContext ctx, Mono.Debugging.Backend.IObjectValueSource source, ObjectPath path, object obj, ObjectValueFlags flags)
+		{
+			object type = obj != null ? GetValueType (ctx, obj) : null;
+			string typeName = type != null ? GetTypeName (ctx, type) : "";
+
+			if (obj == null || IsNull (ctx, obj)) {
+				return ObjectValue.CreateNullObject (source, path, GetDisplayTypeName (typeName), flags);
+			}
+			else if (IsPrimitive (ctx, obj) || IsEnum (ctx,obj)) {
+				return ObjectValue.CreatePrimitive (source, path, GetDisplayTypeName (typeName), ctx.Evaluator.TargetObjectToExpression (ctx, obj), flags);
+			}
+			else if (IsArray (ctx, obj)) {
+				return ObjectValue.CreateObject (source, path, GetDisplayTypeName (typeName), ctx.Evaluator.TargetObjectToExpression (ctx, obj), flags, null);
+			}
+			else {
+				EvaluationResult tvalue = null;
+				TypeDisplayData tdata = null;
+				string tname;
+
+				if (IsNullableType (ctx, type)) {
+					if (NullableHasValue (ctx, type, obj)) {
+						ValueReference value = NullableGetValue (ctx, type, obj);
+
+						tdata = GetTypeDisplayData (ctx, value.Type);
+						obj = value.Value;
+					} else {
+						tdata = GetTypeDisplayData (ctx, type);
+						tvalue = new EvaluationResult ("null");
+					}
+
+					tname = GetDisplayTypeName (typeName);
+				} else {
+					tdata = GetTypeDisplayData (ctx, type);
+
+					if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
+						tname = EvaluateDisplayString (ctx, obj, tdata.TypeDisplayString);
+					else
+						tname = GetDisplayTypeName (typeName);
+				}
+
+				if (tvalue == null) {
+					if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
+						tvalue = new EvaluationResult (EvaluateDisplayString (ctx, obj, tdata.ValueDisplayString));
+					else
+						tvalue = ctx.Evaluator.TargetObjectToExpression (ctx, obj);
+				}
+
+				ObjectValue oval = ObjectValue.CreateObject (source, path, tname, tvalue, flags, null);
+				if (!string.IsNullOrEmpty (tdata.NameDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
+					oval.Name = EvaluateDisplayString (ctx, obj, tdata.NameDisplayString);
+				return oval;
+			}
+		}
+		
+		public ObjectValue[] GetObjectValueChildren (EvaluationContext ctx, IObjectSource objectSource, object obj, int firstItemIndex, int count)
+		{
+			return GetObjectValueChildren (ctx, objectSource, GetValueType (ctx, obj), obj, firstItemIndex, count, true);
+		}
+
+		public virtual ObjectValue[] GetObjectValueChildren (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, int firstItemIndex, int count, bool dereferenceProxy)
+		{
+			if (obj is EvaluationResult)
+				return new ObjectValue[0];
+			
+			if (IsArray (ctx, obj)) {
+				ArrayElementGroup agroup = new ArrayElementGroup (ctx, CreateArrayAdaptor (ctx, obj));
+				return agroup.GetChildren (ctx.Options);
+			}
+
+			if (IsPrimitive (ctx, obj))
+				return new ObjectValue[0];
+
+			if (IsNullableType (ctx, type)) {
+				if (NullableHasValue (ctx, type, obj)) {
+					ValueReference value = NullableGetValue (ctx, type, obj);
+
+					return GetObjectValueChildren (ctx, objectSource, value.Type, value.Value, firstItemIndex, count, dereferenceProxy);
+				} else {
+					return new ObjectValue[0];
+				}
+			}
+
+			bool showRawView = false;
+			
+			// If there is a proxy, it has to show the members of the proxy
+			object proxy = obj;
+			if (dereferenceProxy) {
+				proxy = GetProxyObject (ctx, obj);
+				if (proxy != obj) {
+					type = GetValueType (ctx, proxy);
+					showRawView = true;
+				}
+			}
+
+			TypeDisplayData tdata = GetTypeDisplayData (ctx, type);
+			bool groupPrivateMembers = ctx.Options.GroupPrivateMembers || IsExternalType (ctx, type);
+
+			List<ObjectValue> values = new List<ObjectValue> ();
+			BindingFlags flattenFlag = ctx.Options.FlattenHierarchy ? (BindingFlags)0 : BindingFlags.DeclaredOnly;
+			BindingFlags nonPublicFlag = !(groupPrivateMembers || showRawView) ? BindingFlags.NonPublic : (BindingFlags) 0;
+			BindingFlags staticFlag = ctx.Options.GroupStaticMembers ? (BindingFlags)0 : BindingFlags.Static;
+			BindingFlags access = BindingFlags.Public | BindingFlags.Instance | flattenFlag | nonPublicFlag | staticFlag;
+			
+			// Load all members to a list before creating the object values,
+			// to avoid problems with objects being invalidated due to evaluations in the target,
+			List<ValueReference> list = new List<ValueReference> ();
+			list.AddRange (GetMembersSorted (ctx, objectSource, type, proxy, access));
+			var names = new ObjectValueNameTracker (ctx);
+			object tdataType = type;
+			
+			foreach (ValueReference val in list) {
+				try {
+					object decType = val.DeclaringType;
+					if (decType != null && decType != tdataType) {
+						tdataType = decType;
+						tdata = GetTypeDisplayData (ctx, decType);
+					}
+					DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name);
+					if (state == DebuggerBrowsableState.Never)
+						continue;
+
+					if (state == DebuggerBrowsableState.RootHidden && dereferenceProxy) {
+						object ob = val.Value;
+						if (ob != null) {
+							values.Clear ();
+							values.AddRange (GetObjectValueChildren (ctx, val, ob, -1, -1));
+							showRawView = true;
+							break;
+						}
+					}
+					else {
+						ObjectValue oval = val.CreateObjectValue (true);
+						names.Disambiguate (val, oval);
+						values.Add (oval);
+					}
+
+				}
+				catch (Exception ex) {
+					ctx.WriteDebuggerError (ex);
+					values.Add (ObjectValue.CreateError (null, new ObjectPath (val.Name), GetDisplayTypeName (GetTypeName (ctx, val.Type)), ex.Message, val.Flags));
+				}
+			}
+
+			if (showRawView) {
+				values.Add (RawViewSource.CreateRawView (ctx, objectSource, obj));
+			}
+			else {
+				if (IsArray (ctx, proxy)) {
+					ICollectionAdaptor col = CreateArrayAdaptor (ctx, proxy);
+					ArrayElementGroup agroup = new ArrayElementGroup (ctx, col);
+					ObjectValue val = ObjectValue.CreateObject (null, new ObjectPath ("Raw View"), "", "", ObjectValueFlags.ReadOnly, values.ToArray ());
+					values = new List<ObjectValue> ();
+					values.Add (val);
+					values.AddRange (agroup.GetChildren (ctx.Options));
+				}
+				else {
+					if (ctx.Options.GroupStaticMembers && HasMembers (ctx, type, proxy, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | flattenFlag)) {
+						access = BindingFlags.Static | BindingFlags.Public | flattenFlag | nonPublicFlag;
+						values.Add (FilteredMembersSource.CreateStaticsNode (ctx, objectSource, type, proxy, access));
+					}
+					if (groupPrivateMembers && HasMembers (ctx, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag))
+						values.Add (FilteredMembersSource.CreateNonPublicsNode (ctx, objectSource, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag));
+					
+					if (!ctx.Options.FlattenHierarchy) {
+						object baseType = GetBaseType (ctx, type, false);
+						if (baseType != null)
+							values.Insert (0, BaseTypeViewSource.CreateBaseTypeView (ctx, objectSource, baseType, proxy));
+					}
+				}
+			}
+			return values.ToArray ();
+		}
+
+		public ObjectValue[] GetExpressionValuesAsync (EvaluationContext ctx, string[] expressions)
+		{
+			ObjectValue[] values = new ObjectValue[expressions.Length];
+			for (int n = 0; n < values.Length; n++) {
+				string exp = expressions[n];
+				// This is a workaround to a bug in mono 2.0. That mono version fails to compile
+				// an anonymous method here
+				ExpData edata = new ExpData (ctx, exp, this);
+				values[n] = asyncEvaluationTracker.Run (exp, ObjectValueFlags.Literal, edata.Run);
+			}
+			return values;
+		}
+		
+		class ExpData
+		{
+			readonly ObjectValueAdaptor adaptor;
+			readonly EvaluationContext ctx;
+			readonly string exp;
+			
+			public ExpData (EvaluationContext ctx, string exp, ObjectValueAdaptor adaptor)
+			{
+				this.ctx = ctx;
+				this.exp = exp;
+				this.adaptor = adaptor;
+			}
+			
+			public ObjectValue Run ()
+			{
+				return adaptor.GetExpressionValue (ctx, exp);
+			}
+		}
+
+		public virtual ValueReference GetIndexerReference (EvaluationContext ctx, object target, object[] indices)
+		{
+			return null;
+		}
+
+		public ValueReference GetLocalVariable (EvaluationContext ctx, string name)
+		{
+			return OnGetLocalVariable (ctx, name);
+		}
+
+		protected virtual ValueReference OnGetLocalVariable (EvaluationContext ctx, string name)
+		{
+			ValueReference best = null;
+			foreach (ValueReference var in GetLocalVariables (ctx)) {
+				if (var.Name == name)
+					return var;
+				if (!ctx.Evaluator.CaseSensitive && var.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase))
+					best = var;
+			}
+			return best;
+		}
+
+		public virtual ValueReference GetParameter (EvaluationContext ctx, string name)
+		{
+			return OnGetParameter (ctx, name);
+		}
+
+		protected virtual ValueReference OnGetParameter (EvaluationContext ctx, string name)
+		{
+			ValueReference best = null;
+			foreach (ValueReference var in GetParameters (ctx)) {
+				if (var.Name == name)
+					return var;
+				if (!ctx.Evaluator.CaseSensitive && var.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase))
+					best = var;
+			}
+			return best;
+		}
+
+		public IEnumerable<ValueReference> GetLocalVariables (EvaluationContext ctx)
+		{
+			return OnGetLocalVariables (ctx);
+		}
+
+		public ValueReference GetThisReference (EvaluationContext ctx)
+		{
+			return OnGetThisReference (ctx);
+		}
+
+		public IEnumerable<ValueReference> GetParameters (EvaluationContext ctx)
+		{
+			return OnGetParameters (ctx);
+		}
+
+		protected virtual IEnumerable<ValueReference> OnGetLocalVariables (EvaluationContext ctx)
+		{
+			yield break;
+		}
+
+		protected virtual IEnumerable<ValueReference> OnGetParameters (EvaluationContext ctx)
+		{
+			yield break;
+		}
+
+		protected virtual ValueReference OnGetThisReference (EvaluationContext ctx)
+		{
+			return null;
+		}
+
+		public virtual ValueReference GetCurrentException (EvaluationContext ctx)
+		{
+			return null;
+		}
+
+		public virtual object GetEnclosingType (EvaluationContext ctx)
+		{
+			return null;
+		}
+
+		protected virtual CompletionData GetMemberCompletionData (EvaluationContext ctx, ValueReference vr)
+		{
+			CompletionData data = new CompletionData ();
+
+			foreach (ValueReference cv in vr.GetChildReferences (ctx.Options))
+				data.Items.Add (new CompletionItem (cv.Name, cv.Flags));
+
+			data.ExpressionLength = 0;
+
+			return data;
+		}
+
+		public virtual CompletionData GetExpressionCompletionData (EvaluationContext ctx, string expr)
+		{
+			if (string.IsNullOrEmpty (expr))
+				return null;
+
+			if (expr[expr.Length - 1] == '.') {
+				try {
+					var vr = ctx.Evaluator.Evaluate (ctx, expr.Substring (0, expr.Length - 1), null);
+					if (vr != null)
+						return GetMemberCompletionData (ctx, vr);
+
+					// FIXME: handle types and namespaces...
+				} catch (Exception ex) {
+					ctx.WriteDebuggerError (ex);
+				}
+
+				return null;
+			}
+
+			bool lastWastLetter = false;
+			int i = expr.Length - 1;
+
+			while (i >= 0) {
+				char c = expr[i--];
+				if (!char.IsLetterOrDigit (c) && c != '_')
+					break;
+
+				lastWastLetter = !char.IsDigit (c);
+			}
+
+			if (lastWastLetter) {
+				string partialWord = expr.Substring (i+1);
+				
+				CompletionData data = new CompletionData ();
+				data.ExpressionLength = partialWord.Length;
+				
+				// Local variables
+				
+				foreach (ValueReference vc in GetLocalVariables (ctx))
+					if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
+						data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
+				
+				// Parameters
+				
+				foreach (ValueReference vc in GetParameters (ctx))
+					if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
+						data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
+				
+				// Members
+				
+				ValueReference thisobj = GetThisReference (ctx);
+				
+				if (thisobj != null)
+					data.Items.Add (new CompletionItem ("this", ObjectValueFlags.Field | ObjectValueFlags.ReadOnly));
+
+				object type = GetEnclosingType (ctx);
+				
+				foreach (ValueReference vc in GetMembers (ctx, null, type, thisobj != null ? thisobj.Value : null))
+					if (vc.Name.StartsWith (partialWord, StringComparison.InvariantCulture))
+						data.Items.Add (new CompletionItem (vc.Name, vc.Flags));
+				
+				if (data.Items.Count > 0)
+					return data;
+			}
+
+			return null;
+		}
+		
+		public IEnumerable<ValueReference> GetMembers (EvaluationContext ctx, IObjectSource objectSource, object t, object co)
+		{
+			foreach (ValueReference val in GetMembers (ctx, t, co, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) {
+				val.ParentSource = objectSource;
+				yield return val;
+			}
+		}
+
+		public ValueReference GetMember (EvaluationContext ctx, IObjectSource objectSource, object co, string name)
+		{
+			return GetMember (ctx, objectSource, GetValueType (ctx, co), co, name);
+		}
+
+		public ValueReference GetMember (EvaluationContext ctx, IObjectSource objectSource, object t, object co, string name)
+		{
+			ValueReference m = GetMember (ctx, t, co, name);
+			if (m != null)
+				m.ParentSource = objectSource;
+			return m;
+		}
+		
+		protected virtual ValueReference GetMember (EvaluationContext ctx, object t, object co, string name)
+		{
+			ValueReference best = null;
+			foreach (ValueReference var in GetMembers (ctx, t, co, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) {
+				if (var.Name == name)
+					return var;
+				if (!ctx.Evaluator.CaseSensitive && var.Name.Equals (name, StringComparison.CurrentCultureIgnoreCase))
+					best = var;
+			}
+			return best;
+		}
+
+		internal IEnumerable<ValueReference> GetMembersSorted (EvaluationContext ctx, IObjectSource objectSource, object t, object co)
+		{
+			return GetMembersSorted (ctx, objectSource, t, co, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
+		}
+		
+		internal IEnumerable<ValueReference> GetMembersSorted (EvaluationContext ctx, IObjectSource objectSource, object t, object co, BindingFlags bindingFlags)
+		{
+			List<ValueReference> list = new List<ValueReference> ();
+			foreach (ValueReference vr in GetMembers (ctx, t, co, bindingFlags)) {
+				vr.ParentSource = objectSource;
+				list.Add (vr);
+			}
+			list.Sort (delegate (ValueReference v1, ValueReference v2) {
+				return v1.Name.CompareTo (v2.Name);
+			});
+			return list;
+		}
+		
+		public bool HasMembers (EvaluationContext ctx, object t, object co, BindingFlags bindingFlags)
+		{
+			return GetMembers (ctx, t, co, bindingFlags).Any ();
+		}
+
+		public bool HasMember (EvaluationContext ctx, object type, string memberName)
+		{
+			return HasMember (ctx, type, memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
+		}
+
+		public abstract bool HasMember (EvaluationContext ctx, object type, string memberName, BindingFlags bindingFlags);
+		
+		/// <summary>
+		/// Returns all members of a type. The following binding flags have to be honored:
+		/// BindingFlags.Static, BindingFlags.Instance, BindingFlags.Public, BindingFlags.NonPublic, BindingFlags.DeclareOnly
+		/// </summary>
+		protected abstract IEnumerable<ValueReference> GetMembers (EvaluationContext ctx, object t, object co, BindingFlags bindingFlags);
+		
+		public virtual IEnumerable<object> GetNestedTypes (EvaluationContext ctx, object type)
+		{
+			yield break;
+		}
+
+		public virtual object GetParentType (EvaluationContext ctx, object type)
+		{
+			if ((type is Type))
+				return ((Type) type).DeclaringType;
+
+			var name = GetTypeName (ctx, type);
+			int plus = name.LastIndexOf ('+');
+
+			return plus != -1 ? GetType (ctx, name.Substring (0, plus)) : null;
+		}
+		
+		public virtual object CreateArray (EvaluationContext ctx, object type, object[] values)
+		{
+			object arrType = GetType (ctx, "System.Collections.ArrayList");
+			object arrayList = CreateValue (ctx, arrType, new object[0]);
+			object[] objTypes = new object[] { GetType (ctx, "System.Object") };
+			foreach (object value in values)
+				RuntimeInvoke (ctx, arrType, arrayList, "Add", objTypes, new object[] { value });
+			
+			object typof = CreateTypeObject (ctx, type);
+			objTypes = new object[] { GetType (ctx, "System.Type") };
+			return RuntimeInvoke (ctx, arrType, arrayList, "ToArray", objTypes, new object[] { typof });
+		}
+		
+		public virtual object ToRawValue (EvaluationContext ctx, IObjectSource source, object obj)
+		{
+			if (IsEnum (ctx, obj)) {
+				object longType = GetType (ctx, "System.Int64");
+				object c = Cast (ctx, obj, longType);
+				return TargetObjectToObject (ctx, c);
+			}
+			
+			if (ctx.Options.ChunkRawStrings && IsString (ctx, obj)) {
+				IStringAdaptor adaptor = CreateStringAdaptor (ctx, obj);
+				return new RawValueString (new RemoteRawValueString (adaptor, obj));
+			}
+			
+			if (IsPrimitive (ctx, obj))
+				return TargetObjectToObject (ctx, obj);
+				
+			if (IsArray (ctx, obj)) {
+				ICollectionAdaptor adaptor = CreateArrayAdaptor (ctx, obj);
+				return new RawValueArray (new RemoteRawValueArray (ctx, source, adaptor, obj));
+			}
+			
+			return new RawValue (new RemoteRawValue (ctx, source, obj));
+		}
+		
+		public virtual object FromRawValue (EvaluationContext ctx, object obj)
+		{
+			if (obj is RawValue) {
+				RemoteRawValue val = ((RawValue)obj).Source as RemoteRawValue;
+				if (val == null)
+					throw new InvalidOperationException ("Unknown RawValue source: " + ((RawValue)obj).Source);
+				return val.TargetObject;
+			}
+			else if (obj is RawValueArray) {
+				RemoteRawValueArray val = ((RawValueArray)obj).Source as RemoteRawValueArray;
+				if (val == null)
+					throw new InvalidOperationException ("Unknown RawValueArray source: " + ((RawValueArray)obj).Source);
+				return val.TargetObject;
+			}
+			else if (obj is RawValueString) {
+				RemoteRawValueString val = ((RawValueString)obj).Source as RemoteRawValueString;
+				if (val == null)
+					throw new InvalidOperationException ("Unknown RawValueString source: " + ((RawValueString)obj).Source);
+				return val.TargetObject;
+			}
+			else {
+				if (obj is Array) {
+					Array arr = (Array) obj;
+					if (obj.GetType ().GetElementType () == typeof(RawValue)) {
+						throw new NotSupportedException ();
+					} else {
+						object elemType = GetType (ctx, obj.GetType ().GetElementType ().FullName);
+						if (elemType == null)
+							throw new EvaluatorException ("Unknown target type: {0}", obj.GetType ().GetElementType ().FullName);
+						object[] values = new object [arr.Length];
+						for (int n=0; n<values.Length; n++)
+							values [n] = FromRawValue (ctx, arr.GetValue (n));
+						return CreateArray (ctx, elemType, values);
+					}
+				}
+				return CreateValue (ctx, obj);
+			}
+		}
+		
+		public virtual object TargetObjectToObject (EvaluationContext ctx, object obj)
+		{
+			if (IsNull (ctx, obj))
+				return null;
+
+			if (IsArray (ctx, obj)) {
+				ICollectionAdaptor adaptor = CreateArrayAdaptor (ctx, obj);
+				string ename = GetDisplayTypeName (GetTypeName (ctx, adaptor.ElementType));
+				int[] dims = adaptor.GetDimensions ();
+				StringBuilder tn = new StringBuilder ("[");
+				for (int n=0; n<dims.Length; n++) {
+					if (n>0)
+						tn.Append (',');
+					tn.Append (dims[n]);
+				}
+				tn.Append ("]");
+				int i = ename.LastIndexOf ('>');
+				if (i == -1) i = 0;
+				i = ename.IndexOf ('[', i);
+				if (i != -1)
+					return new EvaluationResult ("{" + ename.Substring (0, i) + tn + ename.Substring (i) + "}");
+
+				return new EvaluationResult ("{" + ename + tn + "}");
+			}
+
+			if (IsEnum (ctx, obj)) {
+				object type = GetValueType (ctx, obj);
+				object longType = GetType (ctx, "System.Int64");
+				object c = Cast (ctx, obj, longType);
+				long val = (long) TargetObjectToObject (ctx, c);
+				long rest = val;
+				string typeName = GetTypeName (ctx, type);
+				string composed = string.Empty;
+				string composedDisplay = string.Empty;
+				foreach (EnumMember em in GetEnumMembers (ctx, type)) {
+					if (em.Value == val)
+						return new EvaluationResult (typeName + "." + em.Name, em.Name);
+					else {
+						if (em.Value != 0 && (rest & em.Value) == em.Value) {
+							rest &= ~em.Value;
+							if (composed.Length > 0) {
+								composed += "|";
+								composedDisplay += "|";
+							}
+							composed += typeName + "." + em.Name;
+							composedDisplay += em.Name;
+						}
+					}
+				}
+
+				if (IsFlagsEnumType (ctx, type) && rest == 0 && composed.Length > 0)
+					return new EvaluationResult (composed, composedDisplay);
+
+				return new EvaluationResult (val.ToString ());
+			}
+
+			if (GetValueTypeName (ctx, obj) == "System.Decimal") {
+				string res = CallToString (ctx, obj);
+				// This returns the decimal formatted using the current culture. It has to be converted to invariant culture.
+				decimal dec = decimal.Parse (res);
+				res = dec.ToString (System.Globalization.CultureInfo.InvariantCulture);
+				return new EvaluationResult (res);
+			}
+
+			if (IsClassInstance (ctx, obj)) {
+				TypeDisplayData tdata = GetTypeDisplayData (ctx, GetValueType (ctx, obj));
+				if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
+					return new EvaluationResult (EvaluateDisplayString (ctx, obj, tdata.ValueDisplayString));
+
+				// Return the type name
+				if (ctx.Options.AllowToStringCalls) {
+					try {
+						return new EvaluationResult ("{" + CallToString (ctx, obj) + "}");
+					} catch (TimeOutException) {
+						// ToString() timed out, fall back to default behavior.
+					}
+				}
+				
+				if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation)
+					return new EvaluationResult ("{" + EvaluateDisplayString (ctx, obj, tdata.TypeDisplayString) + "}");
+				
+				return new EvaluationResult ("{" + GetDisplayTypeName (GetValueTypeName (ctx, obj)) + "}");
+			}
+
+			return new EvaluationResult ("{" + CallToString (ctx, obj) + "}");
+		}
+
+		public object Convert (EvaluationContext ctx, object obj, object targetType)
+		{
+			if (obj == null)
+				return null;
+
+			object res = TryConvert (ctx, obj, targetType);
+			if (res != null)
+				return res;
+
+			throw new EvaluatorException ("Can't convert an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
+		}
+
+		public virtual object TryConvert (EvaluationContext ctx, object obj, object targetType)
+		{
+			return TryCast (ctx, obj, targetType);
+		}
+
+		public virtual object Cast (EvaluationContext ctx, object obj, object targetType)
+		{
+			if (obj == null)
+				return null;
+
+			object res = TryCast (ctx, obj, targetType);
+			if (res != null)
+				return res;
+
+			throw new EvaluatorException ("Can't cast an object of type '{0}' to type '{1}'", GetValueTypeName (ctx, obj), GetTypeName (ctx, targetType));
+		}
+
+		public virtual string CallToString (EvaluationContext ctx, object obj)
+		{
+			return GetValueTypeName (ctx, obj);
+		}
+
+		public object GetProxyObject (EvaluationContext ctx, object obj)
+		{
+			TypeDisplayData data = GetTypeDisplayData (ctx, GetValueType (ctx, obj));
+			if (string.IsNullOrEmpty (data.ProxyType) || !ctx.Options.AllowDebuggerProxy)
+				return obj;
+
+			string proxyType = data.ProxyType;
+			object[] typeArgs = null;
+
+			int index = proxyType.IndexOf ('`');
+			if (index != -1) {
+				// The proxy type is an uninstantiated generic type.
+				// The number of type args of the proxy must match the args of the target object
+				int startIndex = index + 1;
+				int endIndex = index + 1;
+
+				while (endIndex < proxyType.Length && char.IsDigit (proxyType[endIndex]))
+					endIndex++;
+
+				int num = int.Parse (proxyType.Substring (startIndex, endIndex - startIndex));
+				typeArgs = GetTypeArgs (ctx, GetValueType (ctx, obj));
+				if (typeArgs.Length != num)
+					return obj;
+
+				if (endIndex < proxyType.Length) {
+					// chop off the []'d list of generic type arguments
+					proxyType = proxyType.Substring (0, endIndex);
+				}
+			}
+			
+			object ttype = GetType (ctx, proxyType, typeArgs);
+			if (ttype == null) {
+				// the proxy type string might be in the form: "Namespace.TypeName, Assembly...", chop off the ", Assembly..." bit.
+				if ((index = proxyType.IndexOf (',')) != -1)
+					ttype = GetType (ctx, proxyType.Substring (0, index).Trim (), typeArgs);
+			}
+			if (ttype == null)
+				throw new EvaluatorException ("Unknown type '{0}'", data.ProxyType);
+
+			try {
+				object val = CreateValue (ctx, ttype, obj);
+				return val ?? obj;
+			} catch (EvaluatorException) {
+				// probably couldn't find the .ctor for the proxy type because the linker stripped it out
+				return obj;
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				return obj;
+			}
+		}
+
+		public TypeDisplayData GetTypeDisplayData (EvaluationContext ctx, object type)
+		{
+			if (!IsClass (ctx, type))
+				return TypeDisplayData.Default;
+
+			TypeDisplayData td;
+			string tname = GetTypeName (ctx, type);
+			if (typeDisplayData.TryGetValue (tname, out td))
+				return td;
+
+			try {
+				td = OnGetTypeDisplayData (ctx, type);
+			}
+			catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+			}
+			if (td == null)
+				typeDisplayData[tname] = td = TypeDisplayData.Default;
+			else
+				typeDisplayData[tname] = td;
+			return td;
+		}
+
+		protected virtual TypeDisplayData OnGetTypeDisplayData (EvaluationContext ctx, object type)
+		{
+			return null;
+		}
+
+		static bool IsQuoted (string str)
+		{
+			return str.Length >= 2 && str[0] == '"' && str[str.Length - 1] == '"';
+		}
+
+		public string EvaluateDisplayString (EvaluationContext ctx, object obj, string expr)
+		{
+			StringBuilder sb = new StringBuilder ();
+			int i = expr.IndexOf ('{');
+			int last = 0;
+
+			while (i != -1 && i < expr.Length) {
+				sb.Append (expr.Substring (last, i - last));
+				i++;
+
+				int j = expr.IndexOf ('}', i);
+				if (j == -1)
+					return expr;
+
+				string memberExpr = expr.Substring (i, j - i).Trim ();
+				if (memberExpr.Length == 0)
+					return expr;
+
+				int comma = memberExpr.LastIndexOf (',');
+				bool noquotes = false;
+				if (comma != -1) {
+					var option = memberExpr.Substring (comma + 1).Trim ();
+					memberExpr = memberExpr.Substring (0, comma).Trim ();
+					if (option == "nq")
+						noquotes = true;
+				}
+				
+				string[] props = memberExpr.Split (new char[] { '.' });
+				ValueReference member = null;
+				object val = obj;
+				
+				for (int k = 0; k < props.Length; k++) {
+					member = GetMember (ctx, null, GetValueType (ctx, val), val, props[k]);
+					if (member == null)
+						break;
+					
+					val = member.Value;
+				}
+				
+				if (member != null) {
+					var str = ctx.Evaluator.TargetObjectToString (ctx, val);
+					if (str == null)
+						sb.Append ("null");
+					else if (noquotes && IsQuoted (str))
+						sb.Append (str.Substring (1, str.Length - 2));
+					else
+						sb.Append (str);
+				} else {
+					sb.Append ("{Unknown member '" + memberExpr + "'}");
+				}
+
+				last = j + 1;
+				i = expr.IndexOf ('{', last);
+			}
+
+			sb.Append (expr.Substring (last));
+
+			return sb.ToString ();
+		}
+
+		public void AsyncExecute (AsyncOperation operation, int timeout)
+		{
+			asyncOperationManager.Invoke (operation, timeout);
+		}
+
+		public ObjectValue CreateObjectValueAsync (string name, ObjectValueFlags flags, ObjectEvaluatorDelegate evaluator)
+		{
+			return asyncEvaluationTracker.Run (name, flags, evaluator);
+		}
+		
+		public bool IsEvaluating {
+			get { return asyncEvaluationTracker.IsEvaluating; }
+		}
+
+		public void CancelAsyncOperations ( )
+		{
+			asyncEvaluationTracker.Stop ();
+			asyncOperationManager.AbortAll ();
+			asyncEvaluationTracker.WaitForStopped ();
+		}
+
+		public ObjectValue GetExpressionValue (EvaluationContext ctx, string exp)
+		{
+			try {
+				ValueReference var = ctx.Evaluator.Evaluate (ctx, exp);
+				if (var != null)
+					return var.CreateObjectValue (ctx.Options);
+
+				return ObjectValue.CreateUnknown (exp);
+			} catch (ImplicitEvaluationDisabledException) {
+				return ObjectValue.CreateImplicitNotSupported (ctx.ExpressionValueSource, new ObjectPath (exp), "", ObjectValueFlags.None);
+			} catch (NotSupportedExpressionException ex) {
+				return ObjectValue.CreateNotSupported (ctx.ExpressionValueSource, new ObjectPath (exp), ex.Message, "", ObjectValueFlags.None);
+			} catch (EvaluatorException ex) {
+				return ObjectValue.CreateError (ctx.ExpressionValueSource, new ObjectPath (exp), "", ex.Message, ObjectValueFlags.None);
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				return ObjectValue.CreateUnknown (exp);
+			}
+		}
+
+		public bool HasMethod (EvaluationContext ctx, object targetType, string methodName)
+		{
+			BindingFlags flags = BindingFlags.Instance | BindingFlags.Static;
+			if (!ctx.Evaluator.CaseSensitive)
+				flags |= BindingFlags.IgnoreCase;
+			return HasMethod (ctx, targetType, methodName, null, null, flags);
+		}
+		
+		public bool HasMethod (EvaluationContext ctx, object targetType, string methodName, BindingFlags flags)
+		{
+			return HasMethod (ctx, targetType, methodName, null, null, flags);
+		}
+		
+		// argTypes can be null, meaning that it has to return true if there is any method with that name
+		// flags will only contain Static or Instance flags
+		// FIXME: this should become non-virtual
+		public virtual bool HasMethod (EvaluationContext ctx, object targetType, string methodName, object[] argTypes, BindingFlags flags)
+		{
+			return HasMethod (ctx, targetType, methodName, null, argTypes, flags);
+		}
+
+		// argTypes can be null, meaning that it has to return true if there is any method with that name
+		// flags will only contain Static or Instance flags
+		public virtual bool HasMethod (EvaluationContext ctx, object targetType, string methodName, object[] genericTypeArgs, object[] argTypes, BindingFlags flags)
+		{
+			return false;
+		}
+
+		// FIXME: this should become non-virtual and simply call the newer method
+		public virtual object RuntimeInvoke (EvaluationContext ctx, object targetType, object target, string methodName, object[] argTypes, object[] argValues)
+		{
+			return null;
+		}
+
+		public virtual object RuntimeInvoke (EvaluationContext ctx, object targetType, object target, string methodName, object[] genericTypeArgs, object[] argTypes, object[] argValues)
+		{
+			// Note: this is for backward compatibility with debugger backends that haven't yet implemented this particular overload
+			return RuntimeInvoke (ctx, targetType, target, methodName, argTypes, argValues);
+		}
+		
+		public virtual ValidationResult ValidateExpression (EvaluationContext ctx, string expression)
+		{
+			return ctx.Evaluator.ValidateExpression (ctx, expression);
+		}
+	}
+
+	public class TypeDisplayData
+	{
+		public string ProxyType { get; internal set; }
+		public string ValueDisplayString { get; internal set; }
+		public string TypeDisplayString { get; internal set; }
+		public string NameDisplayString { get; internal set; }
+		public bool IsCompilerGenerated { get; internal set; }
+		
+		public bool IsProxyType {
+			get { return ProxyType != null; }
+		}
+
+		public static readonly TypeDisplayData Default = new TypeDisplayData (null, null, null, null, false, null);
+
+		public Dictionary<string, DebuggerBrowsableState> MemberData { get; internal set; }
+		
+		public TypeDisplayData (string proxyType, string valueDisplayString, string typeDisplayString,
+			string nameDisplayString, bool isCompilerGenerated, Dictionary<string, DebuggerBrowsableState> memberData)
+		{
+			ProxyType = proxyType;
+			ValueDisplayString = valueDisplayString;
+			TypeDisplayString = typeDisplayString;
+			NameDisplayString = nameDisplayString;
+			IsCompilerGenerated = isCompilerGenerated;
+			MemberData = memberData;
+		}
+
+		public DebuggerBrowsableState GetMemberBrowsableState (string name)
+		{
+			if (MemberData == null)
+				return DebuggerBrowsableState.Collapsed;
+
+			DebuggerBrowsableState state;
+			if (MemberData.TryGetValue (name, out state))
+				return state;
+
+			return DebuggerBrowsableState.Collapsed;
+		}
+	}
+	
+	class ObjectValueNameTracker
+	{
+		Dictionary<string,KeyValuePair<ObjectValue, ValueReference>> names = new Dictionary<string,KeyValuePair<ObjectValue, ValueReference>> ();
+		EvaluationContext ctx;
+		
+		public ObjectValueNameTracker (EvaluationContext ctx)
+		{
+			this.ctx = ctx;
+		}
+		
+		/// <summary>
+		/// Disambiguate the ObjectValue's name (in the case where the property name also exists in a base class).
+		/// </summary>
+		/// <param name='val'>
+		/// The ValueReference.
+		/// </param>
+		/// <param name='oval'>
+		/// The ObjectValue.
+		/// </param>
+		public void Disambiguate (ValueReference val, ObjectValue oval)
+		{
+			KeyValuePair<ObjectValue, ValueReference> other;
+			if (names.TryGetValue (oval.Name, out other)) {
+				object tn = val.DeclaringType;
+				
+				if (tn != null)
+					oval.Name += " (" + ctx.Adapter.GetDisplayTypeName (ctx, tn) + ")";
+				if (!other.Key.Name.EndsWith (")", StringComparison.Ordinal)) {
+					tn = other.Value.DeclaringType;
+					if (tn != null)
+						other.Key.Name += " (" + ctx.Adapter.GetDisplayTypeName (ctx, tn) + ")";
+				}
+			}
+			
+			names [oval.Name] = new KeyValuePair<ObjectValue, ValueReference> (oval, val);
+		}
+	}
+	
+	public struct EnumMember
+	{
+		public string Name { get; set; }
+		public long Value { get; set; }
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/RawViewSource.cs b/Mono.Debugging/Mono.Debugging.Evaluation/RawViewSource.cs
new file mode 100644
index 0000000..5c063c9
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/RawViewSource.cs
@@ -0,0 +1,83 @@
+// RawViewSource.cs
+//
+// Authors: Lluis Sanchez Gual <lluis at novell.com>
+//          Jeffrey Stedfast <jeff at 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 Mono.Debugging.Backend;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class RawViewSource: RemoteFrameObject, IObjectValueSource
+	{
+		object obj;
+		EvaluationContext ctx;
+		IObjectSource objectSource;
+
+		public RawViewSource (EvaluationContext ctx, IObjectSource objectSource, object obj)
+		{
+			this.ctx = ctx;
+			this.obj = obj;
+			this.objectSource = objectSource;
+		}
+
+		public static ObjectValue CreateRawView (EvaluationContext ctx, IObjectSource objectSource, object obj)
+		{
+			RawViewSource src = new RawViewSource (ctx, objectSource, obj);
+			src.Connect ();
+			ObjectValue val = ObjectValue.CreateObject (src, new ObjectPath ("Raw View"), "", "", ObjectValueFlags.Group|ObjectValueFlags.ReadOnly|ObjectValueFlags.NoRefresh, null);
+			val.ChildSelector = "";
+			return val;
+		}
+		
+		public ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			EvaluationContext cctx = ctx.WithOptions (options);
+			return cctx.Adapter.GetObjectValueChildren (cctx, objectSource, cctx.Adapter.GetValueType (cctx, obj), obj, index, count, false);
+		}
+		
+		public ObjectValue GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+		
+		public EvaluationResult SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			throw new NotSupportedException ();
+		}
+		
+		public void SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+		
+		public object GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			throw new NotImplementedException ();
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/RemoteFrameObject.cs b/Mono.Debugging/Mono.Debugging.Evaluation/RemoteFrameObject.cs
new file mode 100644
index 0000000..e4411eb
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/RemoteFrameObject.cs
@@ -0,0 +1,76 @@
+// RemoteFrameObject.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class RemoteFrameObject: MarshalByRefObject
+	{
+		static List<RemoteFrameObject> connectedValues = new List<RemoteFrameObject> ();
+
+		public static bool TrackConnections { get; set; }
+
+		bool connected;
+		
+		public void Connect ()
+		{
+			if (!TrackConnections)
+				return;
+
+			// Registers the value reference. Once a remote reference of this object
+			// is created, it will never be released, until DisconnectAll is called,
+			// which is done every time the current backtrace changes
+			
+			lock (connectedValues) {
+				if (!connected) {
+					connectedValues.Add (this);
+					connected = true;
+				}
+			}
+		}
+		
+		public static void DisconnectAll ()
+		{
+			lock (connectedValues) {
+				foreach (RemoteFrameObject val in connectedValues) {
+					System.Runtime.Remoting.RemotingServices.Disconnect (val);
+					IDisposable disp = val as IDisposable;
+					if (disp != null)
+						disp.Dispose ();
+				}
+				connectedValues.Clear ();
+			}
+		}
+		
+		public override object InitializeLifetimeService ()
+		{
+			return null;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/RemoteRawValue.cs b/Mono.Debugging/Mono.Debugging.Evaluation/RemoteRawValue.cs
new file mode 100644
index 0000000..73c6c67
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/RemoteRawValue.cs
@@ -0,0 +1,214 @@
+// 
+// RemoteRawValue.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Backend;
+using System.Collections;
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	internal class RemoteRawValue: RemoteFrameObject, IRawValue
+	{
+		object targetObject;
+		EvaluationContext ctx;
+		IObjectSource source;
+		
+		public RemoteRawValue (EvaluationContext gctx, IObjectSource source, object targetObject)
+		{
+			this.ctx = gctx.Clone ();
+			ctx.Options.AllowTargetInvoke = true;
+			ctx.Options.AllowMethodEvaluation = true;
+			this.targetObject = targetObject;
+			this.source = source;
+			Connect ();
+		}
+		
+		public object TargetObject {
+			get { return this.targetObject; }
+		}
+		
+		#region IRawValue implementation
+		public object CallMethod (string name, object[] parameters, EvaluationOptions options)
+		{
+			EvaluationContext localContext = ctx.WithOptions (options);
+			
+			object[] argValues = new object [parameters.Length];
+			object[] argTypes = new object [parameters.Length];
+			for (int n=0; n<argValues.Length; n++) {
+				argValues[n] = localContext.Adapter.FromRawValue (localContext, parameters[n]);
+				argTypes[n] = localContext.Adapter.GetValueType (localContext, argValues[n]);
+			}
+			object type = localContext.Adapter.GetValueType (localContext, targetObject);
+			object res = localContext.Adapter.RuntimeInvoke (localContext, type, targetObject, name, argTypes, argValues);
+			return localContext.Adapter.ToRawValue (localContext, null, res);
+		}
+		
+		public object GetMemberValue (string name, EvaluationOptions options)
+		{
+			EvaluationContext localContext = ctx.WithOptions (options);
+			object type = localContext.Adapter.GetValueType (localContext, targetObject);
+			ValueReference val = localContext.Adapter.GetMember (localContext, source, type, targetObject, name);
+			if (val == null)
+				throw new EvaluatorException ("Member '{0}' not found", name);
+			return localContext.Adapter.ToRawValue (localContext, val, val.Value);
+		}
+		
+		public void SetMemberValue (string name, object value, EvaluationOptions options)
+		{
+			EvaluationContext localContext = ctx.WithOptions (options);
+			object type = localContext.Adapter.GetValueType (localContext, targetObject);
+			ValueReference val = localContext.Adapter.GetMember (localContext, source, type, targetObject, name);
+			if (val == null)
+				throw new EvaluatorException ("Member '{0}' not found", name);
+			val.Value = localContext.Adapter.FromRawValue (localContext, value);
+		}
+		
+		#endregion
+	}
+	
+	internal class RemoteRawValueArray: RemoteFrameObject, IRawValueArray
+	{
+		object targetObject;
+		EvaluationContext ctx;
+		IObjectSource source;
+		ICollectionAdaptor targetArray;
+		
+		public RemoteRawValueArray (EvaluationContext ctx, IObjectSource source, ICollectionAdaptor targetArray, object targetObject)
+		{
+			this.ctx = ctx;
+			this.targetArray = targetArray;
+			this.targetObject = targetObject;
+			this.source = source;
+			Connect ();
+		}
+		
+		public object TargetObject {
+			get { return this.targetObject; }
+		}
+		
+		public object GetValue (int[] index)
+		{
+			return ctx.Adapter.ToRawValue (ctx, source, targetArray.GetElement (index));
+		}
+
+		public Array GetValues (int[] index, int count)
+		{
+			var values = targetArray.GetElements (index, count);
+			var idx = new int[index.Length];
+			var array = new ArrayList ();
+
+			for (int i = 0; i < index.Length; i++)
+				idx[i] = index[i];
+
+			Type commonType = null;
+			for (int i = 0; i < count; i++) {
+				var rv = ctx.Adapter.ToRawValue (ctx, new ArrayObjectSource (targetArray, idx), values.GetValue (i));
+				if (commonType == null)
+					commonType = rv.GetType ();
+				else if (commonType != rv.GetType ())
+					commonType = typeof (void);
+				array.Add (rv);
+
+				idx[idx.Length - 1]++;
+			}
+
+			if (array.Count > 0 && commonType != typeof (void))
+				return array.ToArray (commonType);
+
+			return array.ToArray ();
+		}
+		
+		public void SetValue (int[] index, object value)
+		{
+			targetArray.SetElement (index, ctx.Adapter.FromRawValue (ctx, value));
+		}
+		
+		public int[] Dimensions {
+			get {
+				return targetArray.GetDimensions ();
+			}
+		}
+		
+		public Array ToArray ()
+		{
+			int[] dims = targetArray.GetDimensions ();
+			var array = new ArrayList ();
+
+			if (dims.Length != 1)
+				throw new NotSupportedException ();
+
+			int[] idx = new int [1];
+			Type commonType = null;
+			for (int n = 0; n < dims[0]; n++) {
+				idx[0] = n;
+
+				var rv = ctx.Adapter.ToRawValue (ctx, new ArrayObjectSource (targetArray, idx), targetArray.GetElement (idx));
+				if (commonType == null)
+					commonType = rv.GetType ();
+				else if (commonType != rv.GetType ())
+					commonType = typeof(void);
+				array.Add (rv);
+			}
+
+			if (array.Count > 0 && commonType != typeof(void))
+				return array.ToArray (commonType);
+
+			return array.ToArray ();
+		}
+	}
+	
+	internal class RemoteRawValueString: RemoteFrameObject, IRawValueString
+	{
+		object targetObject;
+		IStringAdaptor targetString;
+		
+		public RemoteRawValueString (IStringAdaptor targetString, object targetObject)
+		{
+			this.targetString = targetString;
+			this.targetObject = targetObject;
+			Connect ();
+		}
+		
+		public object TargetObject {
+			get { return this.targetObject; }
+		}
+		
+		public int Length {
+			get { return targetString.Length; }
+		}
+		
+		public string Value {
+			get { return targetString.Value; }
+		}
+		
+		public string Substring (int index, int length)
+		{
+			return targetString.Substring (index, length);
+		}
+	}
+}
+
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/TimeOutException.cs b/Mono.Debugging/Mono.Debugging.Evaluation/TimeOutException.cs
new file mode 100644
index 0000000..d169381
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/TimeOutException.cs
@@ -0,0 +1,38 @@
+// TimeOutException.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Evaluation
+{
+	public class TimeOutException: EvaluatorException
+	{
+		public TimeOutException (): base ("Timed out.")
+		{
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/TimedEvaluator.cs b/Mono.Debugging/Mono.Debugging.Evaluation/TimedEvaluator.cs
new file mode 100644
index 0000000..f62c004
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/TimedEvaluator.cs
@@ -0,0 +1,254 @@
+// EvaluationContext.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Threading;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class TimedEvaluator
+	{
+		int maxThreads = 1;
+
+		object runningLock = new object ();
+		Queue<Task> pendingTasks = new Queue<Task> ();
+		AutoResetEvent newTaskEvent = new AutoResetEvent (false);
+		Task currentTask;
+		int runningThreads;
+		bool mainThreadBusy;
+		bool useTimeout;
+		bool disposed;
+		
+		public TimedEvaluator (): this (true)
+		{
+		}
+
+		public TimedEvaluator (bool useTimeout)
+		{
+			RunTimeout = 1000;
+			this.useTimeout = useTimeout;
+		}
+
+		public int RunTimeout { get; set; }
+
+		public bool IsEvaluating {
+			get {
+				lock (runningLock) {
+					return pendingTasks.Count > 0 || mainThreadBusy;
+				}
+			}
+		}
+		
+		void OnStartEval ()
+		{
+//			Console.WriteLine ("Eval Started");
+		}
+		
+		void OnEndEval ()
+		{
+//			lock (runningLock) {
+//				Console.WriteLine ("Eval Finished ({0} pending)", pendingTasks.Count);
+//			}
+		}
+		
+		/// <summary>
+		/// Executes the provided evaluator. If a result is obtained before RunTimeout milliseconds,
+		/// the method ends returning True.
+		/// If it does not finish after RunTimeout milliseconds, the method ends retuning False, although
+		/// the evaluation continues in the background. In that case, when evaluation ends, the provided
+		/// delayedDoneCallback delegate is called.
+		/// </summary>
+		public bool Run (EvaluatorDelegate evaluator, EvaluatorDelegate delayedDoneCallback)
+		{
+			if (!useTimeout) {
+				SafeRun (evaluator);
+				return true;
+			}
+			
+			Task task = new Task ();
+			task.Evaluator = evaluator;
+			task.FinishedCallback = delayedDoneCallback;
+			
+			lock (runningLock) {
+				if (disposed)
+					return false;
+				if (mainThreadBusy || runningThreads == 0) {
+					if (runningThreads < maxThreads) {
+						runningThreads++;
+						Thread tr = new Thread (Runner);
+						tr.Name = "Debugger evaluator";
+						tr.IsBackground = true;
+						tr.Start ();
+					} else {
+						// The main thread is busy evaluating and we can't tell
+						// how much time it will take, so we can't wait for it.
+						task.TimedOut = true;
+						pendingTasks.Enqueue (task);
+						return false;
+					}
+				}
+				mainThreadBusy = true;
+				currentTask = task;
+			}
+			
+			OnStartEval ();
+			newTaskEvent.Set ();
+			task.RunningEvent.WaitOne ();
+			
+			lock (task) {
+				if (!task.RunFinishedEvent.WaitOne (RunTimeout, false)) {
+					task.TimedOut = true;
+					return false;
+				} else {
+					lock (runningLock) {
+						mainThreadBusy = false;
+						Monitor.PulseAll (runningLock);
+					}
+				}
+			}
+			return true;
+		}
+
+		void Runner ()
+		{
+			Task threadTask = null;
+			
+			while (!disposed) {
+
+				if (threadTask == null) {
+					newTaskEvent.WaitOne ();
+					
+					lock (runningLock) {
+						if (disposed) {
+							runningThreads--;
+							return;
+						}
+						threadTask = currentTask;
+						currentTask = null;
+					}
+				}
+				
+				threadTask.RunningEvent.Set ();
+				SafeRun (threadTask.Evaluator);
+				threadTask.RunFinishedEvent.Set ();
+
+				Task curTask = threadTask;
+				threadTask = null;
+				
+				OnEndEval ();
+
+				lock (runningLock) {
+					if (disposed) {
+						runningThreads--;
+						return;
+					}
+				}
+				
+				lock (curTask) {
+					if (!curTask.TimedOut)
+						continue; // Done. Keep waiting for more tasks.
+					
+					SafeRun (curTask.FinishedCallback);
+				}
+
+				// The task timed out, so more threads may already have
+				// been created while this one was busy.
+				
+				lock (runningLock) {
+					Monitor.PulseAll (runningLock);
+					if (pendingTasks.Count > 0) {
+						// There is pending work to do.
+						OnStartEval ();
+						threadTask = pendingTasks.Dequeue ();
+					}
+					else if (mainThreadBusy) {
+						// More threads have been created and all are busy.
+						// This will now be the main thread.
+						mainThreadBusy = false;
+					}
+					else {
+						// More threads have been created and one of them is waiting for tasks
+						// This thread is not needed anymore, die
+						runningThreads--;
+						break;
+					}
+				}
+			}
+		}
+		
+		public void Dispose ()
+		{
+			lock (runningLock) {
+				disposed = true;
+				CancelAll ();
+				newTaskEvent.Set ();
+			}
+		}
+
+		public void CancelAll ()
+		{
+			lock (runningLock) {
+				// If there is a task waiting the be picked by the runner,
+				// set the task wait events to avoid deadlocking the caller.
+				if (currentTask != null) {
+					currentTask.RunningEvent.Set ();
+					currentTask.RunFinishedEvent.Set ();
+				}
+				pendingTasks.Clear ();
+				Monitor.PulseAll (runningLock);
+			}
+		}
+
+		public void WaitForStopped ()
+		{
+			lock (runningLock) {
+				while (mainThreadBusy)
+					Monitor.Wait (runningLock);
+			}
+		}
+
+		void SafeRun (EvaluatorDelegate del)
+		{
+			try {
+				del ();
+			} catch {
+			}
+		}
+		
+		class Task
+		{
+			public AutoResetEvent RunningEvent = new AutoResetEvent (false);
+			public AutoResetEvent RunFinishedEvent = new AutoResetEvent (false);
+			public EvaluatorDelegate Evaluator;
+			public EvaluatorDelegate FinishedCallback;
+			public bool TimedOut;
+		}
+	}
+
+	public delegate void EvaluatorDelegate ();
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/TypeValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/TypeValueReference.cs
new file mode 100644
index 0000000..a749220
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/TypeValueReference.cs
@@ -0,0 +1,207 @@
+// TypeValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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.Linq;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Reflection;
+
+using Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class TypeValueReference: ValueReference
+	{
+		readonly string fullName;
+		readonly string name;
+		readonly object type;
+
+		public TypeValueReference (EvaluationContext ctx, object type) : base (ctx)
+		{
+			this.type = type;
+			fullName = ctx.Adapter.GetDisplayTypeName (ctx, type);
+			name = GetTypeName (fullName);
+		}
+		
+		internal static string GetTypeName (string tname)
+		{
+			tname = tname.Replace ('+', '.');
+
+			int sep1 = tname.IndexOf ('<');
+			int sep2 = tname.IndexOf ('[');
+
+			if (sep2 != -1 && (sep2 < sep1 || sep1 == -1))
+				sep1 = sep2;
+
+			if (sep1 == -1)
+				sep1 = tname.Length - 1;
+
+			int i = tname.LastIndexOf ('.', sep1);
+
+			if (i != -1)
+				return tname.Substring (i + 1);
+
+			return tname;
+		}
+		
+		public override object Value {
+			get {
+				throw new NotSupportedException ();
+			}
+			set {
+				throw new NotSupportedException();
+			}
+		}
+
+		public override object Type {
+			get {
+				return type;
+			}
+		}
+		
+		public override object ObjectValue {
+			get {
+				throw new NotSupportedException ();
+			}
+		}
+
+		public override string Name {
+			get {
+				return name;
+			}
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Type;
+			}
+		}
+
+		protected override ObjectValue OnCreateObjectValue (EvaluationOptions options)
+		{
+			return Mono.Debugging.Client.ObjectValue.CreateObject (this, new ObjectPath (Name), "<type>", fullName, Flags, null);
+		}
+
+		public override ValueReference GetChild (string name, EvaluationOptions options)
+		{
+			EvaluationContext ctx = GetContext (options);
+			foreach (ValueReference val in ctx.Adapter.GetMembers (ctx, this, type, null)) {
+				if (val.Name == name)
+					return val;
+			}
+			foreach (object t in ctx.Adapter.GetNestedTypes (ctx, type)) {
+				string tn = ctx.Adapter.GetTypeName (ctx, t);
+				if (GetTypeName (tn) == name)
+					return new TypeValueReference (ctx, t);
+			}
+			return null;
+		}
+
+		public override ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			EvaluationContext ctx = GetContext (options);
+			try {
+				List<ObjectValue> list = new List<ObjectValue> ();
+				BindingFlags flattenFlag = options.FlattenHierarchy ? (BindingFlags)0 : BindingFlags.DeclaredOnly;
+				BindingFlags flags = BindingFlags.Static | BindingFlags.Public | flattenFlag;
+				bool groupPrivateMembers = options.GroupPrivateMembers || ctx.Adapter.IsExternalType (ctx, type);
+				if (!groupPrivateMembers)
+					flags |= BindingFlags.NonPublic;
+				
+				TypeDisplayData tdata = ctx.Adapter.GetTypeDisplayData (ctx, type);
+				object tdataType = type;
+				
+				foreach (ValueReference val in ctx.Adapter.GetMembersSorted (ctx, this, type, null, flags)) {
+					object decType = val.DeclaringType;
+					if (decType != null && decType != tdataType) {
+						tdataType = decType;
+						tdata = ctx.Adapter.GetTypeDisplayData (ctx, decType);
+					}
+					DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name);
+					if (state == DebuggerBrowsableState.Never)
+						continue;
+
+					ObjectValue oval = val.CreateObjectValue (options);
+					list.Add (oval);
+				}
+				
+				List<ObjectValue> nestedTypes = new List<ObjectValue> ();
+				foreach (object t in ctx.Adapter.GetNestedTypes (ctx, type))
+					nestedTypes.Add (new TypeValueReference (ctx, t).CreateObjectValue (options));
+				
+				nestedTypes.Sort (delegate (ObjectValue v1, ObjectValue v2) {
+					return v1.Name.CompareTo (v2.Name);
+				});
+				
+				list.AddRange (nestedTypes);
+				
+				if (groupPrivateMembers)
+					list.Add (FilteredMembersSource.CreateNonPublicsNode (ctx, this, type, null, BindingFlags.NonPublic | BindingFlags.Static | flattenFlag));
+				
+				if (!options.FlattenHierarchy) {
+					object baseType = ctx.Adapter.GetBaseType (ctx, type, false);
+					if (baseType != null) {
+						TypeValueReference baseRef = new TypeValueReference (ctx, baseType);
+						ObjectValue baseVal = baseRef.CreateObjectValue (false);
+						baseVal.Name = "base";
+						list.Insert (0, baseVal);
+					}
+				}
+				
+				return list.ToArray ();
+			} catch (Exception ex) {
+				Console.WriteLine (ex);
+				ctx.WriteDebuggerOutput (ex.Message);
+				return new ObjectValue [0];
+			}
+		}
+
+		public override IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
+		{
+			EvaluationContext ctx = GetContext (options);
+			try {
+				List<ValueReference> list = new List<ValueReference> ();
+				list.AddRange (ctx.Adapter.GetMembersSorted (ctx, this, type, null, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static));
+				
+				List<ValueReference> nestedTypes = new List<ValueReference> ();
+				foreach (object t in ctx.Adapter.GetNestedTypes (ctx, type))
+					nestedTypes.Add (new TypeValueReference (ctx, t));
+				
+				nestedTypes.Sort (delegate (ValueReference v1, ValueReference v2) {
+					return v1.Name.CompareTo (v2.Name);
+				});
+				list.AddRange (nestedTypes);
+				return list;
+			} catch (Exception ex) {
+				Console.WriteLine (ex);
+				ctx.WriteDebuggerOutput (ex.Message);
+				return new ValueReference[0];
+			}
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/UserVariableReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/UserVariableReference.cs
new file mode 100644
index 0000000..50049d7
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/UserVariableReference.cs
@@ -0,0 +1,73 @@
+// 
+// UserVariableReference.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public class UserVariableReference: ValueReference
+	{
+		readonly string name;
+		object currentValue;
+		
+		public UserVariableReference (EvaluationContext ctx, string name): base (ctx)
+		{
+			this.name = name;
+		}
+		
+		public override string Name {
+			get {
+				return name;
+			}
+		}
+		
+		public override object Value {
+			get {
+				if (currentValue != null)
+					return currentValue;
+				else
+					throw new EvaluatorException ("Value undefined.");
+			}
+			set {
+				currentValue = value;
+			}
+		}
+
+		public override object Type {
+			get {
+				return Context.Adapter.GetValueType (Context, Value);
+			}
+		}
+		
+		public override ObjectValueFlags Flags {
+			get {
+				return ObjectValueFlags.Variable;
+			}
+		}
+
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.Evaluation/ValueReference.cs b/Mono.Debugging/Mono.Debugging.Evaluation/ValueReference.cs
new file mode 100644
index 0000000..56e68ea
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.Evaluation/ValueReference.cs
@@ -0,0 +1,266 @@
+// ValueReference.cs
+//
+// Author:
+//   Lluis Sanchez Gual <lluis at 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 Mono.Debugging.Client;
+using Mono.Debugging.Backend;
+using DC = Mono.Debugging.Client;
+
+namespace Mono.Debugging.Evaluation
+{
+	public abstract class ValueReference: RemoteFrameObject, IObjectValueSource, IObjectSource
+	{
+		readonly EvaluationOptions originalOptions;
+		EvaluationContext ctx;
+
+		protected ValueReference (EvaluationContext ctx)
+		{
+			this.ctx = ctx;
+			originalOptions = ctx.Options;
+		}
+		
+		public virtual object ObjectValue {
+			get {
+				object ob = Value;
+				if (ctx.Adapter.IsNull (Context, ob))
+					return null;
+
+				if (ctx.Adapter.IsPrimitive (Context, ob))
+					return ctx.Adapter.TargetObjectToObject (ctx, ob);
+
+				return ob;
+			}
+		}
+		
+		public abstract object Value { get; set; }
+		public abstract string Name { get; }
+		public abstract object Type { get; }
+		public abstract ObjectValueFlags Flags { get; }
+		
+		// For class members, the type declaring the member (null otherwise)
+		public virtual object DeclaringType {
+			get { return null; }
+		}
+
+		public EvaluationContext Context {
+			get {
+				return ctx;
+			}
+		}
+		
+		public EvaluationContext GetContext (EvaluationOptions options)
+		{
+			return ctx.WithOptions (options);
+		}
+
+		public ObjectValue CreateObjectValue (bool withTimeout)
+		{
+			return CreateObjectValue (withTimeout, Context.Options);
+		}
+		
+		public ObjectValue CreateObjectValue (bool withTimeout, EvaluationOptions options)
+		{
+			if (!CanEvaluate (options))
+				return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), ctx.Adapter.GetTypeName (GetContext (options), Type), Flags);
+			if (withTimeout) {
+				return ctx.Adapter.CreateObjectValueAsync (Name, Flags, delegate {
+					return CreateObjectValue (options);
+				});
+			}
+
+			return CreateObjectValue (options);
+		}
+		
+		public ObjectValue CreateObjectValue (EvaluationOptions options)
+		{
+			if (!CanEvaluate (options))
+				return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), ctx.Adapter.GetTypeName (GetContext (options), Type), Flags);
+			
+			Connect ();
+			try {
+				return OnCreateObjectValue (options);
+			} catch (ImplicitEvaluationDisabledException) {
+				return DC.ObjectValue.CreateImplicitNotSupported (this, new ObjectPath (Name), ctx.Adapter.GetTypeName (GetContext (options), Type), Flags);
+			} catch (NotSupportedExpressionException ex) {
+				return DC.ObjectValue.CreateNotSupported (this, new ObjectPath (Name), ex.Message, ctx.Adapter.GetTypeName (GetContext (options), Type), Flags);
+			} catch (EvaluatorException ex) {
+				return DC.ObjectValue.CreateError (this, new ObjectPath (Name), "", ex.Message, Flags);
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				return DC.ObjectValue.CreateUnknown (Name);
+			}
+		}
+		
+		protected virtual bool CanEvaluate (EvaluationOptions options)
+		{
+			return true;
+		}
+		
+		protected virtual ObjectValue OnCreateObjectValue (EvaluationOptions options)
+		{
+			string name = Name;
+			if (string.IsNullOrEmpty (name))
+				name = "?";
+			
+			EvaluationContext newCtx = GetContext (options);
+			EvaluationContext oldCtx = Context;
+			object val = null;
+			
+			try {
+				// Note: The Value property implementation may make use of the EvaluationOptions,
+				// so we need to override our context temporarily to do the evaluation.
+				ctx = newCtx;
+				val = Value;
+			} finally {
+				ctx = oldCtx;
+			}
+			
+			if (val != null)
+				return newCtx.Adapter.CreateObjectValue (newCtx, this, new ObjectPath (name), val, Flags);
+
+			return Mono.Debugging.Client.ObjectValue.CreateNullObject (this, name, newCtx.Adapter.GetTypeName (newCtx, Type), Flags);
+		}
+
+		ObjectValue IObjectValueSource.GetValue (ObjectPath path, EvaluationOptions options)
+		{
+			return CreateObjectValue (true, options);
+		}
+		
+		EvaluationResult IObjectValueSource.SetValue (ObjectPath path, string value, EvaluationOptions options)
+		{
+			try {
+				ctx.WaitRuntimeInvokes ();
+				EvaluationContext cctx = GetContext (options);
+				cctx.Options.AllowMethodEvaluation = true;
+				cctx.Options.AllowTargetInvoke = true;
+				ValueReference vref = cctx.Evaluator.Evaluate (cctx, value, Type);
+				object newValue = cctx.Adapter.Convert (cctx, vref.Value, Type);
+				Value = newValue;
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				ctx.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
+			}
+			
+			try {
+				return ctx.Evaluator.TargetObjectToExpression (ctx, Value);
+			} catch (Exception ex) {
+				ctx.WriteDebuggerError (ex);
+				ctx.WriteDebuggerOutput ("Value assignment failed: {0}: {1}\n", ex.GetType (), ex.Message);
+			}
+			
+			return null;
+		}
+		
+		object IObjectValueSource.GetRawValue (ObjectPath path, EvaluationOptions options)
+		{
+			return ctx.Adapter.ToRawValue (GetContext (options), this, Value);
+		}
+
+		void IObjectValueSource.SetRawValue (ObjectPath path, object value, EvaluationOptions options)
+		{
+			Value = ctx.Adapter.FromRawValue (GetContext (options), value);
+		}
+
+		ObjectValue[] IObjectValueSource.GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			return GetChildren (path, index, count, options);
+		}
+		
+		public virtual string CallToString ()
+		{
+			return ctx.Adapter.CallToString (ctx, Value);
+		}
+
+		public virtual ObjectValue[] GetChildren (ObjectPath path, int index, int count, EvaluationOptions options)
+		{
+			try {
+				return ctx.Adapter.GetObjectValueChildren (GetChildrenContext (options), this, Value, index, count);
+			} catch (Exception ex) {
+				return new ObjectValue [] { Mono.Debugging.Client.ObjectValue.CreateFatalError ("", ex.Message, ObjectValueFlags.ReadOnly) };
+			}
+		}
+
+		public virtual IEnumerable<ValueReference> GetChildReferences (EvaluationOptions options)
+		{
+			try {
+				object val = Value;
+				if (ctx.Adapter.IsClassInstance (Context, val))
+					return ctx.Adapter.GetMembersSorted (GetChildrenContext (options), this, Type, val);
+			} catch {
+				// Ignore
+			}
+			return new ValueReference [0];
+		}
+		
+		public IObjectSource ParentSource { get; internal set; }
+
+		protected EvaluationContext GetChildrenContext (EvaluationOptions options)
+		{
+			EvaluationContext newCtx = ctx.Clone ();
+			if (options != null)
+				newCtx.Options = options;
+			newCtx.Options.EvaluationTimeout = originalOptions.MemberEvaluationTimeout;
+			return newCtx;
+		}
+
+		public virtual ValueReference GetChild (ObjectPath vpath, EvaluationOptions options)
+		{
+			if (vpath.Length == 0)
+				return this;
+
+			ValueReference val = GetChild (vpath[0], options);
+			if (val != null)
+				return val.GetChild (vpath.GetSubpath (1), options);
+
+			return null;
+		}
+
+		public virtual ValueReference GetChild (string name, EvaluationOptions options)
+		{
+			object obj = Value;
+			
+			if (obj == null)
+				return null;
+
+			if (name[0] == '[' && ctx.Adapter.IsArray (Context, obj)) {
+				// Parse the array indices
+				string[] sinds = name.Substring (1, name.Length - 2).Split (',');
+				int[] indices = new int [sinds.Length];
+				for (int n=0; n<sinds.Length; n++)
+					indices [n] = int.Parse (sinds [n]);
+
+				return new ArrayValueReference (ctx, obj, indices);
+			}
+			
+			if (ctx.Adapter.IsClassInstance (Context, obj))
+				return ctx.Adapter.GetMember (GetChildrenContext (options), this, obj, name);
+
+			return null;
+		}
+	}
+}
diff --git a/Mono.Debugging/Mono.Debugging.csproj b/Mono.Debugging/Mono.Debugging.csproj
new file mode 100644
index 0000000..cfd61c9
--- /dev/null
+++ b/Mono.Debugging/Mono.Debugging.csproj
@@ -0,0 +1,140 @@
+<?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>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Mono.Debugging</RootNamespace>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>mono.debugging.snk</AssemblyOriginatorKeyFile>
+    <AssemblyName>Mono.Debugging</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <Execution>
+      <Execution clr-version="Net_2_0" />
+    </Execution>
+    <GenerateDocumentation>true</GenerateDocumentation>
+    <NoWarn>1591;1573</NoWarn>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <Execution>
+      <Execution clr-version="Net_2_0" />
+    </Execution>
+    <DebugSymbols>true</DebugSymbols>
+    <GenerateDocumentation>true</GenerateDocumentation>
+    <NoWarn>1591;1573</NoWarn>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Mono.Debugging.Client\IExpressionEvaluator.cs" />
+    <Compile Include="Mono.Debugging.Client\Breakpoint.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerSession.cs" />
+    <Compile Include="Mono.Debugging.Client\Backtrace.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerStartInfo.cs" />
+    <Compile Include="Mono.Debugging.Client\ProcessEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Client\SourceLocation.cs" />
+    <Compile Include="Mono.Debugging.Client\StackFrame.cs" />
+    <Compile Include="Mono.Debugging.Client\TargetEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Client\TargetEventType.cs" />
+    <Compile Include="Mono.Debugging.Client\ThreadEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Backend\IBacktrace.cs" />
+    <Compile Include="Mono.Debugging.Backend\IDebuggerSessionFrontend.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakpointStore.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakpointEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Client\ObjectValue.cs" />
+    <Compile Include="Mono.Debugging.Backend\IObjectValueSource.cs" />
+    <Compile Include="Mono.Debugging.Client\ObjectValueFlags.cs" />
+    <Compile Include="Mono.Debugging.Client\ObjectPath.cs" />
+    <Compile Include="Mono.Debugging.Client\ThreadInfo.cs" />
+    <Compile Include="Mono.Debugging.Client\ProcessInfo.cs" />
+    <Compile Include="Mono.Debugging.Client\AssemblyLine.cs" />
+    <Compile Include="Mono.Debugging.Backend\DissassemblyBuffer.cs" />
+    <Compile Include="Mono.Debugging.Client\CompletionData.cs" />
+    <Compile Include="Mono.Debugging.Client\Catchpoint.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakEvent.cs" />
+    <Compile Include="Mono.Debugging.Client\CatchpointEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakEventArgs.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerFeatures.cs" />
+    <Compile Include="Mono.Debugging.Backend\IObjectValueUpdater.cs" />
+    <Compile Include="Mono.Debugging.Backend\IObjectValueUpdateCallback.cs" />
+    <Compile Include="Mono.Debugging.Backend\UpdateCallback.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ArrayElementGroup.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ArrayValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\AsyncEvaluationTracker.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\AsyncOperationManager.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\EvaluationContext.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ExpressionEvaluator.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\FilteredMembersSource.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ICollectionAdaptor.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\LiteralValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NamespaceValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NullValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ObjectValueAdaptor.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\RawViewSource.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\RemoteFrameObject.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\TimedEvaluator.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\TimeOutException.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\TypeValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ValueReference.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\UserVariableReference.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerException.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerSessionOptions.cs" />
+    <Compile Include="Mono.Debugging.Client\EvaluationOptions.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\BaseBacktrace.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\BaseTypeViewSource.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\IObjectSource.cs" />
+    <Compile Include="Mono.Debugging.Client\RawValue.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\RemoteRawValue.cs" />
+    <Compile Include="Mono.Debugging.Client\ExceptionInfo.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\ExceptionInfoSource.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakEventStatus.cs" />
+    <Compile Include="Mono.Debugging.Client\BreakEventInfo.cs" />
+    <Compile Include="Mono.Debugging.Client\FunctionBreakpoint.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\IStringAdaptor.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NRefactoryExpressionEvaluator.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NRefactoryExpressionEvaluatorVisitor.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NRefactoryExpressionResolverVisitor.cs" />
+    <Compile Include="Mono.Debugging.Evaluation\NRefactoryExtensions.cs" />
+    <Compile Include="Mono.Debugging.Backend\IDebuggerBackendObject.cs" />
+    <Compile Include="Mono.Debugging.Backend\IRawValue.cs" />
+    <Compile Include="Mono.Debugging.Backend\IRawValueArray.cs" />
+    <Compile Include="Mono.Debugging.Backend\IRawValueString.cs" />
+    <Compile Include="Mono.Debugging.Backend\EvaluationResult.cs" />
+    <Compile Include="Mono.Debugging.Client\DebuggerLoggingService.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Folder Include="Mono.Debugging.Evaluation\" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
+      <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
+      <Name>ICSharpCode.NRefactory</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
+      <Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
+      <Name>ICSharpCode.NRefactory.CSharp</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
diff --git a/Mono.Debugging/mono.debugging.snk b/Mono.Debugging/mono.debugging.snk
new file mode 100644
index 0000000..47df15f
Binary files /dev/null and b/Mono.Debugging/mono.debugging.snk differ
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7050d5c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+This repository contains several libraries which can be used to control the Mono debugger.
+
+* Mono.Debugger.Soft: The Mono Soft Debugger low level API
+* Mono.Debugging: Pluggable debugger API abstraction. It provides a common API to be used as frontend to different debuggers.
+* Mono.Debugging.Soft: Mono.Debugging backend for the Mono Soft Debugger.
+
+Dependencies
+============
+
+The libraries in this repository have external dependencies, specifically:
+
+* cecil (git://github.com/mono/cecil.git)
+* nrefactory (git://github.com/icsharpcode/NRefactory.git)
+
+Those libraries must be cloned side by side with debugger-libs.
\ No newline at end of file
diff --git a/UnitTests/UnitTests/DebugTests.cs b/UnitTests/UnitTests/DebugTests.cs
new file mode 100644
index 0000000..cdcdfa9
--- /dev/null
+++ b/UnitTests/UnitTests/DebugTests.cs
@@ -0,0 +1,110 @@
+// 
+// DebugTests.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 NUnit.Framework;
+using Mono.Debugging.Client;
+using System.IO;
+using System.Threading;
+
+namespace Mono.Debugging.UnitTests
+{
+	public abstract class DebugTests
+	{
+		protected abstract DebuggerStartInfo CreateDebuggerStartInfo ();
+		protected abstract DebuggerSession CreateDebuggerSession ();
+
+		protected DebuggerSession Start (string test)
+		{
+			try {
+				DebuggerStartInfo si = CreateDebuggerStartInfo ();
+				si.Command = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "UnitTests.TestApp.exe");
+				si.Arguments = test;
+
+				DebuggerSessionOptions ops = new DebuggerSessionOptions ();
+				ops.EvaluationOptions = EvaluationOptions.DefaultOptions;
+				ops.EvaluationOptions.EvaluationTimeout = 100000;
+
+				DebuggerSession session = CreateDebuggerSession ();
+				string path = Path.Combine (GetTestsDir (), "UnitTests.TestApp", "Main.cs");
+				path = Path.GetFullPath (path);
+
+				ManualResetEvent done = new ManualResetEvent (false);
+				
+				session.OutputWriter = delegate (bool isStderr, string text) {
+					Console.WriteLine ("PROC:" + text);
+				};
+				
+				session.TargetStopped += delegate {
+					done.Set ();
+				};
+					
+				session.Run (si, ops);
+				if (!done.WaitOne (3000))
+					throw new Exception ("Timeout while waiting for initial breakpoint");
+				
+				return session;
+			} catch (Exception ex) {
+				Console.WriteLine (ex);
+				throw;
+			}
+		}
+
+		public static string GetTestsDir ()
+		{
+			var p = typeof(DebugTests).Assembly.Location;
+			return Path.Combine (Path.GetDirectoryName (p), "..", "..", "..");
+		}
+	}
+	
+	static class EvalHelper
+	{
+		public static ObjectValue Sync (this ObjectValue val)
+		{
+			if (!val.IsEvaluating)
+				return val;
+			
+			object locker = new object ();
+			EventHandler h = delegate {
+				lock (locker) {
+					Monitor.PulseAll (locker);
+				}
+			};
+			
+			val.ValueChanged += h;
+			
+			lock (locker) {
+				while (val.IsEvaluating) {
+					if (!Monitor.Wait (locker, 4000))
+						throw new Exception ("Timeout while waiting for value evaluation");
+				}
+			}
+			
+			val.ValueChanged -= h;
+			return val;
+		}
+	}
+}
diff --git a/UnitTests/UnitTests/EvaluationTests.cs b/UnitTests/UnitTests/EvaluationTests.cs
new file mode 100644
index 0000000..69037f2
--- /dev/null
+++ b/UnitTests/UnitTests/EvaluationTests.cs
@@ -0,0 +1,695 @@
+// 
+// EvaluationTests.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 Mono.Debugging.Client;
+using NUnit.Framework;
+
+namespace Mono.Debugging.UnitTests
+{
+	public abstract class EvaluationTests: DebugTests
+	{
+		DebuggerSession ds;
+		StackFrame frame;
+		
+		[TestFixtureSetUp]
+		public void Setup ()
+		{
+			ds = Start ("TestEvaluation");
+			frame = ds.ActiveThread.Backtrace.GetFrame (0);
+		}
+		
+		[TestFixtureTearDown]
+		public void TearDown ()
+		{
+			ds.Exit ();
+			ds.Dispose ();
+		}
+
+
+		ObjectValue Eval (string exp)
+		{
+			return frame.GetExpressionValue (exp, true).Sync ();
+		}
+		
+		[Test()]
+		public void This ()
+		{
+			ObjectValue val = Eval ("this");
+			Assert.AreEqual ("{UnitTests.TestApp.MainClass}", val.Value);
+			Assert.AreEqual ("UnitTests.TestApp.MainClass", val.TypeName);
+		}
+		
+		[Test()]
+		public void UnaryOperators ()
+		{
+			ObjectValue val = Eval ("~1234");
+			Assert.AreEqual ((~1234).ToString (), val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("!true");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("!false");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("-1234");
+			Assert.AreEqual ("-1234", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("+1234");
+			Assert.AreEqual ("1234", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+		}
+		
+		[Test()]
+		public void TypeReference ()
+		{
+			ObjectValue val = Eval ("System.String");
+			Assert.AreEqual ("string", val.Value);
+			Assert.AreEqual ("<type>", val.TypeName);
+			Assert.AreEqual (ObjectValueFlags.Type, val.Flags & ObjectValueFlags.OriginMask);
+			
+			val = Eval ("MainClass");
+			Assert.AreEqual ("UnitTests.TestApp.MainClass", val.Value);
+			Assert.AreEqual ("<type>", val.TypeName);
+			Assert.AreEqual (ObjectValueFlags.Type, val.Flags & ObjectValueFlags.OriginMask);
+			
+			val = Eval ("UnitTests.TestApp.MainClass");
+			Assert.AreEqual ("MonoDevelop.Debugger.Tests.TestApp.MainClass", val.Value);
+			Assert.AreEqual ("<type>", val.TypeName);
+			Assert.AreEqual (ObjectValueFlags.Type, val.Flags & ObjectValueFlags.OriginMask);
+		}
+		
+		[Test()]
+		public virtual void TypeReferenceGeneric ()
+		{
+			ObjectValue val = Eval ("System.Collections.Generic.Dictionary<string,int>");
+			Assert.AreEqual ("System.Collections.Generic.Dictionary<string,int>", val.Value);
+			Assert.AreEqual ("<type>", val.TypeName);
+			Assert.AreEqual (ObjectValueFlags.Type, val.Flags & ObjectValueFlags.OriginMask);
+		}
+		
+		[Test()]
+		public virtual void Typeof ()
+		{
+			ObjectValue val = Eval ("typeof(System.Console)");
+			Assert.IsTrue (val.TypeName == "System.MonoType" || val.TypeName == "System.RuntimeType", "Incorrect type name: " + val.TypeName);
+			Assert.AreEqual ("{System.Console}", val.Value);
+		}
+		
+		[Test()]
+		public void MethodInvoke ()
+		{
+			ObjectValue val;
+			val = Eval ("TestMethod ()");
+			Assert.AreEqual ("1", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("TestMethod (\"23\")");
+			Assert.AreEqual ("24", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("TestMethod (42)");
+			Assert.AreEqual ("43", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+						 
+			val = Eval ("TestMethod (false)");
+			Assert.AreEqual ("2", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("this.TestMethod ()");
+			Assert.AreEqual ("1", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("this.TestMethod (\"23\")");
+			Assert.AreEqual ("24", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("this.TestMethod (42)");
+			Assert.AreEqual ("43", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("System.Int32.Parse (\"67\")");
+			Assert.AreEqual ("67", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("this.BoxingTestMethod (43)");
+			Assert.AreEqual ("\"43\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+		}
+		
+		[Test()]
+		public void Indexers ()
+		{
+			ObjectValue val = Eval ("numbers[0]");
+			Assert.AreEqual ("\"one\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("numbers[1]");
+			Assert.AreEqual ("\"two\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("numbers[2]");
+			Assert.AreEqual ("\"three\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("staticString[2]");
+			Assert.AreEqual ("'m'", val.Value);
+			Assert.AreEqual ("char", val.TypeName);
+			
+			val = Eval ("alist[0]");
+			Assert.AreEqual ("1", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("alist[1]");
+			Assert.AreEqual ("\"two\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("alist[2]");
+			Assert.AreEqual ("3", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+		}
+		
+		[Test()]
+		public void MemberReference ()
+		{
+			ObjectValue val = Eval ("alist.Count");
+			Assert.AreEqual ("3", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			Eval ("var tt = this");
+			
+			val = Eval ("tt.someString");
+			Assert.AreEqual ("\"hi\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("UnitTests");
+			Assert.AreEqual ("UnitTests", val.Value);
+			Assert.AreEqual ("<namespace>", val.TypeName);
+			
+			val = Eval ("UnitTests.TestApp.MainClass");
+			Assert.AreEqual ("UnitTests.TestApp.MainClass", val.Value);
+			Assert.AreEqual ("<type>", val.TypeName);
+			
+			val = Eval ("UnitTests.TestApp.MainClass.staticString");
+			Assert.AreEqual ("\"some static\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+		}
+		
+		[Test()]
+		public void ConditionalExpression ()
+		{
+			ObjectValue val = Eval ("true ? \"yes\" : \"no\"");
+			Assert.AreEqual ("\"yes\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("false ? \"yes\" : \"no\"");
+			Assert.AreEqual ("\"no\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+		}
+		
+		[Test()]
+		public void Cast ()
+		{
+			ObjectValue val;
+			val = Eval ("(byte)n");
+			Assert.AreEqual ("32", val.Value);
+			Assert.AreEqual ("byte", val.TypeName);
+			
+			val = Eval ("(int)n");
+			Assert.AreEqual ("32", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("(long)n");
+			Assert.AreEqual ("32", val.Value);
+			Assert.AreEqual ("long", val.TypeName);
+			
+			val = Eval ("(float)n");
+			Assert.AreEqual ("32", val.Value);
+			Assert.AreEqual ("float", val.TypeName);
+			
+			val = Eval ("(double)n");
+			Assert.AreEqual ("32", val.Value);
+			Assert.AreEqual ("double", val.TypeName);
+			
+			val = Eval ("(string)staticString");
+			Assert.AreEqual ("\"some static\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("(int)numbers");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("(int)this");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("(C)a");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("(C)b");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("(C)c");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("(B)a");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("(B)b");
+			Assert.AreEqual ("{B}", val.Value);
+			Assert.AreEqual ("B", val.TypeName);
+			
+			val = Eval ("(B)c");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("(A)a");
+			Assert.AreEqual ("{A}", val.Value);
+			Assert.AreEqual ("A", val.TypeName);
+			
+			val = Eval ("(A)b");
+			Assert.AreEqual ("{B}", val.Value);
+			Assert.AreEqual ("B", val.TypeName);
+			
+			val = Eval ("(A)c");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			// Try cast
+			
+			val = Eval ("c as A");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("c as B");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("c as C");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("b as A");
+			Assert.AreEqual ("{B}", val.Value);
+			Assert.AreEqual ("B", val.TypeName);
+			
+			val = Eval ("b as B");
+			Assert.AreEqual ("{B}", val.Value);
+			Assert.AreEqual ("B", val.TypeName);
+			
+			val = Eval ("b as C");
+			Assert.AreEqual ("null", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("a as A");
+			Assert.AreEqual ("{A}", val.Value);
+			Assert.AreEqual ("A", val.TypeName);
+			
+			val = Eval ("a as B");
+			Assert.AreEqual ("null", val.Value);
+			Assert.AreEqual ("B", val.TypeName);
+			
+			val = Eval ("a as C");
+			Assert.AreEqual ("null", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			// Enum cast
+			
+			val = Eval ("(int)SomeEnum.two");
+			Assert.AreEqual ("2", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			
+			val = Eval ("(long)SomeEnum.two");
+			Assert.AreEqual ("2", val.Value);
+			Assert.AreEqual ("long", val.TypeName);
+			
+			val = Eval ("(SomeEnum)2");
+			Assert.AreEqual ("SomeEnum.two", val.Value);
+			Assert.AreEqual ("two", val.DisplayValue);
+			Assert.AreEqual ("SomeEnum", val.TypeName);
+			
+			val = Eval ("(SomeEnum)3");
+			Assert.AreEqual ("SomeEnum.one|SomeEnum.two", val.Value);
+			Assert.AreEqual ("one|two", val.DisplayValue);
+			Assert.AreEqual ("SomeEnum", val.TypeName);
+		}
+		
+		[Test()]
+		public void BinaryOperators ()
+		{
+			ObjectValue val;
+			
+			// Boolean
+			
+			val = Eval ("true && true");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("true && false");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("false && true");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("false && false");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("false || false");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("false || true");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("true || false");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("true || true");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("false || 1");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("1 || true");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("true && 1");
+			Assert.IsTrue (val.IsError);
+			
+			val = Eval ("1 && true");
+			Assert.IsTrue (val.IsError);
+			
+			// Concat string
+			
+			val = Eval ("\"a\" + \"b\"");
+			Assert.AreEqual ("\"ab\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("\"a\" + 2");
+			Assert.AreEqual ("\"a2\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("2 + \"a\"");
+			Assert.AreEqual ("\"2a\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			val = Eval ("this + \"a\"");
+			Assert.AreEqual ("\"UnitTests.TestApp.MainClassa\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			
+			// Equality
+			
+			val = Eval ("2 == 2");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("2 == 3");
+			Assert.AreEqual ("false", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			val = Eval ("(long)2 == (int)2");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+			
+			// Arithmetic
+			
+			val = Eval ("2 + 3");
+			Assert.AreEqual ("5", val.Value);
+			
+			val = Eval ("2 + 2 == 4");
+			Assert.AreEqual ("true", val.Value);
+			Assert.AreEqual ("bool", val.TypeName);
+		}
+		
+		[Test()]
+		public virtual void Assignment ()
+		{
+			ObjectValue val;
+			Eval ("n = 6");
+			val = Eval ("n");
+			Assert.AreEqual ("6", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			Eval ("n = 32");
+			val = Eval ("n");
+			Assert.AreEqual ("32", val.Value);
+			
+			Eval ("someString = \"test\"");
+			val = Eval ("someString");
+			Assert.AreEqual ("\"test\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			Eval ("someString = \"hi\"");
+			val = Eval ("someString");
+			Assert.AreEqual ("\"hi\"", val.Value);
+			
+			Eval ("numbers[0] = \"test\"");
+			val = Eval ("numbers[0]");
+			Assert.AreEqual ("\"test\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			Eval ("numbers[0] = \"one\"");
+			val = Eval ("numbers[0]");
+			Assert.AreEqual ("\"one\"", val.Value);
+
+			Eval ("alist[0] = 6");
+			val = Eval ("alist[0]");
+			Assert.AreEqual ("6", val.Value);
+			Assert.AreEqual ("int", val.TypeName);
+			Eval ("alist[0] = 1");
+			val = Eval ("alist[0]");
+			Assert.AreEqual ("1", val.Value);
+		}
+		
+		[Test()]
+		public virtual void AssignmentStatic ()
+		{
+			ObjectValue val;
+			
+			Eval ("staticString = \"test\"");
+			val = Eval ("staticString");
+			Assert.AreEqual ("\"test\"", val.Value);
+			Assert.AreEqual ("string", val.TypeName);
+			Eval ("staticString = \"some static\"");
+			val = Eval ("staticString");
+			Assert.AreEqual ("\"some static\"", val.Value);
+		}
+		
+		[Test()]
+		public void FormatBool ()
+		{
+			ObjectValue val;
+			val = Eval ("true");
+			Assert.AreEqual ("true", val.Value);
+			val = Eval ("false");
+			Assert.AreEqual ("false", val.Value);
+		}
+		
+		[Test()]
+		public void FormatNumber ()
+		{
+			ObjectValue val;
+			val = Eval ("(int)123");
+			Assert.AreEqual ("123", val.Value);
+			val = Eval ("(int)-123");
+			Assert.AreEqual ("-123", val.Value);
+			
+			val = Eval ("(long)123");
+			Assert.AreEqual ("123", val.Value);
+			val = Eval ("(long)-123");
+			Assert.AreEqual ("-123", val.Value);
+			
+			val = Eval ("(byte)123");
+			Assert.AreEqual ("123", val.Value);
+			
+			val = Eval ("(uint)123");
+			Assert.AreEqual ("123", val.Value);
+			
+			val = Eval ("(ulong)123");
+			Assert.AreEqual ("123", val.Value);
+			
+			val = Eval ("dec");
+			Assert.AreEqual ("123.456", val.Value);
+		}
+		
+		[Test()]
+		public void FormatString ()
+		{
+			ObjectValue val;
+			val = Eval ("\"hi\"");
+			Assert.AreEqual ("\"hi\"", val.Value);
+			
+			val = Eval ("EscapedStrings");
+			Assert.AreEqual ("\" \\\" \\\\ \\a \\b \\f \\v \\n \\r \\t\"", val.Value);
+			
+			val = Eval ("\" \\\" \\\\ \\a \\b \\f \\v \\n \\r \\t\"");
+			Assert.AreEqual ("\" \\\" \\\\ \\a \\b \\f \\v \\n \\r \\t\"", val.Value);
+		}
+		
+		[Test()]
+		public void FormatChar ()
+		{
+			ObjectValue val;
+			val = Eval ("'A'");
+			Assert.AreEqual ("'A'", val.Value);
+			Assert.AreEqual ("65 'A'", val.DisplayValue);
+			
+			val = Eval ("'\\0'");
+			Assert.AreEqual ("'\\0'", val.Value);
+			Assert.AreEqual ("0 '\\0'", val.DisplayValue);
+			
+			val = Eval ("'\"'");
+			Assert.AreEqual ("'\"'", val.Value);
+			Assert.AreEqual ("34 '\"'", val.DisplayValue);
+			
+			val = Eval ("'\\''");
+			Assert.AreEqual ("'\\''", val.Value);
+			Assert.AreEqual ("39 '\\''", val.DisplayValue);
+			
+			val = Eval ("'\\\\'");
+			Assert.AreEqual ("'\\\\'", val.Value);
+			Assert.AreEqual ("92 '\\\\'", val.DisplayValue);
+			
+			val = Eval ("'\\a'");
+			Assert.AreEqual ("'\\a'", val.Value);
+			Assert.AreEqual ("7 '\\a'", val.DisplayValue);
+			
+			val = Eval ("'\\b'");
+			Assert.AreEqual ("'\\b'", val.Value);
+			Assert.AreEqual ("8 '\\b'", val.DisplayValue);
+			
+			val = Eval ("'\\f'");
+			Assert.AreEqual ("'\\f'", val.Value);
+			Assert.AreEqual ("12 '\\f'", val.DisplayValue);
+			
+			val = Eval ("'\\v'");
+			Assert.AreEqual ("'\\v'", val.Value);
+			Assert.AreEqual ("11 '\\v'", val.DisplayValue);
+			
+			val = Eval ("'\\n'");
+			Assert.AreEqual ("'\\n'", val.Value);
+			Assert.AreEqual ("10 '\\n'", val.DisplayValue);
+			
+			val = Eval ("'\\r'");
+			Assert.AreEqual ("'\\r'", val.Value);
+			Assert.AreEqual ("13 '\\r'", val.DisplayValue);
+			
+			val = Eval ("'\\t'");
+			Assert.AreEqual ("'\\t'", val.Value);
+			Assert.AreEqual ("9 '\\t'", val.DisplayValue);
+		}
+		
+		[Test()]
+		public void FormatObject ()
+		{
+			ObjectValue val;
+			
+			val = Eval ("c");
+			Assert.AreEqual ("{C}", val.Value);
+			Assert.AreEqual ("C", val.TypeName);
+			
+			val = Eval ("withDisplayString");
+			Assert.AreEqual ("Some one Value 2 End", val.Value);
+			Assert.AreEqual ("WithDisplayString", val.TypeName);
+			
+			val = Eval ("withProxy");
+			Assert.AreEqual ("{WithProxy}", val.Value);
+			Assert.AreEqual ("WithProxy", val.TypeName);
+			
+/*			val = Eval ("withToString");
+			Assert.AreEqual ("{SomeString}", val.Value);
+			Assert.AreEqual ("WithToString", val.TypeName);*/
+		}
+		
+		[Test()]
+		public void FormatArray ()
+		{
+			ObjectValue val;
+			
+			val = Eval ("numbers");
+			Assert.AreEqual ("{string[3]}", val.Value);
+			Assert.AreEqual ("string[]", val.TypeName);
+			
+			val = Eval ("numbersArrays");
+			Assert.AreEqual ("{int[2][]}", val.Value);
+			Assert.AreEqual ("int[][]", val.TypeName);
+			
+			val = Eval ("numbersMulti");
+			Assert.AreEqual ("{int[3,4,5]}", val.Value);
+			Assert.AreEqual ("int[,,]", val.TypeName);
+		}
+		
+		[Test()]
+		public void FormatGeneric ()
+		{
+			ObjectValue val;
+		
+			ds.Options.EvaluationOptions.AllowTargetInvoke = false;
+			val = Eval ("dict");
+			ds.Options.EvaluationOptions.AllowTargetInvoke = true;
+			Assert.AreEqual ("{System.Collections.Generic.Dictionary<int,string[]>}", val.Value);
+			Assert.AreEqual ("System.Collections.Generic.Dictionary<int,string[]>", val.TypeName);
+			
+			ds.Options.EvaluationOptions.AllowTargetInvoke = false;
+			val = Eval ("dictArray");
+			ds.Options.EvaluationOptions.AllowTargetInvoke = true;
+			Assert.AreEqual ("{System.Collections.Generic.Dictionary<int,string[]>[2,3]}", val.Value);
+			Assert.AreEqual ("System.Collections.Generic.Dictionary<int,string[]>[,]", val.TypeName);
+			
+			val = Eval ("thing.done");
+			Assert.AreEqual ("{Thing<string>.Done<int>[1]}", val.Value);
+			Assert.AreEqual ("Thing<string>.Done<int>[]", val.TypeName);
+			
+			val = Eval ("done");
+			Assert.AreEqual ("{Thing<string>.Done<int>}", val.Value);
+			Assert.AreEqual ("Thing<string>.Done<int>", val.TypeName);
+		}
+		
+		[Test()]
+		public void FormatEnum ()
+		{
+			ObjectValue val;
+			
+			val = Eval ("SomeEnum.one");
+			Assert.AreEqual ("SomeEnum.one", val.Value);
+			Assert.AreEqual ("one", val.DisplayValue);
+			
+			val = Eval ("SomeEnum.two");
+			Assert.AreEqual ("SomeEnum.two", val.Value);
+			Assert.AreEqual ("two", val.DisplayValue);
+			
+			val = Eval ("SomeEnum.one | SomeEnum.two");
+			Assert.AreEqual ("SomeEnum.one|SomeEnum.two", val.Value);
+			Assert.AreEqual ("one|two", val.DisplayValue);
+		}
+	}
+}
diff --git a/UnitTests/UnitTests/SdbEvaluationTests.cs b/UnitTests/UnitTests/SdbEvaluationTests.cs
new file mode 100644
index 0000000..ed26d34
--- /dev/null
+++ b/UnitTests/UnitTests/SdbEvaluationTests.cs
@@ -0,0 +1,48 @@
+// 
+// SdbEvaluationTests.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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 NUnit.Framework;
+using Mono.Debugging.Client;
+using Mono.Debugging.Soft;
+using System.Collections.Generic;
+
+namespace Mono.Debugging.UnitTests
+{
+	[TestFixture()]
+	public class SdbEvaluationTests: EvaluationTests
+	{
+		protected override DebuggerSession CreateDebuggerSession ()
+		{
+			return new SoftDebuggerSession ();
+		}
+
+		protected override DebuggerStartInfo CreateDebuggerStartInfo ()
+		{
+			return new SoftDebuggerStartInfo (null, new Dictionary<string,string> ());
+		}
+	}
+}
diff --git a/UnitTests/UnitTests/SdbStackFrameTests.cs b/UnitTests/UnitTests/SdbStackFrameTests.cs
new file mode 100644
index 0000000..70b271b
--- /dev/null
+++ b/UnitTests/UnitTests/SdbStackFrameTests.cs
@@ -0,0 +1,49 @@
+// 
+// SdbStackFrameTests.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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 NUnit.Framework;
+using Mono.Debugging.Client;
+using Mono.Debugging.Soft;
+using System.Collections.Generic;
+
+namespace Mono.Debugging.UnitTests
+{
+	[TestFixture()]
+	public class SdbStackFrameTests: StackFrameTests
+	{
+		protected override DebuggerSession CreateDebuggerSession ()
+		{
+			return new SoftDebuggerSession ();
+		}
+
+		protected override DebuggerStartInfo CreateDebuggerStartInfo ()
+		{
+			return new SoftDebuggerStartInfo (null, new Dictionary<string,string> ());
+		}
+	}
+}
+
diff --git a/UnitTests/UnitTests/StackFrameTests.cs b/UnitTests/UnitTests/StackFrameTests.cs
new file mode 100644
index 0000000..59127a8
--- /dev/null
+++ b/UnitTests/UnitTests/StackFrameTests.cs
@@ -0,0 +1,122 @@
+// 
+// StackFrameTests.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2010 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 Mono.Debugging.Client;
+using NUnit.Framework;
+
+namespace Mono.Debugging.UnitTests
+{
+	public abstract class StackFrameTests: DebugTests
+	{
+		DebuggerSession ds;
+		StackFrame frame;
+		
+		[TestFixtureSetUp]
+		public void Setup ()
+		{
+			ds = Start ("TestEvaluation");
+			frame = ds.ActiveThread.Backtrace.GetFrame (0);
+		}
+		
+		[TestFixtureTearDown]
+		public void TearDown ()
+		{
+			ds.Exit ();
+			ds.Dispose ();
+		}
+		
+		public StackFrame Frame {
+			get { return frame; }
+		}
+		
+		[Test]
+		public void VirtualProperty ()
+		{
+			EvaluationOptions ops = EvaluationOptions.DefaultOptions.Clone ();
+			ops.FlattenHierarchy = false;
+			
+			ObjectValue val = Frame.GetExpressionValue ("c", ops);
+			Assert.IsNotNull (val);
+			val.WaitHandle.WaitOne ();
+			Assert.IsFalse (val.IsError);
+			Assert.IsFalse (val.IsUnknown);
+			
+			// The C class does not have a Prop property
+			
+			ObjectValue prop = val.GetChild ("Prop", ops);
+			Assert.IsNull (prop);
+			
+			prop = val.GetChild ("PropNoVirt1", ops);
+			Assert.IsNull (prop);
+			
+			prop = val.GetChild ("PropNoVirt2", ops);
+			Assert.IsNull (prop);
+			
+			val = val.GetChild ("base", ops);
+			Assert.IsNotNull (val);
+			val.WaitHandle.WaitOne ();
+			Assert.IsFalse (val.IsError);
+			Assert.IsFalse (val.IsUnknown);
+			
+			// The B class has a Prop property, value is 2
+			
+			prop = val.GetChild ("Prop", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("2", prop.Value);
+			
+			prop = val.GetChild ("PropNoVirt1", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("2", prop.Value);
+			
+			prop = val.GetChild ("PropNoVirt2", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("2", prop.Value);
+			
+			val = val.GetChild ("base", ops);
+			Assert.IsNotNull (val);
+			val.WaitHandle.WaitOne ();
+			Assert.IsFalse (val.IsError);
+			Assert.IsFalse (val.IsUnknown);
+			
+			// The A class has a Prop property, value is 1, but must return 2 becasue it is overriden
+			
+			prop = val.GetChild ("Prop", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("2", prop.Value);
+			
+			prop = val.GetChild ("PropNoVirt1", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("1", prop.Value);
+			
+			prop = val.GetChild ("PropNoVirt2", ops);
+			Assert.IsNotNull (prop);
+			Assert.AreEqual ("1", prop.Value);
+		}
+		
+	}
+}
+
diff --git a/UnitTests/UnitTests/UnitTests.TestApp/Main.cs b/UnitTests/UnitTests/UnitTests.TestApp/Main.cs
new file mode 100644
index 0000000..8de7934
--- /dev/null
+++ b/UnitTests/UnitTests/UnitTests.TestApp/Main.cs
@@ -0,0 +1,179 @@
+// 
+// Main.cs
+//  
+// Author:
+//       Lluis Sanchez Gual <lluis at novell.com>
+// 
+// Copyright (c) 2009 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.Diagnostics;
+
+namespace UnitTests.TestApp
+{
+	class MainClass
+	{
+		public static void Main (string[] args)
+		{
+			MainClass mc = new MainClass ();
+			typeof (MainClass).GetMethod (args[0]).Invoke (mc, null);
+		}
+
+		// Tests
+
+		static string staticString = "some static";
+		string someString = "hi";
+		string[] numbers = new string[] { "one","two","three" };
+
+		public void TestEvaluation ()
+		{
+			int n = 32;
+			decimal dec = 123.456m;
+			ArrayList alist = new ArrayList ();
+			alist.Add (1);
+			alist.Add ("two");
+			alist.Add (3);
+
+			A c = new C ();
+			A b = new B ();
+			A a = new A ();
+
+			WithDisplayString withDisplayString = new WithDisplayString ();
+			WithProxy withProxy = new WithProxy ();
+			WithToString withToString = new WithToString ();
+
+			int[][] numbersArrays = new int [2][];
+			int[,,] numbersMulti = new int [3,4,5];
+
+			var dict = new Dictionary<int, string[]> ();
+			var dictArray = new Dictionary<int, string[]> [2,3];
+			var thing = new Thing<string> ();
+			var done = new Thing<string>.Done<int> ();
+
+			Console.WriteLine (n); Debugger.Break ();
+		}
+
+		public int TestMethod ()
+		{
+			float c = 4;
+			return 1;
+		}
+
+		public int TestMethod (string a)
+		{
+			return int.Parse (a) + 1;
+		}
+
+		public int TestMethod (int a)
+		{
+			return a + 1;
+		}
+
+		public static int TestMethod (bool b)
+		{
+			return b ? 1 : 2;
+		}
+
+		public string BoxingTestMethod (object a)
+		{
+			return a.ToString ();
+		}
+
+		public string EscapedStrings {
+			get { return " \" \\ \a \b \f \v \n \r \t"; }
+		}
+	}
+}
+
+class A
+{
+	public virtual int Prop { get { return 1; } }
+	public int PropNoVirt1 { get { return 1; } }
+	public virtual int PropNoVirt2 { get { return 1; } }
+}
+
+class B: A
+{
+	public override int Prop { get { return 2; } }
+	public new int PropNoVirt1 { get { return 2; } }
+	public new int PropNoVirt2 { get { return 2; } }
+}
+
+class C: B
+{
+}
+
+[DebuggerDisplay ("Some {Val1} Value {Val2} End")]
+class WithDisplayString
+{
+	internal string Val1 = "one";
+	public int Val2 { get { return 2; } }
+}
+
+class WithToString
+{
+	public override string ToString ()
+	{
+		return "SomeString";
+	}
+}
+
+[DebuggerTypeProxy (typeof(TheProxy))]
+class WithProxy
+{
+	public string Val1 {
+		get { return "one"; }
+	}
+}
+
+class TheProxy
+{
+	WithProxy wp;
+
+	public TheProxy (WithProxy wp)
+	{
+		this.wp = wp;
+	}
+
+	public string Val1 {
+		get { return wp.Val1; } 
+	}
+}
+
+class Thing<T>
+{
+	public class Done<U>
+	{
+	}
+
+	public Done<int>[] done = new Done<int> [1];
+}
+
+[Flags]
+enum SomeEnum
+{
+	none=0,
+	one=1,
+	two=2,
+	four=4
+}
diff --git a/UnitTests/UnitTests/UnitTests.TestApp/Properties/AssemblyInfo.cs b/UnitTests/UnitTests/UnitTests.TestApp/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c1fb439
--- /dev/null
+++ b/UnitTests/UnitTests/UnitTests.TestApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes. 
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("UnitTests.TestApp")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Xamarin Inc.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly, 
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/UnitTests/UnitTests/UnitTests.TestApp/UnitTests.TestApp.csproj b/UnitTests/UnitTests/UnitTests.TestApp/UnitTests.TestApp.csproj
new file mode 100644
index 0000000..f3b415a
--- /dev/null
+++ b/UnitTests/UnitTests/UnitTests.TestApp/UnitTests.TestApp.csproj
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>UnitTests.TestApp</RootNamespace>
+    <AssemblyName>UnitTests.TestApp</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Externalconsole>true</Externalconsole>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Externalconsole>true</Externalconsole>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Main.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/UnitTests/UnitTests/UnitTests.csproj b/UnitTests/UnitTests/UnitTests.csproj
new file mode 100644
index 0000000..37be7da
--- /dev/null
+++ b/UnitTests/UnitTests/UnitTests.csproj
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0349A5CF-1F90-4055-A3B2-BDAA347AED71}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>UnitTests</RootNamespace>
+    <AssemblyName>UnitTests</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="nunit.framework">
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Compile Include="DebugTests.cs" />
+    <Compile Include="EvaluationTests.cs" />
+    <Compile Include="SdbEvaluationTests.cs" />
+    <Compile Include="SdbStackFrameTests.cs" />
+    <Compile Include="StackFrameTests.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Mono.Debugging\Mono.Debugging.csproj">
+      <Project>{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}</Project>
+      <Name>Mono.Debugging</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Mono.Debugging.Soft\Mono.Debugging.Soft.csproj">
+      <Project>{DE40756E-57F6-4AF2-B155-55E3A88CCED8}</Project>
+      <Name>Mono.Debugging.Soft</Name>
+    </ProjectReference>
+    <ProjectReference Include="UnitTests.TestApp\UnitTests.TestApp.csproj">
+      <Project>{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}</Project>
+      <Name>UnitTests.TestApp</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Mono.Debugger.Soft\Mono.Debugger.Soft.csproj">
+      <Project>{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}</Project>
+      <Name>Mono.Debugger.Soft</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/debugger-libs.sln b/debugger-libs.sln
new file mode 100644
index 0000000..649b0e0
--- /dev/null
+++ b/debugger-libs.sln
@@ -0,0 +1,302 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Debugger.Soft", "Mono.Debugger.Soft\Mono.Debugger.Soft.csproj", "{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "..\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj", "{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSharp", "..\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj", "{53DCA265-3C3C-42F9-B647-F72BA678122B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Debugging", "Mono.Debugging\Mono.Debugging.csproj", "{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil.Mdb", "..\cecil\symbols\mdb\Mono.Cecil.Mdb.csproj", "{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Debugging.Soft", "Mono.Debugging.Soft\Mono.Debugging.Soft.csproj", "{DE40756E-57F6-4AF2-B155-55E3A88CCED8}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unit Tests", "Unit Tests", "{66CF303B-09F8-4123-B869-0608D54B1970}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "UnitTests\UnitTests\UnitTests.csproj", "{0349A5CF-1F90-4055-A3B2-BDAA347AED71}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.TestApp", "UnitTests\UnitTests\UnitTests.TestApp\UnitTests.TestApp.csproj", "{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+		net_2_0_Debug|Any CPU = net_2_0_Debug|Any CPU
+		net_2_0_Release|Any CPU = net_2_0_Release|Any CPU
+		net_3_5_Debug|Any CPU = net_3_5_Debug|Any CPU
+		net_3_5_Release|Any CPU = net_3_5_Release|Any CPU
+		net_4_0_Debug|Any CPU = net_4_0_Debug|Any CPU
+		net_4_0_Release|Any CPU = net_4_0_Release|Any CPU
+		silverlight_Debug|Any CPU = silverlight_Debug|Any CPU
+		silverlight_Release|Any CPU = silverlight_Release|Any CPU
+		winphone_Debug|Any CPU = winphone_Debug|Any CPU
+		winphone_Release|Any CPU = winphone_Release|Any CPU
+		net_4_5_Debug|Any CPU = net_4_5_Debug|Any CPU
+		net_4_5_Release|Any CPU = net_4_5_Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.net_4_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.Release|Any CPU.Build.0 = Release|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.net_4_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.Release|Any CPU.Build.0 = Release|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.net_4_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.Release|Any CPU.Build.0 = Release|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{372E8E3E-29D5-4B4D-88A2-4711CD628C4E}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_5_Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_5_Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.net_4_5_Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_5_Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_5_Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_5_Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.net_4_5_Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|Any CPU.Build.0 = Release|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{53DCA265-3C3C-42F9-B647-F72BA678122B}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.net_4_5_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.silverlight_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{8559DD7F-A16F-46D0-A05A-9139FAEBA8FD}.winphone_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.net_4_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{90C99ADB-7D4B-4EB4-98C2-40BD1B14C7D2}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_2_0_Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Debug|Any CPU.Build.0 = net_3_5_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_3_5_Release|Any CPU.Build.0 = net_3_5_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_0_Release|Any CPU.Build.0 = net_4_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Debug|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Debug|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Release|Any CPU.ActiveCfg = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.net_4_5_Release|Any CPU.Build.0 = net_2_0_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_2_0_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.ActiveCfg = silverlight_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Debug|Any CPU.Build.0 = silverlight_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.ActiveCfg = silverlight_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.silverlight_Release|Any CPU.Build.0 = silverlight_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.ActiveCfg = winphone_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Debug|Any CPU.Build.0 = winphone_Debug|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.ActiveCfg = winphone_Release|Any CPU
+		{D68133BD-1E63-496E-9EDE-4FBDBF77B486}.winphone_Release|Any CPU.Build.0 = winphone_Release|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_2_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_2_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_2_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_2_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_3_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_3_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_3_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_3_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_0_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_0_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_0_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_0_Release|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_5_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_5_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_5_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.net_4_5_Release|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.silverlight_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.silverlight_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.silverlight_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.silverlight_Release|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.winphone_Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.winphone_Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.winphone_Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{DE40756E-57F6-4AF2-B155-55E3A88CCED8}.winphone_Release|Any CPU.Build.0 = Debug|Any CPU
+	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{0349A5CF-1F90-4055-A3B2-BDAA347AED71} = {66CF303B-09F8-4123-B869-0608D54B1970}
+		{19C3E201-4625-48B7-8E89-4ED9BA3BBD52} = {66CF303B-09F8-4123-B869-0608D54B1970}
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = Mono.Debugger.Soft\Mono.Debugger.Soft.csproj
+	EndGlobalSection
+EndGlobal

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cli-libs/packages/mono-debugger-libs.git



More information about the Pkg-cli-libs-commits mailing list