[Pkg-cli-apps-commits] [SCM] monodevelop branch, master-experimental, updated. debian/2.4+dfsg-3-8-g1207056

Jo Shields directhex at apebox.org
Sat Dec 18 11:57:29 UTC 2010


The following commit has been merged in the master-experimental branch:
commit 1207056ad938826c28aa9c9d0e3c68704a768a9a
Author: Jo Shields <directhex at apebox.org>
Date:   Sat Dec 18 11:53:45 2010 +0000

    Inject a snapshot of the Mono Soft Debugger source from 2010-10-23 (as found in Mono commitid fbd6abac72ec96f2034d), along with some build system special sauce (as found in Debian MonoDevelop commitid 9915fc77e5385d377241. This is needed because MonoDevelop 2.4.1 makes use of methods in Mono.Debugger.Soft which post-date the release of Mono 2.6.7, our Squeeze release version. And upstream's just-bundle-the-DLL-in-the-source route is inappropriate for Debian.

diff --git a/debian/patches/inject_Mono.Debugger.Soft_source.patch b/debian/patches/inject_Mono.Debugger.Soft_source.patch
new file mode 100644
index 0000000..e423b2d
--- /dev/null
+++ b/debian/patches/inject_Mono.Debugger.Soft_source.patch
@@ -0,0 +1,9173 @@
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AbsentInformationException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AbsentInformationException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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.") {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainCreateEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainCreateEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,95 @@
++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 {
++				if (friendly_name == null)
++					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];
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainUnloadEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AppDomainUnloadEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ArrayMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ArrayMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,140 @@
++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) {
++		}
++
++		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 ();
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyLoadEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyUnloadEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/AssemblyUnloadEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/BreakpointEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/BreakpointEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/BreakpointEventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/BreakpointEventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Connection.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,1820 @@
++using System;
++using System.IO;
++using System.Net;
++using System.Net.Sockets;
++using System.Threading;
++using System.Collections.Generic;
++using System.Text;
++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;
++		}
++	}
++
++	class DebugInfo {
++		public int max_il_offset;
++		public string filename;
++		public int[] il_offsets;
++		public int[] line_numbers;
++	}
++
++	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 long[] nested;
++	}
++
++	class MethodInfo {
++		public int attributes, iattributes, token;
++	}
++
++	class MethodBodyInfo {
++		public byte[] il;
++	}
++
++	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;
++	}
++
++	enum ValueTypeId {
++		VALUE_TYPE_ID_NULL = 0xf0,
++		VALUE_TYPE_ID_TYPE = 0xf1
++	}
++
++	enum InvokeFlags {
++		NONE = 0x0,
++		DISABLE_BREAKPOINTS = 0x1,
++		SINGLE_THREADED = 0x2
++	}
++
++	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
++	}
++
++	enum StackFrameFlags {
++		DEBUGGER_INVOKE = 1
++	}
++
++	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;
++		}
++	}
++
++	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;
++		}
++	}
++
++	class AssemblyModifier : Modifier {
++		public long[] Assemblies {
++			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 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
++	}
++
++	public class ErrorHandlerEventArgs : EventArgs {
++
++		public ErrorCode ErrorCode {
++			get; set;
++		}
++	}
++
++	/*
++	 * Represents the connection to the debuggee
++	 */
++	class Connection
++	{
++		/*
++		 * The protocol and the packet format is based on JDWP, the differences 
++		 * are in the set of supported events, and the commands.
++		 */
++		public const string HANDSHAKE_STRING = "DWP-Handshake";
++
++		public const int HEADER_LENGTH = 11;
++
++		/*
++		 * 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.
++		 */
++		public const int MAJOR_VERSION = 2;
++		public const int MINOR_VERSION = 2;
++
++		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
++		}
++
++		enum ModifierKind {
++			COUNT = 1,
++			THREAD_ONLY = 3,
++			LOCATION_ONLY = 7,
++			EXCEPTION_ONLY = 8,
++			STEP = 10,
++			ASSEMBLY_ONLY = 11
++		}
++
++		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
++		}
++
++		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
++		}
++
++		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
++		}
++
++		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
++		}
++
++		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
++		}
++
++		enum CmdObjectRef {
++			GET_TYPE = 1,
++			GET_VALUES = 2,
++			IS_COLLECTED = 3,
++			GET_ADDRESS = 4,
++			GET_DOMAIN = 5,
++			SET_VALUES = 6
++		}
++
++		class Header {
++			public int id;
++			public int command_set;
++			public int command;
++			public int flags;
++		}			
++
++		public static int GetPacketLength (byte[] header) {
++			int offset = 0;
++			return decode_int (header, ref offset);
++		}
++
++		public static bool IsReplyPacket (byte[] packet) {
++			int offset = 8;
++			return decode_byte (packet, ref offset) == 0x80;
++		}
++
++		public 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);
++		}
++
++		public 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);
++		}
++
++		public 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);
++				}
++			}
++		}
++
++		class PacketWriter {
++
++			byte[] data;
++			int offset;
++
++			public PacketWriter () {
++				// FIXME:
++				data = new byte [1024];
++				offset = 0;
++			}
++
++			public PacketWriter WriteByte (byte val) {
++				encode_byte (data, val, ref offset);
++				return this;
++			}
++
++			public PacketWriter WriteInt (int val) {
++				encode_int (data, val, ref offset);
++				return this;
++			}
++
++			public PacketWriter WriteId (long id) {
++				encode_id (data, id, ref offset);
++				return this;
++			}
++
++			public PacketWriter WriteLong (long val) {
++				encode_long (data, val, ref offset);
++				return this;
++			}
++
++			public PacketWriter WriteFloat (float f) {
++				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) {
++				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) {
++				encode_int (data, s.Length, ref offset);
++				byte[] b = Encoding.UTF8.GetBytes (s);
++				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);
++
++		Socket socket;
++		bool closed;
++		Thread receiver_thread;
++		Dictionary<int, byte[]> reply_packets;
++		Dictionary<int, ReplyCallback> reply_cbs;
++		object reply_packets_monitor;
++
++		public event EventHandler<ErrorHandlerEventArgs> ErrorHandler;
++
++		public Connection (Socket socket) {
++			this.socket = socket;
++			//socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.NoDelay, 1);
++			closed = false;
++			reply_packets = new Dictionary<int, byte[]> ();
++			reply_cbs = new Dictionary<int, ReplyCallback> ();
++			reply_packets_monitor = new Object ();
++		}
++
++		int Receive (byte[] buf, int buf_offset, int len) {
++			int offset = 0;
++
++			while (offset < len) {
++				int n = socket.Receive (buf, buf_offset + offset, len - offset, SocketFlags.None);
++
++				if (n == 0)
++					return offset;
++				offset += n;
++			}
++
++			return offset;
++		}
++
++		public VersionInfo Version;
++
++		// Do the wire protocol handshake
++		public 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.");
++
++			socket.Send (buf);
++
++			receiver_thread = new Thread (new ThreadStart (receiver_thread_main));
++			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;
++		}
++
++		public EndPoint EndPoint {
++			get {
++				return socket.RemoteEndPoint;
++			}
++		}
++
++		public 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;
++			}
++		}
++
++		public void WritePacket (byte[] packet) {
++			// FIXME: Throw ClosedConnectionException () if the connection is closed
++			// FIXME: Throw ClosedConnectionException () if another thread closes the connection
++			// FIXME: Locking
++			socket.Send (packet);
++		}
++
++		public void Close () {
++			closed = true;
++		}
++
++		public bool IsClosed {
++			get {
++				return closed;
++			}
++		}
++
++		bool disconnected;
++
++		void receiver_thread_main () {
++			while (true) {
++				try {
++					bool res = ReceivePacket ();
++					if (!res)
++						break;
++				} catch (Exception ex) {
++					Console.WriteLine (ex);
++					break;
++				}
++			}
++
++			lock (reply_packets_monitor) {
++				disconnected = true;
++				Monitor.PulseAll (reply_packets_monitor);
++			}
++			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);
++						}
++					}
++
++					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 {
++								throw new NotImplementedException ("Unknown event kind: " + kind);
++							}
++						}
++
++						EventHandler.Events (suspend_policy, events);
++					}
++				}
++
++				return true;
++		}
++
++		public IEventHandler EventHandler {
++			get; set;
++		}
++
++		/* Send a request and call cb when a result is received */
++		int Send (CommandSet command_set, int command, PacketWriter packet, Action<PacketReader> cb) {
++			int id = IdGenerator;
++
++			lock (reply_packets_monitor) {
++				reply_cbs [id] = delegate (int packet_id, byte[] p) {
++					/* Run the callback on a tp thread to avoid blocking the receive thread */
++					PacketReader r = new PacketReader (p);
++					cb.BeginInvoke (r, null, null);
++				};
++			}
++						
++			if (packet == null)
++				WritePacket (EncodePacket (id, (int)command_set, command, null, 0));
++			else
++				WritePacket (EncodePacket (id, (int)command_set, command, packet.Data, packet.Offset));
++
++			return id;
++		}
++
++		PacketReader SendReceive (CommandSet command_set, int command, PacketWriter packet) {
++			int id = IdGenerator;
++
++			if (packet == null)
++				WritePacket (EncodePacket (id, (int)command_set, command, null, 0));
++			else
++				WritePacket (EncodePacket (id, (int)command_set, command, packet.Data, packet.Offset));
++
++			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 (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
++		 */
++
++		public 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;
++		}
++
++		public void VM_SetProtocolVersion (int major, int minor) {
++			SendReceive (CommandSet.VM, (int)CmdVM.SET_PROTOCOL_VERSION, new PacketWriter ().WriteInt (major).WriteInt (minor));
++		}
++
++		public 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;
++		}
++
++		public void VM_Suspend () {
++			SendReceive (CommandSet.VM, (int)CmdVM.SUSPEND);
++		}
++
++		public void VM_Resume () {
++			SendReceive (CommandSet.VM, (int)CmdVM.RESUME);
++		}
++
++		public void VM_Exit (int exitCode) {
++			SendReceive (CommandSet.VM, (int)CmdVM.EXIT, new PacketWriter ().WriteInt (exitCode));
++		}
++
++		public void VM_Dispose () {
++			SendReceive (CommandSet.VM, (int)CmdVM.DISPOSE);
++		}
++
++		public 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 ();
++			}
++		}
++
++		public delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ErrorCode error, object state);
++
++		public 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);
++					}
++				});
++		}
++
++		public void VM_AbortInvoke (long thread, int id)
++		{
++			SendReceive (CommandSet.VM, (int)CmdVM.ABORT_INVOKE, new PacketWriter ().WriteId (thread).WriteInt (id));
++		}
++
++		/*
++		 * DOMAIN
++		 */
++
++		public long RootDomain {
++			get {
++				return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ROOT_DOMAIN, null).ReadId ();
++			}
++		}
++
++		public string Domain_GetName (long id) {
++			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_FRIENDLY_NAME, new PacketWriter ().WriteId (id)).ReadString ();
++		}
++
++		public 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;
++		}
++
++		public long Domain_GetEntryAssembly (long id) {
++			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ENTRY_ASSEMBLY, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public long Domain_GetCorlib (long id) {
++			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_CORLIB, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public long Domain_CreateString (long id, string s) {
++			return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.CREATE_STRING, new PacketWriter ().WriteId (id).WriteString (s)).ReadId ();
++		}
++
++		public 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
++		 */
++
++		public string Method_GetName (long id) {
++			return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
++		}
++
++		public long Method_GetDeclaringType (long id) {
++			return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_DECLARING_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public 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 ();
++			info.filename = res.ReadString ();
++
++			int n_il_offsets = res.ReadInt ();
++			info.il_offsets = new int [n_il_offsets];
++			info.line_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 ();
++			}
++
++			return info;
++		}
++
++		public 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;
++		}
++
++		public 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;
++		}
++
++		public 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 ();
++
++			return info;
++		}
++
++		public 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 ();
++
++			return info;
++		}
++
++		public 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 ();
++			}
++		}
++
++		/*
++		 * THREAD
++		 */
++
++		public string Thread_GetName (long id) {
++			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
++		}
++
++		public 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) {
++				frames [i].id = res.ReadInt ();
++				frames [i].method = res.ReadId ();
++				frames [i].il_offset = res.ReadInt ();
++				frames [i].flags = (StackFrameFlags)res.ReadByte ();
++			}
++			return frames;
++		}
++
++		public int Thread_GetState (long id) {
++			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_STATE, new PacketWriter ().WriteId (id)).ReadInt ();
++		}
++
++		public 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;
++		}
++
++		public long Thread_GetId (long id) {
++			return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_ID, new PacketWriter ().WriteId (id)).ReadLong ();
++		}
++
++		/*
++		 * MODULE
++		 */
++
++		public 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
++		 */
++
++		public string Assembly_GetLocation (long id) {
++			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_LOCATION, new PacketWriter ().WriteId (id)).ReadString ();
++		}
++
++		public long Assembly_GetEntryPoint (long id) {
++			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_ENTRY_POINT, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public long Assembly_GetManifestModule (long id) {
++			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_MANIFEST_MODULE, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public long Assembly_GetObject (long id) {
++			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public 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 ();
++		}
++
++		public string Assembly_GetName (long id) {
++			return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
++		}
++
++		/*
++		 * TYPE
++		 */
++
++		public 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;
++
++			int nested_len = r.ReadInt ();
++			res.nested = new long [nested_len];
++			for (int i = 0; i < nested_len; ++i)
++				res.nested [i] = r.ReadId ();
++
++			return res;
++		}
++
++		public 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;
++		}
++
++		public 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;
++		}
++
++		public 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;
++		}
++
++		public long Type_GetObject (long id) {
++			return SendReceive (CommandSet.TYPE, (int)CmdType.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
++		}
++
++		public ValueImpl[] Type_GetValues (long id, long[] fields) {
++			int len = fields.Length;
++			PacketReader 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;
++		}			
++
++		public 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));
++		}
++
++		public 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;
++		}
++
++		public 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;
++		}
++
++		public 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);
++		}
++
++		public 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);
++		}
++
++		public 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);
++		}
++			
++		/*
++		 * EVENTS
++		 */
++
++		public 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);
++					} 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.");
++						}
++					} 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 {
++						throw new NotImplementedException ();
++					}
++				}
++			} else {
++				w.WriteByte (0);
++			}
++			return SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.SET, w).ReadInt ();
++		}
++
++		public void ClearEventRequest (EventType etype, int req_id) {
++			SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR, new PacketWriter ().WriteByte ((byte)etype).WriteInt (req_id));
++		}			
++
++		public void ClearAllBreakpoints () {
++			SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR_ALL_BREAKPOINTS, new PacketWriter ());
++		}
++			
++		/*
++		 * STACK FRAME
++		 */
++		public 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 ();
++		}
++
++		public 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;
++		}
++
++		public 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
++		 */
++		public 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;
++		}
++
++		public 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;
++		}
++
++		public 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
++		 */
++		public string String_GetValue (long id) {
++			return SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_VALUE, new PacketWriter ().WriteId (id)).ReadString ();
++		}			
++
++		/*
++		 * OBJECTS
++		 */
++		public long Object_GetType (long id) {
++			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
++		}			
++
++		public long Object_GetDomain (long id) {
++			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_DOMAIN, new PacketWriter ().WriteId (id)).ReadId ();
++		}			
++
++		public 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;
++		}
++
++		public 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));
++		}
++
++		public bool Object_IsCollected (long id) {
++			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.IS_COLLECTED, new PacketWriter ().WriteId (id)).ReadInt () == 1;
++		}			
++
++		public long Object_GetAddress (long id) {
++			return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_ADDRESS, new PacketWriter ().WriteId (id)).ReadLong ();
++		}			
++
++	}
++
++	/* 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);
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeDataMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeDataMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,143 @@
++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);
++
++					if (arg.is_property) {
++						foreach (var prop in ctor.DeclaringType.GetProperties ()) {
++							if (prop.Id == arg.id)
++								named_args [j] = new CustomAttributeNamedArgumentMirror (prop, null, val);
++						}
++					} else {
++						foreach (var field in ctor.DeclaringType.GetFields ()) {
++							if (field.Id == arg.id)
++								named_args [j] = new CustomAttributeNamedArgumentMirror (null, field, val);
++						}
++					}
++					if (named_args [j] == null)
++						throw new NotImplementedException ();
++				}
++				res [i] = new CustomAttributeDataMirror (vm.GetMethod (attr.ctor_id), ctor_args, named_args);
++			}
++
++			return res;
++		}
++	}
++
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/DataConverter.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/DataConverter.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
++		
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EnumMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EnumMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Event.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Event.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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);
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventQueueImpl.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventQueueImpl.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventType.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventType.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,23 @@
++
++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,
++		// Not part of the wire protocol
++		VMDisconnect = 99
++	}
++}
+\ No newline at end of file
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ExceptionEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ExceptionEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,35 @@
++using System;
++using System.Collections.Generic;
++
++namespace Mono.Debugger.Soft
++{
++	public sealed class ExceptionEventRequest : EventRequest {
++
++		TypeMirror exc_type;
++		bool caught, uncaught;
++		
++		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;
++		}
++
++		public TypeMirror ExceptionType {
++			get {
++				return exc_type;
++			}
++		}
++
++		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 });
++			SendReq (mods);
++		}
++	}
++}
+\ No newline at end of file
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/FieldInfoMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/FieldInfoMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,159 @@
++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;
++
++		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);
++		}
++
++		CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
++			// 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 ();
++		}
++	}
++}
++
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/IInvokeAsyncResult.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/IInvokeAsyncResult.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,10 @@
++using System;
++using System.Collections.Generic;
++
++namespace Mono.Debugger.Soft
++{
++	public interface IInvokeAsyncResult : IAsyncResult
++	{
++		void Abort ();
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ILInstruction.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ILInstruction.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/IMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ITargetProcess.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ITargetProcess.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++		
++		
++		
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvalidStackFrameException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvalidStackFrameException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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.") {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvocationException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvocationException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/InvokeOptions.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/LocalVariable.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/LocalVariable.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
++
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Location.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Location.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,51 @@
++using System;
++
++namespace Mono.Debugger.Soft
++{
++	public class Location : Mirror
++	{
++		MethodMirror method;
++		//long native_addr;
++		int il_offset;
++		string source_file;
++		int line_number;
++		//int column_number;
++		
++		internal Location (VirtualMachine vm, MethodMirror method, long native_addr, int il_offset, string source_file, int line_number, int column_number) : 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.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;
++			}
++	    }
++
++		public override string ToString () {
++			return String.Format ("{0}+0x{1:x} at {2}:{3}", Method.FullName, ILOffset, SourceFile, LineNumber);
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,203 @@
++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
++{
++	public class MethodBodyMirror : Mirror
++	{
++		MethodMirror method;
++		byte[] il;
++
++		internal MethodBodyMirror (VirtualMachine vm, MethodMirror method, byte[] il) : base (vm, 0) {
++			this.method = method;
++			this.il = il;
++		}
++
++		public MethodMirror Method {
++			get {
++				return method;
++			}
++		}
++
++		public byte[] GetILAsByteArray () {
++			return il;
++		}
++
++		public List<ILInstruction> Instructions {
++			get {
++				return ReadCilBody (new BinaryReader (new MemoryStream (il)), 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 :
++					br.ReadByte ();
++					//instr.Operand = GetVariable (body, br.ReadByte ());
++					break;
++				case OperandType.ShortInlineParam :
++					br.ReadByte ();
++					//instr.Operand = GetParameter (body, br.ReadByte ());
++					break;
++				case OperandType.InlineSig :
++					br.ReadInt32 ();
++					//instr.Operand = GetCallSiteAt (br.ReadInt32 (), context);
++					break;
++				case OperandType.InlineI :
++					br.ReadInt32 ();
++					//instr.Operand = br.ReadInt32 ();
++					break;
++				case OperandType.InlineVar :
++					br.ReadInt16 ();
++					//instr.Operand = GetVariable (body, br.ReadInt16 ());
++					break;
++				case OperandType.InlineParam :
++					br.ReadInt16 ();
++					//instr.Operand = GetParameter (body, 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;
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodEntryEventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodExitEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodExitEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodExitEventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodExitEventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,290 @@
++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 MethodMirror : Mirror
++	{
++		string name;
++		MethodInfo info;
++		TypeMirror declaring_type;
++		DebugInfo debug_info;
++		C.MethodDefinition meta;
++		ParameterInfoMirror[] param_info;
++		ParameterInfoMirror ret_param;
++		LocalVariable[] locals;
++		IList<Location> locations;
++		MethodBodyMirror body;
++
++		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_name + ":" + Name + " ()");
++				else
++					sb.Append (type_namespace + "." + type_name + ":" + Name + " ()");
++				return sb.ToString ();
++			}
++	    }
++
++		void GetInfo () {
++			if (info == null)
++				info = vm.conn.Method_GetInfo (id);
++		}
++
++		public int MetadataToken {
++			get {
++				GetInfo ();
++				return info.token;
++			}
++		}
++
++		public MethodAttributes Attributes {
++			get {
++				GetInfo ();
++				return (MethodAttributes)info.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"));
++			}
++		}
++
++	    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) {
++				var li = vm.conn.Method_GetLocalsInfo (id);
++				// 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.il);
++			}
++			return body;
++		}
++
++		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.filename;
++			}
++	    }
++
++		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], SourceFile, line_numbers [i], 0);
++					locations = res;
++				}
++				return locations;
++			}
++		}				
++
++		internal int il_offset_to_line_number (int il_offset) {
++			if (debug_info == null)
++				debug_info = vm.conn.Method_GetDebugInfo (id);
++
++			// FIXME: Optimize this
++			for (int i = debug_info.il_offsets.Length - 1; i >= 0; --i) {
++				if (debug_info.il_offsets [i] <= il_offset)
++					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.LookupByToken (new MetadataToken (MetadataToken));
++				return meta;
++			}
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Mirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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 ();
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ModuleMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ModuleMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ObjectCollectedException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ObjectCollectedException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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.") {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,259 @@
++using System;
++using System.Collections.Generic;
++using System.Runtime.Remoting.Messaging;
++using System.Threading;
++
++namespace Mono.Debugger.Soft
++{
++	public class ObjectMirror : Value {
++	
++		internal ObjectMirror (VirtualMachine vm, long id) : base (vm, id) {
++		}
++	
++		public TypeMirror Type {
++			get {
++				return vm.GetType (vm.conn.Object_GetType (id));
++			}
++		}
++
++		public AppDomainMirror Domain {
++			get {
++				return vm.GetDomain (vm.conn.Object_GetDomain (id));
++			}
++		}
++
++		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);
++		}
++
++		/*
++		 * 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 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 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);
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ParameterInfoMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ParameterInfoMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/PrimitiveValue.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/PrimitiveValue.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,39 @@
++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 () {
++			return "PrimitiveValue<" + Value + ">";
++		}
++	}
++}
+\ No newline at end of file
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/PropertyInfoMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/PropertyInfoMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,117 @@
++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;
++
++		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 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) {
++			// 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 ();
++		}
++	}
++}
++
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StackFrame.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StackFrame.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,189 @@
++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;
++
++					if (il_offset == -1)
++						line_number = -1;
++					else
++						line_number = method.il_offset_to_line_number (il_offset);
++
++					location = new Location (vm, Method, 0, il_offset, method.SourceFile, line_number, 0);
++				}
++				return location;
++			}
++		}
++
++		public string FileName {
++			get {
++				return Location.SourceFile;
++			}
++	    }
++
++		public int ILOffset {
++			get {
++				return Location.ILOffset;
++			}
++		}
++
++		public int LineNumber {
++			get {
++				return Location.LineNumber;
++			}
++	    }
++
++		public bool IsDebuggerInvoke {
++			get {
++				return (flags & StackFrameFlags.DEBUGGER_INVOKE) != 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 ();
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StepEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,64 @@
++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
++	}
++
++	public sealed class StepEventRequest : EventRequest {
++
++		ThreadMirror step_thread;
++		StepDepth depth;
++		StepSize size;
++		
++		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 });
++			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;
++			}
++		}
++	}
++}
+\ No newline at end of file
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StringMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StringMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,17 @@
++using System;
++using System.Collections;
++
++namespace Mono.Debugger.Soft
++{
++	public class StringMirror : ObjectMirror {
++
++		internal StringMirror (VirtualMachine vm, long id) : base (vm, id) {
++		}
++
++		public string Value {
++			get {
++				return vm.conn.String_GetValue (id);
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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);
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/SuspendPolicy.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/SuspendPolicy.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadDeathEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadDeathEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,65 @@
++using System;
++using System.Threading;
++
++namespace Mono.Debugger.Soft
++{
++	public class ThreadMirror : ObjectMirror
++	{
++		string name;
++
++		internal ThreadMirror (VirtualMachine vm, long id) : base (vm, id) {
++		}
++
++		// FIXME: Cache, invalidate when the thread/runtime is resumed
++		public StackFrame[] GetFrames () {
++			FrameInfo[] frame_info = vm.conn.Thread_GetFrameInfo (id, 0, -1);
++
++			StackFrame[] frames = new StackFrame [frame_info.Length];
++			for (int i = 0; i < frame_info.Length; ++i) {
++				FrameInfo info = (FrameInfo)frame_info [i];
++				MethodMirror method = vm.GetMethod (info.method);
++				frames [i] = new StackFrame (vm, info.id, this, method, info.il_offset, info.flags);
++			}
++
++			return frames;
++	    }
++
++		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;
++			}
++		}
++
++		/*
++		 * Return a unique identifier for this thread, multiple ThreadMirror objects
++		 * may have the same ThreadId because of appdomains.
++		 */
++		public long ThreadId {
++			get {
++				return vm.conn.Thread_GetId (id);
++			}
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadStartEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/ThreadStartEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/TypeLoadEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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;
++			}
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,650 @@
++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;
++		TypeMirror[] nested;
++		CustomAttributeDataMirror[] cattrs;
++
++		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 {
++				// FIXME: base_type could be null for object/interfaces
++				if (base_type == null) {
++					base_type = vm.GetType (GetInfo ().base_type);
++				}
++				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 ();
++			}
++		}
++
++		public TypeMirror GetElementType () {
++			GetInfo ();
++			if (element_type == null && info.element_type != 0)
++				element_type = vm.GetType (info.element_type);
++			return element_type;
++		}
++
++		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 "Int32":
++						return "int";
++					case "Boolean":
++						return "bool";
++					default:
++						return FullName;
++					}
++				}
++				// FIXME: Only do this for real corlib types
++				if (Namespace == "System") {
++					string s = Name;
++					switch (s) {
++					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) {
++			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));
++			} 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.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);
++		}
++
++		public string[] GetSourceFiles (bool return_full_paths) {
++			return vm.conn.Type_GetSourceFiles (id, return_full_paths);
++		}
++
++		public C.TypeDefinition Metadata {
++			get {
++				if (meta == null) {
++					if (Assembly.Metadata == null || MetadataToken == 0)
++						return null;
++					meta = (C.TypeDefinition)Assembly.Metadata.MainModule.LookupByToken (new MetadataToken (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 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) {
++			// FIXME: Handle inherit
++			if (cattrs == null) {
++				CattrInfo[] info = vm.conn.Type_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 ();
++		}
++
++		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);
++		}			
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectedException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMDisconnectedException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,10 @@
++using System;
++
++namespace Mono.Debugger.Soft
++{
++	public class VMDisconnectedException : Exception {
++		
++		public VMDisconnectedException () : base () {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMMismatchException.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMMismatchException.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,10 @@
++using System;
++
++namespace Mono.Debugger.Soft
++{
++	public class VMMismatchException : Exception
++	{
++		public VMMismatchException () : base () {
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMStartEvent.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VMStartEvent.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++    }
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Value.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Value.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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) {
++		}
++	}
++}
++
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,599 @@
++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 {
++				return conn.EndPoint;
++			}
++		}
++
++		public VersionInfo Version {
++			get {
++				return version;
++			}
++		}
++
++		EventSet current_es;
++		int current_es_index;
++
++		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 ();
++			}
++		}
++
++		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 InvalidOperationException ("The vm is not suspended.");
++				else
++					throw;
++			}
++	    }
++
++		public void Exit (int exitCode) {
++			conn.VM_Exit (exitCode);
++		}
++
++		public void Dispose () {
++			conn.VM_Dispose ();
++			conn.Close ();
++			notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null);
++		}
++
++		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);
++		}
++
++		//
++		// 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 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 ();
++		}
++
++		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 InvalidOperationException ("The vm is not suspended.");
++			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 ();
++			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;
++			}
++	    }
++
++		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)
++						domain_id = conn.Object_GetDomain (id);
++					AppDomainMirror d = GetDomain (domain_id);
++
++					if (type_id == 0)
++						type_id = conn.Object_GetType (id);
++					TypeMirror t = GetType (type_id);
++
++					if (t.Assembly == d.Corlib && t.Namespace == "System.Threading" && t.Name == "Thread")
++						obj = new ThreadMirror (this, id);
++					else if (t.Assembly == d.Corlib && t.Namespace == "System" && t.Name == "String")
++						obj = new StringMirror (this, id);
++					else if (typeof (T) == typeof (ArrayMirror))
++						obj = new ArrayMirror (this, id);
++					else
++						obj = new ObjectMirror (this, id);
++					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;
++		}
++    }
++
++	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;
++				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);
++        }
++    }
++
++	internal class CommandException : Exception {
++
++		public CommandException (ErrorCode error_code) : base ("Debuggee returned error code " + error_code + ".") {
++			ErrorCode = error_code;
++		}
++
++		public ErrorCode ErrorCode {
++			get; set;
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -0,0 +1,308 @@
++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 Connection (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, LaunchOptions options = null) {
++			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 async = (AsyncResult) asyncResult;
++			LaunchCallback cb = (LaunchCallback) async.AsyncDelegate;
++			return cb.EndInvoke (asyncResult);
++		}
++
++		public static VirtualMachine Launch (ProcessStartInfo info, LaunchOptions options = null) {
++			return EndLaunch (BeginLaunch (info, null, options));
++		}
++
++		public static VirtualMachine Launch (string[] args, LaunchOptions options = null) {
++			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) {
++				con_sock.Disconnect (false);
++				con_sock.Close ();
++			}
++
++			if (dbg_sock.Connected)
++				dbg_sock.Disconnect (false);
++			dbg_sock.Close ();
++
++			Connection conn = new Connection (dbg_acc);
++
++			VirtualMachine vm = new VirtualMachine (null, conn);
++
++			if (con_acc != null) {
++				vm.StandardOutput = new StreamReader (new NetworkStream (con_acc));
++				vm.StandardError = null;
++			}
++
++			conn.EventHandler = new EventHandler (vm);
++
++			vm.connect ();
++
++			return vm;
++		}
++
++		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) {
++			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);
++
++			if (con_ep != null) {
++				con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
++				con_sock.Bind (con_ep);
++				con_sock.Listen (1000);
++			}
++			
++			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 async = (AsyncResult) asyncResult;
++			ListenCallback cb = (ListenCallback) async.AsyncDelegate;
++			return cb.EndInvoke (asyncResult);
++		}
++
++		public static VirtualMachine Listen (IPEndPoint dbg_ep, IPEndPoint con_ep = null) { 
++			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 conn = new Connection (dbg_sock);
++
++			VirtualMachine vm = new VirtualMachine (null, conn);
++
++			if (con_sock != null) {
++				vm.StandardOutput = new StreamReader (new NetworkStream (con_sock));
++				vm.StandardError = null;
++			}
++
++			conn.EventHandler = new EventHandler (vm);
++
++			vm.connect ();
++
++			return vm;
++		}
++
++		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 async = (AsyncResult) asyncResult;
++			ConnectCallback cb = (ConnectCallback) async.AsyncDelegate;
++			return cb.EndInvoke (asyncResult);
++		}
++
++		public static void CancelConnection (IAsyncResult asyncResult)
++		{
++			((Socket)asyncResult.AsyncState).Close ();
++		}
++	}
++}
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Makefile.am
+===================================================================
+--- monodevelop.git.orig/src/addins/MonoDevelop.Debugger.Soft/Makefile.am	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Makefile.am	2010-12-18 11:49:17.000000000 +0000
+@@ -1,4 +1,5 @@
+ SUBDIRS = \
++	Mono.Debugger.Soft \
+ 	Mono.Debugging.Soft \
+ 	MonoDevelop.Debugger.Soft \
+ 	MonoDevelop.Debugger.Soft.AspNet \
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Makefile.am
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Makefile.am	2010-12-18 11:49:32.000000000 +0000
+@@ -0,0 +1,107 @@
++ADDIN_BUILD = $(top_builddir)/build/AddIns/MonoDevelop.Debugger.Soft
++ASSEMBLY = $(ADDIN_BUILD)/Mono.Debugger.Soft.dll
++
++SIGNING_KEY=$(top_srcdir)/src/core/Mono.Debugging/mono.debugging.snk
++
++CECIL_ASM_SRC = /usr/lib/mono-cecil/Mono.Cecil.dll
++CECIL_ASM = $(ADDIN_BUILD)/Mono.Cecil.dll
++
++REFS =  \
++	-r:System \
++	-r:System.Core \
++	-r:/usr/lib/mono-cecil/Mono.Cecil.dll
++
++FILES =  \
++	AbsentInformationException.cs \
++	AppDomainCreateEvent.cs \
++	AppDomainMirror.cs \
++	AppDomainUnloadEvent.cs \
++	ArrayMirror.cs \
++	AssemblyLoadEvent.cs \
++	AssemblyMirror.cs \
++	AssemblyUnloadEvent.cs \
++	BreakpointEvent.cs \
++	BreakpointEventRequest.cs \
++	Connection.cs \
++	CustomAttributeDataMirror.cs \
++	CustomAttributeNamedArgumentMirror.cs \
++	CustomAttributeTypedArgumentMirror.cs \
++	DataConverter.cs \
++	EnumMirror.cs \
++	Event.cs \
++	EventQueueImpl.cs \
++	EventRequest.cs \
++	EventType.cs \
++	EventSet.cs \
++	ExceptionEvent.cs \
++	ExceptionEventRequest.cs \
++	FieldInfoMirror.cs \
++	IInvokeAsyncResult.cs \
++	ILInstruction.cs \
++	IMirror.cs \
++	InvalidStackFrameException.cs \
++	InvocationException.cs \
++	InvokeOptions.cs \
++	ITargetProcess.cs \
++	LocalVariable.cs \
++	Location.cs \
++	MethodBodyMirror.cs \
++	MethodEntryEvent.cs \
++	MethodEntryEventRequest.cs \
++	MethodExitEvent.cs \
++	MethodExitEventRequest.cs \
++	MethodMirror.cs \
++	Mirror.cs \
++	ModuleMirror.cs \
++	ObjectCollectedException.cs \
++	ObjectMirror.cs \
++	ParameterInfoMirror.cs \
++	PrimitiveValue.cs \
++	PropertyInfoMirror.cs \
++	StackFrame.cs \
++	StepEvent.cs \
++	StepEventRequest.cs \
++	StringMirror.cs \
++	StructMirror.cs \
++	SuspendPolicy.cs \
++	ThreadDeathEvent.cs \
++	ThreadMirror.cs \
++	ThreadStartEvent.cs \
++	TypeLoadEvent.cs \
++	TypeMirror.cs \
++	Value.cs \
++	VirtualMachine.cs \
++	VirtualMachineManager.cs \
++	VMDeathEvent.cs \
++	VMDisconnectedException.cs \
++	VMDisconnectEvent.cs \
++	VMMismatchException.cs \
++	VMStartEvent.cs
++
++RES =
++
++CSC_FLAGS = -unsafe -D:MONO_DATACONVERTER_STATIC_METHODS
++
++all: $(ASSEMBLY) $(ASSEMBLY).mdb $(DATA_FILE_BUILD) $(SIGNING_KEY)
++
++$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) $(CECIL_ASM)
++	mkdir -p $(ADDIN_BUILD)
++	$(CSC) $(CSC_FLAGS) -debug -out:$@ -keyfile:$(SIGNING_KEY) -target:library $(REFS) $(build_deps) \
++		$(build_resources:%=/resource:%) $(build_sources)
++
++$(ASSEMBLY).mdb: $(ASSEMBLY)
++
++$(CECIL_ASM): $(CECIL_ASM_SRC)
++	mkdir -p $(ADDIN_BUILD)
++	cp $^ $@
++
++check: all
++
++assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.Debugger.Soft
++assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb $(CECIL_ASM)
++
++CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb
++EXTRA_DIST = $(FILES) $(RES)
++
++include $(top_srcdir)/Makefile.include
++
+Index: monodevelop.git/configure.in
+===================================================================
+--- monodevelop.git.orig/configure.in	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/configure.in	2010-12-18 11:49:17.000000000 +0000
+@@ -373,6 +373,7 @@
+ src/addins/MonoDevelop.Refactoring/Makefile
+ src/addins/MonoDevelop.Debugger/Makefile
+ src/addins/MonoDevelop.Debugger.Soft/Makefile
++src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/Makefile
+ src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Makefile
+ src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/Makefile
+ src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.AspNet/Makefile
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Makefile.am
+===================================================================
+--- monodevelop.git.orig/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Makefile.am	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Makefile.am	2010-12-18 11:49:17.000000000 +0000
+@@ -2,16 +2,13 @@
+ ASSEMBLY = $(ADDIN_BUILD)/Mono.Debugging.Soft.dll
+ 
+ DBG_ASM = $(ADDIN_BUILD)/Mono.Debugger.Soft.dll
+-DBG_ASM_SRC = $(top_srcdir)/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Mono.Debugger.Soft.dll
+-DBG_MDB = $(DBG_ASM).mdb
+-DBG_MDB_SRC = $(DBG_ASM_SRC).mdb
+ 
+ SIGNING_KEY=$(top_srcdir)/src/core/Mono.Debugging/mono.debugging.snk
+ 
+ DEPS = $(top_builddir)/build/bin/Mono.Debugging.dll
+ 
+ REFS =  \
+-	-r:$(top_srcdir)/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Mono.Debugger.Soft.dll \
++	-r:$(DBG_ASM) \
+ 	-r:System \
+ 	-r:System.Core
+ 
+@@ -32,28 +29,20 @@
+ 
+ all: $(ASSEMBLY) $(ASSEMBLY).mdb $(DATA_FILE_BUILD) $(SIGNING_KEY)
+ 
+-$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) $(DBG_ASM) $(DBG_MDB)
++$(ASSEMBLY): $(build_sources) $(build_resources) $(DEPS) $(DBG_ASM)
+ 	mkdir -p $(ADDIN_BUILD)
+ 	$(CSC) $(CSC_FLAGS) -debug -out:$@ -keyfile:$(SIGNING_KEY) -target:library $(REFS) $(build_deps) \
+ 		$(build_resources:%=/resource:%) $(build_sources)
+ 
+-$(DBG_ASM): $(DBG_ASM_SRC)
+-	mkdir -p $(ADDIN_BUILD)
+-	cp $^ $@ 
+-
+-$(DBG_MDB): $(DBG_MDB_SRC)
+-	mkdir -p $(ADDIN_BUILD)
+-	cp $^ $@
+-
+ $(ASSEMBLY).mdb: $(ASSEMBLY)
+ 
+ check: all
+ 
+ assemblydir = $(MD_ADDIN_DIR)/MonoDevelop.Debugger.Soft
+-assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb $(DBG_ASM) $(DBG_MDB)
++assembly_DATA = $(ASSEMBLY) $(ASSEMBLY).mdb
+ 
+-CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb $(DBG_ASM) $(DBG_MDB)
+-EXTRA_DIST = $(FILES) $(RES) $(DBG_ASM_SRC) $(DBG_MDB_SRC)
++CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb
++EXTRA_DIST = $(FILES) $(RES)
+ 
+ include $(top_srcdir)/Makefile.include
+ 
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/Makefile.am
+===================================================================
+--- monodevelop.git.orig/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/Makefile.am	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft/Makefile.am	2010-12-18 11:49:17.000000000 +0000
+@@ -13,7 +13,7 @@
+ REFS =  \
+ 	$(GLIB_SHARP_LIBS) \
+ 	$(GTK_SHARP_LIBS) \
+-	-r:$(top_srcdir)/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Mono.Debugger.Soft.dll \
++	-r:$(top_builddir)/build/AddIns/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft.dll \
+ 	-r:System \
+ 	-r:System.Core
+ 
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.AspNet/Makefile.am
+===================================================================
+--- monodevelop.git.orig/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.AspNet/Makefile.am	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.AspNet/Makefile.am	2010-12-18 11:49:17.000000000 +0000
+@@ -14,7 +14,7 @@
+ REFS =  \
+ 	$(GLIB_SHARP_LIBS) \
+ 	$(GTK_SHARP_LIBS) \
+-	-r:$(top_srcdir)/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Mono.Debugger.Soft.dll \
++	-r:$(top_builddir)/build/AddIns/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft.dll \
+ 	-r:System \
+ 	-r:System.Core
+ 
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.Moonlight/Makefile.am
+===================================================================
+--- monodevelop.git.orig/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.Moonlight/Makefile.am	2010-12-18 11:46:35.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/MonoDevelop.Debugger.Soft.Moonlight/Makefile.am	2010-12-18 11:49:17.000000000 +0000
+@@ -14,7 +14,7 @@
+ REFS =  \
+ 	$(GLIB_SHARP_LIBS) \
+ 	$(GTK_SHARP_LIBS) \
+-	-r:$(top_srcdir)/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugging.Soft/Mono.Debugger.Soft.dll \
++	-r:$(top_builddir)/build/AddIns/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft.dll \
+ 	-r:System \
+ 	-r:System.Core
+ 
+Index: monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ monodevelop.git/src/addins/MonoDevelop.Debugger.Soft/Mono.Debugger.Soft/EventSet.cs	2010-12-18 11:49:17.000000000 +0000
+@@ -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/debian/patches/series b/debian/patches/series
index 69b7563..1d06c28 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,6 +1,7 @@
 #stetic_widget_corruption_r144546.patch -p3
+inject_Mono.Debugger.Soft_source.patch
 avoid-dependency-on-Mono.Addins-0.5.patch
-use_system_Mono.Debugger.Soft.patch
+#use_system_Mono.Debugger.Soft.patch
 #use_keyfile_not_keycontainer.patch
 link_system_nunit.patch
 use_libsvn1.patch

-- 
monodevelop



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