-Mono.Debugger/CustomAttributeTypedArgumentMirror.cs
-Mono.Debugger/ExceptionEvent.cs
-Mono.Debugger/ModuleMirror.cs
-Mono.Debugger/AppDomainMirror.cs
-Mono.Debugger/AssemblyLoadEvent.cs
-Mono.Debugger/VMStartEvent.cs
-Mono.Debugger/StackFrame.cs
-Mono.Debugger/CustomAttributeDataMirror.cs
-Mono.Debugger/ThreadStartEvent.cs
-Mono.Debugger/ILInstruction.cs
-Mono.Debugger/PrimitiveValue.cs
-Mono.Debugger/VMDisconnectedException.cs
-Mono.Debugger/Mirror.cs
-Mono.Debugger/EnumMirror.cs
-Mono.Debugger/FieldInfoMirror.cs
-Mono.Debugger/TypeMirror.cs
-Mono.Debugger/CustomAttributeNamedArgumentMirror.cs
-Mono.Debugger/DataConverter.cs
-Mono.Debugger/AssemblyMirror.cs
-Mono.Debugger/VirtualMachine.cs
-Mono.Debugger/VMMismatchException.cs
-Mono.Debugger/AppDomainUnloadEvent.cs
-Mono.Debugger/ExceptionEventRequest.cs
-Mono.Debugger/EventType.cs
-Mono.Debugger/StructMirror.cs
-Mono.Debugger/InvocationException.cs
-Mono.Debugger/IMirror.cs
-Mono.Debugger/VMDeathEvent.cs
-Mono.Debugger/MethodBodyMirror.cs
-Mono.Debugger/MethodEntryEvent.cs
-Mono.Debugger/MethodMirror.cs
-Mono.Debugger/BreakpointEventRequest.cs
-Mono.Debugger/MethodEntryEventRequest.cs
-Mono.Debugger/LocalVariable.cs
-Mono.Debugger/ParameterInfoMirror.cs
-Mono.Debugger/Event.cs
-Mono.Debugger/AppDomainCreateEvent.cs
-Mono.Debugger/ThreadDeathEvent.cs
-Mono.Debugger/SuspendPolicy.cs
-Mono.Debugger/VirtualMachineManager.cs
-Mono.Debugger/MethodExitEvent.cs
-Mono.Debugger/MethodExitEventRequest.cs
-Mono.Debugger/EventQueueImpl.cs
-Mono.Debugger/ObjectMirror.cs
-Mono.Debugger/Value.cs
-Mono.Debugger/StepEvent.cs
-Mono.Debugger/Location.cs
-Mono.Debugger/ObjectCollectedException.cs
-Mono.Debugger/EventRequest.cs
-Mono.Debugger/InvalidStackFrameException.cs
-Mono.Debugger/BreakpointEvent.cs
-Mono.Debugger/StringMirror.cs
-Mono.Debugger/PropertyInfoMirror.cs
-Mono.Debugger/ArrayMirror.cs
-Mono.Debugger/StepEventRequest.cs
-Mono.Debugger/Connection.cs
-Mono.Debugger/ThreadMirror.cs
-Mono.Debugger/TypeLoadEvent.cs
-Mono.Debugger/VMDisconnectEvent.cs
-Mono.Debugger/InvokeOptions.cs
+Mono.Debugger.Soft/CustomAttributeTypedArgumentMirror.cs
+Mono.Debugger.Soft/ExceptionEvent.cs
+Mono.Debugger.Soft/ModuleMirror.cs
+Mono.Debugger.Soft/AppDomainMirror.cs
+Mono.Debugger.Soft/AssemblyLoadEvent.cs
+Mono.Debugger.Soft/VMStartEvent.cs
+Mono.Debugger.Soft/StackFrame.cs
+Mono.Debugger.Soft/CustomAttributeDataMirror.cs
+Mono.Debugger.Soft/ThreadStartEvent.cs
+Mono.Debugger.Soft/ILInstruction.cs
+Mono.Debugger.Soft/PrimitiveValue.cs
+Mono.Debugger.Soft/VMDisconnectedException.cs
+Mono.Debugger.Soft/Mirror.cs
+Mono.Debugger.Soft/EnumMirror.cs
+Mono.Debugger.Soft/FieldInfoMirror.cs
+Mono.Debugger.Soft/TypeMirror.cs
+Mono.Debugger.Soft/CustomAttributeNamedArgumentMirror.cs
+Mono.Debugger.Soft/DataConverter.cs
+Mono.Debugger.Soft/AssemblyMirror.cs
+Mono.Debugger.Soft/VirtualMachine.cs
+Mono.Debugger.Soft/VMMismatchException.cs
+Mono.Debugger.Soft/AppDomainUnloadEvent.cs
+Mono.Debugger.Soft/ExceptionEventRequest.cs
+Mono.Debugger.Soft/EventType.cs
+Mono.Debugger.Soft/StructMirror.cs
+Mono.Debugger.Soft/InvocationException.cs
+Mono.Debugger.Soft/IMirror.cs
+Mono.Debugger.Soft/VMDeathEvent.cs
+Mono.Debugger.Soft/MethodBodyMirror.cs
+Mono.Debugger.Soft/MethodEntryEvent.cs
+Mono.Debugger.Soft/MethodMirror.cs
+Mono.Debugger.Soft/BreakpointEventRequest.cs
+Mono.Debugger.Soft/MethodEntryEventRequest.cs
+Mono.Debugger.Soft/LocalVariable.cs
+Mono.Debugger.Soft/ParameterInfoMirror.cs
+Mono.Debugger.Soft/Event.cs
+Mono.Debugger.Soft/AppDomainCreateEvent.cs
+Mono.Debugger.Soft/ThreadDeathEvent.cs
+Mono.Debugger.Soft/SuspendPolicy.cs
+Mono.Debugger.Soft/VirtualMachineManager.cs
+Mono.Debugger.Soft/MethodExitEvent.cs
+Mono.Debugger.Soft/MethodExitEventRequest.cs
+Mono.Debugger.Soft/EventQueueImpl.cs
+Mono.Debugger.Soft/ObjectMirror.cs
+Mono.Debugger.Soft/Value.cs
+Mono.Debugger.Soft/StepEvent.cs
+Mono.Debugger.Soft/Location.cs
+Mono.Debugger.Soft/ObjectCollectedException.cs
+Mono.Debugger.Soft/EventRequest.cs
+Mono.Debugger.Soft/InvalidStackFrameException.cs
+Mono.Debugger.Soft/BreakpointEvent.cs
+Mono.Debugger.Soft/StringMirror.cs
+Mono.Debugger.Soft/PropertyInfoMirror.cs
+Mono.Debugger.Soft/ArrayMirror.cs
+Mono.Debugger.Soft/StepEventRequest.cs
+Mono.Debugger.Soft/Connection.cs
+Mono.Debugger.Soft/ThreadMirror.cs
+Mono.Debugger.Soft/TypeLoadEvent.cs
+Mono.Debugger.Soft/VMDisconnectEvent.cs
+Mono.Debugger.Soft/InvokeOptions.cs
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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));
+ }
+
+
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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 ();
+ }
+ }
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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));
+ }
+
+ /*
+ * 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;
+ }
+ }
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+2009-12-05 Lluis Sanchez <lluis@novell.com>
+
+ * StructMirror.cs: Fix field indexer for structs with static fields.
+ * VirtualMachineManager.cs: Added an option to LaunchOptions which
+ allows providing a custom method for launching the process. This
+ allows launching mono in a wrapper process.
+
+2009-12-03 Zoltan Varga <vargaz@gmail.com>
+
+ * StructMirror.cs (this): Ignore static fields.
+
+2009-12-02 Geoff Norton <gnorton@novell.com>
+
+ * VirtualMachineManager.cs: We might get a SocketException (interrupted)
+ here, so lets just handle all Exceptions to our Accept pattern the same
+ way
+
+2009-12-01 Zoltan Varga <vargaz@gmail.com>
+
+ * VirtualMachine.cs (ErrorHandler): Handle NOT_SUSPENDED error code too.
+
+2009-11-24 Zoltan Varga <vargaz@gmail.com>
+
+ * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Make the BeginInvokeMethod
+ which takes a 'vm' argument obsolete, it was added by mistake, add a version
+ without that argument instead.
+
+2009-11-19 Zoltan Varga <vargaz@gmail.com>
+
+ * AssemblyMirror.cs: Add a GetName () method.
+
+2009-11-17 Zoltan Varga <vargaz@gmail.com>
+
+ * Connection.cs ObjectMirror.cs: Implement invokes in a real asynchronous way,
+ without waiting.
+
+2009-11-14 Zoltan Varga <vargaz@gmail.com>
+
+ * InvokeOptions.cs: Add SingleThreaded option, not yet works.
+
+ * VirtualMachineManager.cs (Launch): Pass options to BeginLaunch.
+
+ * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Implement an async version of
+ InvokeMethod ().
+
+2009-11-13 Zoltan Varga <vargaz@gmail.com>
+
+ * InvokeOptions.cs: New file.
+
+ * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Add support for passing flags
+ to InvokeMethod ().
+
+ * Connection.cs: Bump protocol version.
+
+2009-11-12 Zoltan Varga <vargaz@gmail.com>
+
+ * VirtualMachineManager.cs: Put back the old Launch (string[], LaunchOptions)
+ overload.
+
+2009-11-11 Geoff Norton <gnorton@novell.com>
+
+ * VirtualMachineManager.cs: Refactor the APIs to have async methods.
+ Remove a bunch of Listen overloads that are pointless. Refactor
+ Launch to take a ProcessStartInfo instead of string arguments.
+
+2009-11-10 Zoltan Varga <vargaz@gmail.com>
+
+ * VirtualMachineManager.cs (Launch): Close the listening socket instead of
+ shutting it down since Shutdown throws on exception on non-connected sockets
+ in ms.net.
+
+2009-11-05 Zoltan Varga <vargaz@gmail.com>
+
+ * VirtualMachineManager.cs (Listen): Resurrect the old listen method.
+
+ * VirtualMachineManager.cs (Connect): New method to connect to a runtime
+ listening at the provided address.
+
+2009-11-04 Lluis Sanchez <lluis@novell.com>
+
+ * VirtualMachineManager.cs: Properly redirect standard output.
+
+2009-11-03 Zoltan Varga <vargaz@gmail.com>
+
+ * EventRequest.cs (AssemblyFilter): New property to filter
+ events based on a list of assemblies.
+
+ * Connection.cs: Add assembly filters to the protocol implementation.
--- /dev/null
+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
+{
+ 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;
+ 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;
+ }
+ }
+
+ class AssemblyModifier : Modifier {
+ public long[] Assemblies {
+ get; set;
+ }
+ }
+
+ public enum ErrorCode {
+ NONE = 0,
+ INVALID_OBJECT = 20,
+ INVALID_FIELDID = 25,
+ INVALID_FRAMEID = 30,
+ NOT_IMPLEMENTED = 100,
+ NOT_SUSPENDED = 101,
+ INVALID_ARGUMENT = 102
+ }
+
+ 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,
+ * and the debuggee's minor version is <= the library's minor version.
+ */
+ public const int MAJOR_VERSION = 2;
+ public const int MINOR_VERSION = 0;
+
+ 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
+ }
+
+ enum CmdEvent {
+ COMPOSITE = 100
+ }
+
+ enum CmdThread {
+ GET_FRAME_INFO = 1,
+ GET_NAME = 2,
+ GET_STATE = 3,
+ GET_INFO = 4
+ }
+
+ 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
+ }
+
+ 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
+ }
+
+ 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 ();
+ }
+
+ 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) {
+ r.ReadByte (); // suspend_policy
+ int nevents = r.ReadInt ();
+
+ for (int i = 0; i < nevents; ++i) {
+ EventKind kind = (EventKind)r.ReadByte ();
+ int req_id = r.ReadInt ();
+
+ if (kind == EventKind.VM_START) {
+ long thread_id = r.ReadId ();
+ EventHandler.VMStart (req_id, thread_id, null);
+ } else if (kind == EventKind.VM_DEATH) {
+ EventHandler.VMDeath (req_id, 0, null);
+ } else if (kind == EventKind.THREAD_START) {
+ long thread_id = r.ReadId ();
+ EventHandler.ThreadStart (req_id, thread_id, thread_id);
+ } else if (kind == EventKind.THREAD_DEATH) {
+ long thread_id = r.ReadId ();
+ EventHandler.ThreadDeath (req_id, thread_id, thread_id);
+ } else if (kind == EventKind.ASSEMBLY_LOAD) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ EventHandler.AssemblyLoad (req_id, thread_id, id);
+ } else if (kind == EventKind.TYPE_LOAD) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ EventHandler.TypeLoad (req_id, thread_id, id);
+ } else if (kind == EventKind.METHOD_ENTRY) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ EventHandler.MethodEntry (req_id, thread_id, id);
+ } else if (kind == EventKind.METHOD_EXIT) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ 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 ();
+ 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 ();
+ 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
+ EventHandler.Exception (req_id, thread_id, id, loc);
+ } else if (kind == EventKind.APPDOMAIN_CREATE) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ EventHandler.AppDomainCreate (req_id, thread_id, id);
+ } else if (kind == EventKind.APPDOMAIN_UNLOAD) {
+ long thread_id = r.ReadId ();
+ long id = r.ReadId ();
+ EventHandler.AppDomainUnload (req_id, thread_id, id);
+ } else {
+ throw new NotImplementedException ("Unknown event kind: " + kind);
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public IEventHandler EventHandler {
+ get; set;
+ }
+
+ /* Send a request and call cb when a result is received */
+ void 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));
+ }
+
+ 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 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 void VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
+ 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);
+ }
+ });
+ }
+
+ /*
+ * 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 ();
+ }
+
+ /*
+ * 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;
+ }
+
+ /*
+ * 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;
+
+ 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) {
+ var r = SendReceive (CommandSet.TYPE, (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) {
+ w.WriteByte ((byte)ModifierKind.EXCEPTION_ONLY);
+ w.WriteId ((mod as ExceptionModifier).Type);
+ } 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 VMStart (int req_id, long thread_id, string vm_uri);
+
+ void VMDeath (int req_id, long thread_id, string vm_uri);
+
+ void VMDisconnect (int req_id, long thread_id, string vm_uri);
+
+ void ThreadStart (int req_id, long thread_id, long id);
+
+ void ThreadDeath (int req_id, long thread_id, long id);
+
+ void AssemblyLoad (int req_id, long thread_id, long id);
+
+ void TypeLoad (int req_id, long thread_id, long id);
+
+ void MethodEntry (int req_id, long thread_id, long id);
+
+ void MethodExit (int req_id, long thread_id, long id);
+
+ void Breakpoint (int req_id, long thread_id, long method_id, long loc);
+
+ void Step (int req_id, long thread_id, long method_id, long loc);
+
+ void Exception (int req_id, long thread_id, long exc_id, long loc);
+
+ void AppDomainCreate (int req_id, long thread_id, long id);
+
+ void AppDomainUnload (int req_id, long thread_id, long id);
+ }
+}
--- /dev/null
+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;
+ }
+ }
+
+}
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+}
--- /dev/null
+//
+// Authors:
+// Miguel de Icaza (miguel@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
+
+ }
+}
--- /dev/null
+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) {
+ }
+
+ 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
--- /dev/null
+
+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);
+ }
+ }
+ }
+}
--- /dev/null
+#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
--- /dev/null
+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
--- /dev/null
+
+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
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Mono.Debugger.Soft
+{
+ public sealed class ExceptionEventRequest : EventRequest {
+
+ TypeMirror exc_type;
+
+ internal ExceptionEventRequest (VirtualMachine vm, TypeMirror exc_type) : 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;
+ }
+
+ 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 });
+ SendReq (mods);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+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 ();
+ }
+ }
+}
+
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+}
--- /dev/null
+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.") {
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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
+ }
+}
--- /dev/null
+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;
+ }
+ }
+ }
+}
+
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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 ();
+ }
+ }
+}
--- /dev/null
+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
+ }
+}
--- /dev/null
+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.") {
+ }
+ }
+}
--- /dev/null
+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 : IAsyncResult {
+
+ 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 ValueImpl Value {
+ get; set;
+ }
+
+ public ValueImpl Exception {
+ get; set;
+ }
+ }
+
+ internal static IAsyncResult 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, Callback = callback };
+
+ 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));
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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 ();
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+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);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+
+namespace Mono.Debugger.Soft
+{
+ // Keep it in sync with debugger-agent.h
+ public enum SuspendPolicy {
+ None = 0,
+ EventThread = 1,
+ All = 2
+ }
+}
--- /dev/null
+
+namespace Mono.Debugger.Soft
+{
+ public class ThreadDeathEvent : Event {
+ internal ThreadDeathEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadDeath, vm, req_id, id) {
+ }
+ }
+}
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+
+namespace Mono.Debugger.Soft
+{
+ public class ThreadStartEvent : Event {
+ internal ThreadStartEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadStart, vm, req_id, id) {
+ }
+ }
+}
--- /dev/null
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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 {
+ // FIXME:
+ return false;
+ //return IsSubclassOf (typeof (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 vm.conn.Type_GetSourceFiles (id);
+ }
+
+ 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;
+ }
+
+ /*
+ * 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);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace Mono.Debugger.Soft
+{
+ public class VMDeathEvent : Event
+ {
+ public VMDeathEvent (VirtualMachine vm, int req_id) : base (EventType.VMDeath, vm, req_id, -1) {
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace Mono.Debugger.Soft
+{
+ public class VMDisconnectEvent : Event
+ {
+ public VMDisconnectEvent (VirtualMachine vm, int req_id) : base (EventType.VMDisconnect, vm, req_id, -1) {
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace Mono.Debugger.Soft
+{
+ public class VMDisconnectedException : Exception {
+
+ public VMDisconnectedException () : base () {
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace Mono.Debugger.Soft
+{
+ public class VMMismatchException : Exception
+ {
+ public VMMismatchException () : base () {
+ }
+ }
+}
--- /dev/null
+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) {
+ }
+ }
+}
--- /dev/null
+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) {
+ }
+ }
+}
+
--- /dev/null
+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;
+ Process process;
+
+ internal Connection conn;
+
+ internal VirtualMachine (Process 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 {
+ return process;
+ }
+ }
+
+ public AppDomainMirror RootDomain {
+ get {
+ return root_domain;
+ }
+ }
+
+ public EndPoint EndPoint {
+ get {
+ return conn.EndPoint;
+ }
+ }
+
+ public Event GetNextEvent () {
+ lock (queue_monitor) {
+ if (queue.Count == 0)
+ Monitor.Wait (queue_monitor);
+ return (Event)queue.Dequeue ();
+ }
+ }
+
+ public Event GetNextEvent (int timeout) {
+ throw new NotImplementedException ();
+ }
+
+ 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, 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);
+ }
+
+ //
+ // 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);
+ }
+
+ public void EnableEvents (params EventType[] events) {
+ foreach (EventType etype in 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 (Event e) {
+ lock (queue_monitor) {
+ queue.Enqueue (e);
+ 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.");
+ 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
+ VersionInfo ver = conn.Version;
+ if ((ver.MajorVersion != Connection.MAJOR_VERSION) ||
+ (ver.MinorVersion > Connection.MINOR_VERSION))
+ throw new NotSupportedException (String.Format ("The debuggee implements protocol version {0}.{1}, while {2}.{3} is required.", ver.MajorVersion, ver.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, 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 (new VMStartEvent (vm, req_id, thread_id));
+ break;
+ case EventType.VMDeath:
+ queue_event (new VMDeathEvent (vm, req_id));
+ break;
+ case EventType.VMDisconnect:
+ queue_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 VMStart (int req_id, long thread_id, string vm_uri) {
+ vm.notify_vm_event (EventType.VMStart, req_id, thread_id, vm_uri);
+ }
+
+ public void VMDeath (int req_id, long thread_id, string vm_uri) {
+ vm.notify_vm_event (EventType.VMDeath, req_id, thread_id, vm_uri);
+ }
+
+ public void VMDisconnect (int req_id, long thread_id, string vm_uri) {
+ vm.notify_vm_event (EventType.VMDisconnect, req_id, thread_id, vm_uri);
+ }
+
+ public void ThreadStart (int req_id, long thread_id, long id) {
+ vm.queue_event (new ThreadStartEvent (vm, req_id, id));
+ }
+
+ public void ThreadDeath (int req_id, long thread_id, long id) {
+ vm.queue_event (new ThreadDeathEvent (vm, req_id, id));
+ }
+
+ public void AssemblyLoad (int req_id, long thread_id, long id) {
+ vm.queue_event (new AssemblyLoadEvent (vm, req_id, thread_id, id));
+ }
+
+ public void TypeLoad (int req_id, long thread_id, long id) {
+ vm.queue_event (new TypeLoadEvent (vm, req_id, thread_id, id));
+ }
+
+ public void MethodEntry (int req_id, long thread_id, long id) {
+ vm.queue_event (new MethodEntryEvent (vm, req_id, thread_id, id));
+ }
+
+ public void MethodExit (int req_id, long thread_id, long id) {
+ vm.queue_event (new MethodExitEvent (vm, req_id, thread_id, id));
+ }
+
+ public void Breakpoint (int req_id, long thread_id, long id, long loc) {
+ vm.queue_event (new BreakpointEvent (vm, req_id, thread_id, id, loc));
+ }
+
+ public void Step (int req_id, long thread_id, long id, long loc) {
+ vm.queue_event (new StepEvent (vm, req_id, thread_id, id, loc));
+ }
+
+ public void Exception (int req_id, long thread_id, long id, long loc) {
+ vm.queue_event (new ExceptionEvent (vm, req_id, thread_id, id, loc));
+ }
+
+ public void AppDomainCreate (int req_id, long thread_id, long id) {
+ vm.queue_event (new AppDomainCreateEvent (vm, req_id, thread_id, id));
+ }
+
+ public void AppDomainUnload (int req_id, long thread_id, long id) {
+ vm.queue_event (new AppDomainUnloadEvent (vm, req_id, thread_id, id));
+ }
+ }
+
+ internal class CommandException : Exception {
+
+ public CommandException (ErrorCode error_code) : base ("Debuggee returned error code " + error_code + ".") {
+ ErrorCode = error_code;
+ }
+
+ public ErrorCode ErrorCode {
+ get; set;
+ }
+ }
+}
--- /dev/null
+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 delegate Process ProcessLauncher (ProcessStartInfo info);
+ }
+
+ public class VirtualMachineManager
+ {
+ private delegate VirtualMachine LaunchCallback (Process p, Socket socket);
+ private delegate VirtualMachine ListenCallback (Socket dbg_sock, Socket con_sock);
+
+ internal VirtualMachineManager () {
+ }
+
+ public static VirtualMachine LaunchInternal (Process p, Socket socket) {
+ Socket accepted = null;
+ try {
+ accepted = socket.Accept ();
+ } catch (Exception) {
+ throw;
+ }
+
+ Connection conn = new Connection (accepted);
+
+ VirtualMachine vm = new VirtualMachine (p, conn);
+
+ if (p.StartInfo.RedirectStandardOutput)
+ vm.StandardOutput = p.StandardOutput;
+
+ if (p.StartInfo.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";
+
+ Process p;
+ if (options != null && options.CustomProcessLauncher != null)
+ p = options.CustomProcessLauncher (info);
+ else
+ p = Process.Start (info);
+
+ p.Exited += delegate (object sender, EventArgs eargs) {
+ socket.Close ();
+ };
+
+ LaunchCallback c = new LaunchCallback (LaunchInternal);
+ return c.BeginInvoke (p, 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 ();
+ }
+
+ 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) {
+ if (endpoint == null)
+ throw new ArgumentNullException ("endpoint");
+
+ Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+ socket.Connect (endpoint);
+
+ Connection conn = new Connection (socket);
+
+ VirtualMachine vm = new VirtualMachine (null, conn);
+
+ conn.EventHandler = new EventHandler (vm);
+
+ vm.connect ();
+
+ return vm;
+ }
+ }
+}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- 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));
- }
-
-
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- 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 ();
- }
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Reflection;
-using Mono.Debugger;
-using Mono.Cecil;
-
-namespace Mono.Debugger
-{
- 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));
- }
-
- /*
- * 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;
- }
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Mono.Debugger
-{
- 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
+++ /dev/null
-2009-12-05 Lluis Sanchez <lluis@novell.com>
-
- * StructMirror.cs: Fix field indexer for structs with static fields.
- * VirtualMachineManager.cs: Added an option to LaunchOptions which
- allows providing a custom method for launching the process. This
- allows launching mono in a wrapper process.
-
-2009-12-03 Zoltan Varga <vargaz@gmail.com>
-
- * StructMirror.cs (this): Ignore static fields.
-
-2009-12-02 Geoff Norton <gnorton@novell.com>
-
- * VirtualMachineManager.cs: We might get a SocketException (interrupted)
- here, so lets just handle all Exceptions to our Accept pattern the same
- way
-
-2009-12-01 Zoltan Varga <vargaz@gmail.com>
-
- * VirtualMachine.cs (ErrorHandler): Handle NOT_SUSPENDED error code too.
-
-2009-11-24 Zoltan Varga <vargaz@gmail.com>
-
- * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Make the BeginInvokeMethod
- which takes a 'vm' argument obsolete, it was added by mistake, add a version
- without that argument instead.
-
-2009-11-19 Zoltan Varga <vargaz@gmail.com>
-
- * AssemblyMirror.cs: Add a GetName () method.
-
-2009-11-17 Zoltan Varga <vargaz@gmail.com>
-
- * Connection.cs ObjectMirror.cs: Implement invokes in a real asynchronous way,
- without waiting.
-
-2009-11-14 Zoltan Varga <vargaz@gmail.com>
-
- * InvokeOptions.cs: Add SingleThreaded option, not yet works.
-
- * VirtualMachineManager.cs (Launch): Pass options to BeginLaunch.
-
- * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Implement an async version of
- InvokeMethod ().
-
-2009-11-13 Zoltan Varga <vargaz@gmail.com>
-
- * InvokeOptions.cs: New file.
-
- * ObjectMirror.cs TypeMirror.cs StructMirror.cs: Add support for passing flags
- to InvokeMethod ().
-
- * Connection.cs: Bump protocol version.
-
-2009-11-12 Zoltan Varga <vargaz@gmail.com>
-
- * VirtualMachineManager.cs: Put back the old Launch (string[], LaunchOptions)
- overload.
-
-2009-11-11 Geoff Norton <gnorton@novell.com>
-
- * VirtualMachineManager.cs: Refactor the APIs to have async methods.
- Remove a bunch of Listen overloads that are pointless. Refactor
- Launch to take a ProcessStartInfo instead of string arguments.
-
-2009-11-10 Zoltan Varga <vargaz@gmail.com>
-
- * VirtualMachineManager.cs (Launch): Close the listening socket instead of
- shutting it down since Shutdown throws on exception on non-connected sockets
- in ms.net.
-
-2009-11-05 Zoltan Varga <vargaz@gmail.com>
-
- * VirtualMachineManager.cs (Listen): Resurrect the old listen method.
-
- * VirtualMachineManager.cs (Connect): New method to connect to a runtime
- listening at the provided address.
-
-2009-11-04 Lluis Sanchez <lluis@novell.com>
-
- * VirtualMachineManager.cs: Properly redirect standard output.
-
-2009-11-03 Zoltan Varga <vargaz@gmail.com>
-
- * EventRequest.cs (AssemblyFilter): New property to filter
- events based on a list of assemblies.
-
- * Connection.cs: Add assembly filters to the protocol implementation.
+++ /dev/null
-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
-{
- 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;
- 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;
- }
- }
-
- class AssemblyModifier : Modifier {
- public long[] Assemblies {
- get; set;
- }
- }
-
- public enum ErrorCode {
- NONE = 0,
- INVALID_OBJECT = 20,
- INVALID_FIELDID = 25,
- INVALID_FRAMEID = 30,
- NOT_IMPLEMENTED = 100,
- NOT_SUSPENDED = 101,
- INVALID_ARGUMENT = 102
- }
-
- 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,
- * and the debuggee's minor version is <= the library's minor version.
- */
- public const int MAJOR_VERSION = 2;
- public const int MINOR_VERSION = 0;
-
- 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
- }
-
- enum CmdEvent {
- COMPOSITE = 100
- }
-
- enum CmdThread {
- GET_FRAME_INFO = 1,
- GET_NAME = 2,
- GET_STATE = 3,
- GET_INFO = 4
- }
-
- 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
- }
-
- 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
- }
-
- 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 ();
- }
-
- 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) {
- r.ReadByte (); // suspend_policy
- int nevents = r.ReadInt ();
-
- for (int i = 0; i < nevents; ++i) {
- EventKind kind = (EventKind)r.ReadByte ();
- int req_id = r.ReadInt ();
-
- if (kind == EventKind.VM_START) {
- long thread_id = r.ReadId ();
- EventHandler.VMStart (req_id, thread_id, null);
- } else if (kind == EventKind.VM_DEATH) {
- EventHandler.VMDeath (req_id, 0, null);
- } else if (kind == EventKind.THREAD_START) {
- long thread_id = r.ReadId ();
- EventHandler.ThreadStart (req_id, thread_id, thread_id);
- } else if (kind == EventKind.THREAD_DEATH) {
- long thread_id = r.ReadId ();
- EventHandler.ThreadDeath (req_id, thread_id, thread_id);
- } else if (kind == EventKind.ASSEMBLY_LOAD) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- EventHandler.AssemblyLoad (req_id, thread_id, id);
- } else if (kind == EventKind.TYPE_LOAD) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- EventHandler.TypeLoad (req_id, thread_id, id);
- } else if (kind == EventKind.METHOD_ENTRY) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- EventHandler.MethodEntry (req_id, thread_id, id);
- } else if (kind == EventKind.METHOD_EXIT) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- 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 ();
- 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 ();
- 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
- EventHandler.Exception (req_id, thread_id, id, loc);
- } else if (kind == EventKind.APPDOMAIN_CREATE) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- EventHandler.AppDomainCreate (req_id, thread_id, id);
- } else if (kind == EventKind.APPDOMAIN_UNLOAD) {
- long thread_id = r.ReadId ();
- long id = r.ReadId ();
- EventHandler.AppDomainUnload (req_id, thread_id, id);
- } else {
- throw new NotImplementedException ("Unknown event kind: " + kind);
- }
- }
- }
- }
-
- return true;
- }
-
- public IEventHandler EventHandler {
- get; set;
- }
-
- /* Send a request and call cb when a result is received */
- void 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));
- }
-
- 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 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 void VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
- 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);
- }
- });
- }
-
- /*
- * 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 ();
- }
-
- /*
- * 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;
- }
-
- /*
- * 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;
-
- 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) {
- var r = SendReceive (CommandSet.TYPE, (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) {
- w.WriteByte ((byte)ModifierKind.EXCEPTION_ONLY);
- w.WriteId ((mod as ExceptionModifier).Type);
- } 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 VMStart (int req_id, long thread_id, string vm_uri);
-
- void VMDeath (int req_id, long thread_id, string vm_uri);
-
- void VMDisconnect (int req_id, long thread_id, string vm_uri);
-
- void ThreadStart (int req_id, long thread_id, long id);
-
- void ThreadDeath (int req_id, long thread_id, long id);
-
- void AssemblyLoad (int req_id, long thread_id, long id);
-
- void TypeLoad (int req_id, long thread_id, long id);
-
- void MethodEntry (int req_id, long thread_id, long id);
-
- void MethodExit (int req_id, long thread_id, long id);
-
- void Breakpoint (int req_id, long thread_id, long method_id, long loc);
-
- void Step (int req_id, long thread_id, long method_id, long loc);
-
- void Exception (int req_id, long thread_id, long exc_id, long loc);
-
- void AppDomainCreate (int req_id, long thread_id, long id);
-
- void AppDomainUnload (int req_id, long thread_id, long id);
- }
-}
+++ /dev/null
-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 {
-
- 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;
- }
- }
-
-}
+++ /dev/null
-using System;
-using System.Runtime.InteropServices;
-using System.Reflection;
-
-namespace Mono.Debugger {
-
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Runtime.InteropServices;
-using System.Collections.ObjectModel;
-using System.Reflection;
-
-namespace Mono.Debugger {
-
- 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;
- }
- }
-}
+++ /dev/null
-//
-// Authors:
-// Miguel de Icaza (miguel@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
-
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- /*
- * Represents an enum value in the debuggee
- */
- public class EnumMirror : StructMirror {
-
- internal EnumMirror (VirtualMachine vm, TypeMirror type, Value[] fields) : base (vm, type, fields) {
- }
-
- 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
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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);
- }
- }
- }
-}
+++ /dev/null
-#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
-{
- 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
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Mono.Debugger
-{
- 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
+++ /dev/null
-
-namespace Mono.Debugger
-{
- // 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
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- public sealed class ExceptionEventRequest : EventRequest {
-
- TypeMirror exc_type;
-
- internal ExceptionEventRequest (VirtualMachine vm, TypeMirror exc_type) : 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;
- }
-
- 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 });
- SendReq (mods);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Reflection;
-using C = Mono.Cecil;
-using Mono.Cecil.Metadata;
-
-namespace Mono.Debugger
-{
- 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 ();
- }
- }
-}
-
+++ /dev/null
-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
-{
- /*
- * 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- /*
- * 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;
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class InvalidStackFrameException : Exception {
-
- public InvalidStackFrameException () : base ("The requested operation cannot be completed because the specified stack frame is no longer valid.") {
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- 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
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- [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
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
-
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-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
-{
- 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;
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public sealed class MethodEntryEventRequest : EventRequest {
-
- internal MethodEntryEventRequest (VirtualMachine vm) : base (vm, EventType.MethodEntry) {
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public sealed class MethodExitEventRequest : EventRequest {
-
- internal MethodExitEventRequest (VirtualMachine vm) : base (vm, EventType.MethodExit) {
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Reflection;
-using C = Mono.Cecil;
-using Mono.Cecil.Metadata;
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- 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 ();
- }
- }
-}
+++ /dev/null
-using System;
-using Mono.Debugger;
-using Mono.Cecil;
-
-namespace Mono.Debugger
-{
- 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
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class ObjectCollectedException : Exception {
-
- public ObjectCollectedException () : base ("The requested operation cannot be completed because the object has been garbage collected.") {
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Runtime.Remoting.Messaging;
-using System.Threading;
-
-namespace Mono.Debugger
-{
- 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 : IAsyncResult {
-
- 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 ValueImpl Value {
- get; set;
- }
-
- public ValueImpl Exception {
- get; set;
- }
- }
-
- internal static IAsyncResult 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, Callback = callback };
-
- 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));
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Reflection;
-
-namespace Mono.Debugger
-{
- 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
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- /*
- * 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
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Reflection;
-using C = Mono.Cecil;
-using Mono.Cecil.Metadata;
-
-namespace Mono.Debugger
-{
- 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 ();
- }
- }
-}
-
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- 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
+++ /dev/null
-using System;
-using System.Collections;
-
-namespace Mono.Debugger
-{
- public class StringMirror : ObjectMirror {
-
- internal StringMirror (VirtualMachine vm, long id) : base (vm, id) {
- }
-
- public string Value {
- get {
- return vm.conn.String_GetValue (id);
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- /*
- * 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);
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-
-namespace Mono.Debugger
-{
- // Keep it in sync with debugger-agent.h
- public enum SuspendPolicy {
- None = 0,
- EventThread = 1,
- All = 2
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- public class ThreadDeathEvent : Event {
- internal ThreadDeathEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadDeath, vm, req_id, id) {
- }
- }
-}
+++ /dev/null
-using System;
-using System.Threading;
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- public class ThreadStartEvent : Event {
- internal ThreadStartEvent (VirtualMachine vm, int req_id, long id) : base (EventType.ThreadStart, vm, req_id, id) {
- }
- }
-}
+++ /dev/null
-
-namespace Mono.Debugger
-{
- 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;
- }
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using C = Mono.Cecil;
-using Mono.Cecil.Metadata;
-
-namespace Mono.Debugger
-{
- /*
- * 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 {
- // FIXME:
- return false;
- //return IsSubclassOf (typeof (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 vm.conn.Type_GetSourceFiles (id);
- }
-
- 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;
- }
-
- /*
- * 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);
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class VMDeathEvent : Event
- {
- public VMDeathEvent (VirtualMachine vm, int req_id) : base (EventType.VMDeath, vm, req_id, -1) {
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class VMDisconnectEvent : Event
- {
- public VMDisconnectEvent (VirtualMachine vm, int req_id) : base (EventType.VMDisconnect, vm, req_id, -1) {
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class VMDisconnectedException : Exception {
-
- public VMDisconnectedException () : base () {
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class VMMismatchException : Exception
- {
- public VMMismatchException () : base () {
- }
- }
-}
+++ /dev/null
-using System;
-
-namespace Mono.Debugger
-{
- public class VMStartEvent : Event
- {
- public VMStartEvent (VirtualMachine vm, int req_id, long thread_id) : base (EventType.VMStart, vm, req_id, thread_id) {
- }
- }
-}
+++ /dev/null
-using System;
-using System.Collections.Generic;
-
-namespace Mono.Debugger
-{
- public abstract class Value : Mirror {
-
- // FIXME: Add a 'Value' field
-
- internal Value (VirtualMachine vm, long id) : base (vm, id) {
- }
- }
-}
-
+++ /dev/null
-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
-{
- public class VirtualMachine : Mirror
- {
- Queue queue;
- object queue_monitor;
- object startup_monitor;
- AppDomainMirror root_domain;
- Dictionary<int, EventRequest> requests;
- Process process;
-
- internal Connection conn;
-
- internal VirtualMachine (Process 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 {
- return process;
- }
- }
-
- public AppDomainMirror RootDomain {
- get {
- return root_domain;
- }
- }
-
- public EndPoint EndPoint {
- get {
- return conn.EndPoint;
- }
- }
-
- public Event GetNextEvent () {
- lock (queue_monitor) {
- if (queue.Count == 0)
- Monitor.Wait (queue_monitor);
- return (Event)queue.Dequeue ();
- }
- }
-
- public Event GetNextEvent (int timeout) {
- throw new NotImplementedException ();
- }
-
- 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, 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);
- }
-
- //
- // 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);
- }
-
- public void EnableEvents (params EventType[] events) {
- foreach (EventType etype in 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 (Event e) {
- lock (queue_monitor) {
- queue.Enqueue (e);
- 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.");
- 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
- VersionInfo ver = conn.Version;
- if ((ver.MajorVersion != Connection.MAJOR_VERSION) ||
- (ver.MinorVersion > Connection.MINOR_VERSION))
- throw new NotSupportedException (String.Format ("The debuggee implements protocol version {0}.{1}, while {2}.{3} is required.", ver.MajorVersion, ver.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, 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 (new VMStartEvent (vm, req_id, thread_id));
- break;
- case EventType.VMDeath:
- queue_event (new VMDeathEvent (vm, req_id));
- break;
- case EventType.VMDisconnect:
- queue_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 VMStart (int req_id, long thread_id, string vm_uri) {
- vm.notify_vm_event (EventType.VMStart, req_id, thread_id, vm_uri);
- }
-
- public void VMDeath (int req_id, long thread_id, string vm_uri) {
- vm.notify_vm_event (EventType.VMDeath, req_id, thread_id, vm_uri);
- }
-
- public void VMDisconnect (int req_id, long thread_id, string vm_uri) {
- vm.notify_vm_event (EventType.VMDisconnect, req_id, thread_id, vm_uri);
- }
-
- public void ThreadStart (int req_id, long thread_id, long id) {
- vm.queue_event (new ThreadStartEvent (vm, req_id, id));
- }
-
- public void ThreadDeath (int req_id, long thread_id, long id) {
- vm.queue_event (new ThreadDeathEvent (vm, req_id, id));
- }
-
- public void AssemblyLoad (int req_id, long thread_id, long id) {
- vm.queue_event (new AssemblyLoadEvent (vm, req_id, thread_id, id));
- }
-
- public void TypeLoad (int req_id, long thread_id, long id) {
- vm.queue_event (new TypeLoadEvent (vm, req_id, thread_id, id));
- }
-
- public void MethodEntry (int req_id, long thread_id, long id) {
- vm.queue_event (new MethodEntryEvent (vm, req_id, thread_id, id));
- }
-
- public void MethodExit (int req_id, long thread_id, long id) {
- vm.queue_event (new MethodExitEvent (vm, req_id, thread_id, id));
- }
-
- public void Breakpoint (int req_id, long thread_id, long id, long loc) {
- vm.queue_event (new BreakpointEvent (vm, req_id, thread_id, id, loc));
- }
-
- public void Step (int req_id, long thread_id, long id, long loc) {
- vm.queue_event (new StepEvent (vm, req_id, thread_id, id, loc));
- }
-
- public void Exception (int req_id, long thread_id, long id, long loc) {
- vm.queue_event (new ExceptionEvent (vm, req_id, thread_id, id, loc));
- }
-
- public void AppDomainCreate (int req_id, long thread_id, long id) {
- vm.queue_event (new AppDomainCreateEvent (vm, req_id, thread_id, id));
- }
-
- public void AppDomainUnload (int req_id, long thread_id, long id) {
- vm.queue_event (new AppDomainUnloadEvent (vm, req_id, thread_id, id));
- }
- }
-
- internal class CommandException : Exception {
-
- public CommandException (ErrorCode error_code) : base ("Debuggee returned error code " + error_code + ".") {
- ErrorCode = error_code;
- }
-
- public ErrorCode ErrorCode {
- get; set;
- }
- }
-}
+++ /dev/null
-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
-{
- public class LaunchOptions {
- public string AgentArgs {
- get; set;
- }
-
- public bool Valgrind {
- get; set;
- }
-
- public ProcessLauncher CustomProcessLauncher {
- get; set;
- }
-
- public delegate Process ProcessLauncher (ProcessStartInfo info);
- }
-
- public class VirtualMachineManager
- {
- private delegate VirtualMachine LaunchCallback (Process p, Socket socket);
- private delegate VirtualMachine ListenCallback (Socket dbg_sock, Socket con_sock);
-
- internal VirtualMachineManager () {
- }
-
- public static VirtualMachine LaunchInternal (Process p, Socket socket) {
- Socket accepted = null;
- try {
- accepted = socket.Accept ();
- } catch (Exception) {
- throw;
- }
-
- Connection conn = new Connection (accepted);
-
- VirtualMachine vm = new VirtualMachine (p, conn);
-
- if (p.StartInfo.RedirectStandardOutput)
- vm.StandardOutput = p.StandardOutput;
-
- if (p.StartInfo.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";
-
- Process p;
- if (options != null && options.CustomProcessLauncher != null)
- p = options.CustomProcessLauncher (info);
- else
- p = Process.Start (info);
-
- p.Exited += delegate (object sender, EventArgs eargs) {
- socket.Close ();
- };
-
- LaunchCallback c = new LaunchCallback (LaunchInternal);
- return c.BeginInvoke (p, 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 ();
- }
-
- 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) {
- if (endpoint == null)
- throw new ArgumentNullException ("endpoint");
-
- Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- socket.Connect (endpoint);
-
- Connection conn = new Connection (socket);
-
- VirtualMachine vm = new VirtualMachine (null, conn);
-
- conn.EventHandler = new EventHandler (vm);
-
- vm.connect ();
-
- return vm;
- }
- }
-}