2009-11-14 Zoltan Varga <vargaz@gmail.com>
[mcs.git] / class / Mono.Debugger.Soft / Mono.Debugger / Connection.cs
blobacf5ee42d4ec48079ee421ac01094384c0616de3
1 using System;
2 using System.IO;
3 using System.Net;
4 using System.Net.Sockets;
5 using System.Threading;
6 using System.Collections.Generic;
7 using System.Text;
8 using Mono.Cecil.Metadata;
10 namespace Mono.Debugger
12 class VersionInfo {
13 public string VMVersion {
14 get; set;
17 public int MajorVersion {
18 get; set;
21 public int MinorVersion {
22 get; set;
26 class DebugInfo {
27 public int max_il_offset;
28 public string filename;
29 public int[] il_offsets;
30 public int[] line_numbers;
33 struct FrameInfo {
34 public long id;
35 public long method;
36 public int il_offset;
37 public StackFrameFlags flags;
40 class TypeInfo {
41 public string ns, name, full_name;
42 public long assembly, module, base_type, element_type;
43 public int token, rank, attributes;
44 public bool is_byref, is_pointer, is_primitive, is_valuetype;
45 public long[] nested;
48 class MethodInfo {
49 public int attributes, iattributes, token;
52 class MethodBodyInfo {
53 public byte[] il;
56 struct ParamInfo {
57 public int call_conv;
58 public int param_count;
59 public int generic_param_count;
60 public long ret_type;
61 public long[] param_types;
62 public string[] param_names;
65 struct LocalsInfo {
66 public long[] types;
67 public string[] names;
68 public int[] live_range_start;
69 public int[] live_range_end;
72 struct PropInfo {
73 public long id;
74 public string name;
75 public long get_method, set_method;
76 public int attrs;
79 class CattrNamedArgInfo {
80 public bool is_property;
81 public long id;
82 public ValueImpl value;
85 class CattrInfo {
86 public long ctor_id;
87 public ValueImpl[] ctor_args;
88 public CattrNamedArgInfo[] named_args;
91 class ThreadInfo {
92 public bool is_thread_pool;
95 enum ValueTypeId {
96 VALUE_TYPE_ID_NULL = 0xf0,
97 VALUE_TYPE_ID_TYPE = 0xf1
100 enum InvokeFlags {
101 NONE = 0x0,
102 DISABLE_BREAKPOINTS = 0x1,
103 SINGLE_THREADED = 0x2
106 class ValueImpl {
107 public ElementType Type; /* or one of the VALUE_TYPE_ID constants */
108 public long Objid;
109 public object Value;
110 public long Klass; // For ElementType.ValueType
111 public ValueImpl[] Fields; // for ElementType.ValueType
112 public bool IsEnum; // For ElementType.ValueType
113 public long Id; /* For VALUE_TYPE_ID_TYPE */
116 class ModuleInfo {
117 public string Name, ScopeName, FQName, Guid;
118 public long Assembly;
121 enum TokenType {
122 STRING = 0,
123 TYPE = 1,
124 FIELD = 2,
125 METHOD = 3,
126 UNKNOWN = 4
129 enum StackFrameFlags {
130 DEBUGGER_INVOKE = 1
133 class ResolvedToken {
134 public TokenType Type;
135 public string Str;
136 public long Id;
139 class Modifier {
142 class CountModifier : Modifier {
143 public int Count {
144 get; set;
148 class LocationModifier : Modifier {
149 public long Method {
150 get; set;
153 public long Location {
154 get; set;
158 class StepModifier : Modifier {
159 public long Thread {
160 get; set;
163 public int Depth {
164 get; set;
167 public int Size {
168 get; set;
172 class ThreadModifier : Modifier {
173 public long Thread {
174 get; set;
178 class ExceptionModifier : Modifier {
179 public long Type {
180 get; set;
184 class AssemblyModifier : Modifier {
185 public long[] Assemblies {
186 get; set;
190 public enum ErrorCode {
191 NONE = 0,
192 INVALID_OBJECT = 20,
193 INVALID_FIELDID = 25,
194 INVALID_FRAMEID = 30,
195 NOT_IMPLEMENTED = 100,
196 NOT_SUSPENDED = 101,
197 INVALID_ARGUMENT = 102
200 public class ErrorHandlerEventArgs : EventArgs {
202 public ErrorCode ErrorCode {
203 get; set;
208 * Represents the connection to the debuggee
210 class Connection
213 * The protocol and the packet format is based on JDWP, the differences
214 * are in the set of supported events, and the commands.
216 public const string HANDSHAKE_STRING = "DWP-Handshake";
218 public const int HEADER_LENGTH = 11;
221 * Th version of the wire-protocol implemented by the library. The library
222 * and the debuggee can communicate if they implement the same major version,
223 * and the debuggee's minor version is <= the library's minor version.
225 public const int MAJOR_VERSION = 2;
226 public const int MINOR_VERSION = 0;
228 enum WPSuspendPolicy {
229 NONE = 0,
230 EVENT_THREAD = 1,
231 ALL = 2
234 enum CommandSet {
235 VM = 1,
236 OBJECT_REF = 9,
237 STRING_REF = 10,
238 THREAD = 11,
239 ARRAY_REF = 13,
240 EVENT_REQUEST = 15,
241 STACK_FRAME = 16,
242 APPDOMAIN = 20,
243 ASSEMBLY = 21,
244 METHOD = 22,
245 TYPE = 23,
246 MODULE = 24,
247 EVENT = 64
250 enum EventKind {
251 VM_START = 0,
252 VM_DEATH = 1,
253 THREAD_START = 2,
254 THREAD_DEATH = 3,
255 APPDOMAIN_CREATE = 4, // Not in JDI
256 APPDOMAIN_UNLOAD = 5, // Not in JDI
257 METHOD_ENTRY = 6,
258 METHOD_EXIT = 7,
259 ASSEMBLY_LOAD = 8,
260 ASSEMBLY_UNLOAD = 9,
261 BREAKPOINT = 10,
262 STEP = 11,
263 TYPE_LOAD = 12,
264 EXCEPTION = 13
267 enum ModifierKind {
268 COUNT = 1,
269 THREAD_ONLY = 3,
270 LOCATION_ONLY = 7,
271 EXCEPTION_ONLY = 8,
272 STEP = 10,
273 ASSEMBLY_ONLY = 11
276 enum CmdVM {
277 VERSION = 1,
278 ALL_THREADS = 2,
279 SUSPEND = 3,
280 RESUME = 4,
281 EXIT = 5,
282 DISPOSE = 6,
283 INVOKE_METHOD = 7
286 enum CmdEvent {
287 COMPOSITE = 100
290 enum CmdThread {
291 GET_FRAME_INFO = 1,
292 GET_NAME = 2,
293 GET_STATE = 3,
294 GET_INFO = 4
297 enum CmdEventRequest {
298 SET = 1,
299 CLEAR = 2,
300 CLEAR_ALL_BREAKPOINTS = 3
303 enum CmdAppDomain {
304 GET_ROOT_DOMAIN = 1,
305 GET_FRIENDLY_NAME = 2,
306 GET_ASSEMBLIES = 3,
307 GET_ENTRY_ASSEMBLY = 4,
308 CREATE_STRING = 5,
309 GET_CORLIB = 6
312 enum CmdAssembly {
313 GET_LOCATION = 1,
314 GET_ENTRY_POINT = 2,
315 GET_MANIFEST_MODULE = 3,
316 GET_OBJECT = 4,
317 GET_TYPE = 5
320 enum CmdModule {
321 GET_INFO = 1,
324 enum CmdMethod {
325 GET_NAME = 1,
326 GET_DECLARING_TYPE = 2,
327 GET_DEBUG_INFO = 3,
328 GET_PARAM_INFO = 4,
329 GET_LOCALS_INFO = 5,
330 GET_INFO = 6,
331 GET_BODY = 7,
332 RESOLVE_TOKEN = 8
335 enum CmdType {
336 GET_INFO = 1,
337 GET_METHODS = 2,
338 GET_FIELDS = 3,
339 GET_VALUES = 4,
340 GET_OBJECT = 5,
341 GET_SOURCE_FILES = 6,
342 SET_VALUES = 7,
343 IS_ASSIGNABLE_FROM = 8,
344 GET_PROPERTIES = 9,
345 GET_CATTRS = 10,
346 GET_FIELD_CATTRS = 11,
347 GET_PROPERTY_CATTRS = 12
350 enum CmdStackFrame {
351 GET_VALUES = 1,
352 GET_THIS = 2,
353 SET_VALUES = 3
356 enum CmdArrayRef {
357 GET_LENGTH = 1,
358 GET_VALUES = 2,
359 SET_VALUES = 3
362 enum CmdStringRef {
363 GET_VALUE = 1
366 enum CmdObjectRef {
367 GET_TYPE = 1,
368 GET_VALUES = 2,
369 IS_COLLECTED = 3,
370 GET_ADDRESS = 4,
371 GET_DOMAIN = 5,
372 SET_VALUES = 6
375 class Header {
376 public int id;
377 public int command_set;
378 public int command;
379 public int flags;
382 public static int GetPacketLength (byte[] header) {
383 int offset = 0;
384 return decode_int (header, ref offset);
387 public static bool IsReplyPacket (byte[] packet) {
388 int offset = 8;
389 return decode_byte (packet, ref offset) == 0x80;
392 public static int GetPacketId (byte[] packet) {
393 int offset = 4;
394 return decode_int (packet, ref offset);
397 static int decode_byte (byte[] packet, ref int offset) {
398 return packet [offset++];
401 static int decode_short (byte[] packet, ref int offset) {
402 int res = ((int)packet [offset] << 8) | (int)packet [offset + 1];
403 offset += 2;
404 return res;
407 static int decode_int (byte[] packet, ref int offset) {
408 int res = ((int)packet [offset] << 24) | ((int)packet [offset + 1] << 16) | ((int)packet [offset + 2] << 8) | (int)packet [offset + 3];
409 offset += 4;
410 return res;
413 static long decode_id (byte[] packet, ref int offset) {
414 return decode_int (packet, ref offset);
417 static long decode_long (byte[] packet, ref int offset) {
418 uint high = (uint)decode_int (packet, ref offset);
419 uint low = (uint)decode_int (packet, ref offset);
421 return (long)(((ulong)high << 32) | (ulong)low);
424 public static SuspendPolicy decode_suspend_policy (int suspend_policy) {
425 switch ((WPSuspendPolicy)suspend_policy) {
426 case WPSuspendPolicy.NONE:
427 return SuspendPolicy.None;
428 case WPSuspendPolicy.EVENT_THREAD:
429 return SuspendPolicy.EventThread;
430 case WPSuspendPolicy.ALL:
431 return SuspendPolicy.All;
432 default:
433 throw new NotImplementedException ();
437 static Header decode_command_header (byte[] packet) {
438 int offset = 0;
439 Header res = new Header ();
441 decode_int (packet, ref offset);
442 res.id = decode_int (packet, ref offset);
443 res.flags = decode_byte (packet, ref offset);
444 res.command_set = decode_byte (packet, ref offset);
445 res.command = decode_byte (packet, ref offset);
447 return res;
450 static void encode_byte (byte[] buf, int b, ref int offset) {
451 buf [offset] = (byte)b;
452 offset ++;
455 static void encode_int (byte[] buf, int i, ref int offset) {
456 buf [offset] = (byte)((i >> 24) & 0xff);
457 buf [offset + 1] = (byte)((i >> 16) & 0xff);
458 buf [offset + 2] = (byte)((i >> 8) & 0xff);
459 buf [offset + 3] = (byte)((i >> 0) & 0xff);
460 offset += 4;
463 static void encode_id (byte[] buf, long id, ref int offset) {
464 encode_int (buf, (int)id, ref offset);
467 static void encode_long (byte[] buf, long l, ref int offset) {
468 encode_int (buf, (int)((l >> 32) & 0xffffffff), ref offset);
469 encode_int (buf, (int)(l & 0xffffffff), ref offset);
472 public static byte[] EncodePacket (int id, int commandSet, int command, byte[] data, int dataLen) {
473 byte[] buf = new byte [dataLen + 11];
474 int offset = 0;
476 encode_int (buf, buf.Length, ref offset);
477 encode_int (buf, id, ref offset);
478 encode_byte (buf, 0, ref offset);
479 encode_byte (buf, commandSet, ref offset);
480 encode_byte (buf, command, ref offset);
482 for (int i = 0; i < dataLen; ++i)
483 buf [offset + i] = data [i];
485 return buf;
488 class PacketReader {
489 byte[] packet;
490 int offset;
492 public PacketReader (byte[] packet) {
493 this.packet = packet;
495 // For event packets
496 Header header = decode_command_header (packet);
497 CommandSet = (CommandSet)header.command_set;
498 Command = header.command;
500 // For reply packets
501 offset = 0;
502 ReadInt (); // length
503 ReadInt (); // id
504 ReadByte (); // flags
505 ErrorCode = ReadShort ();
508 public CommandSet CommandSet {
509 get; set;
512 public int Command {
513 get; set;
516 public int ErrorCode {
517 get; set;
520 public int Offset {
521 get {
522 return offset;
526 public int ReadByte () {
527 return decode_byte (packet, ref offset);
530 public int ReadShort () {
531 return decode_short (packet, ref offset);
534 public int ReadInt () {
535 return decode_int (packet, ref offset);
538 public long ReadId () {
539 return decode_id (packet, ref offset);
542 public long ReadLong () {
543 return decode_long (packet, ref offset);
546 public float ReadFloat () {
547 float f = DataConverter.FloatFromBE (packet, offset);
548 offset += 4;
549 return f;
552 public double ReadDouble () {
553 double d = DataConverter.DoubleFromBE (packet, offset);
554 offset += 8;
555 return d;
558 public string ReadString () {
559 int len = decode_int (packet, ref offset);
560 string res = new String (Encoding.UTF8.GetChars (packet, offset, len));
561 offset += len;
562 return res;
565 public ValueImpl ReadValue () {
566 ElementType etype = (ElementType)ReadByte ();
568 switch (etype) {
569 case ElementType.Void:
570 return new ValueImpl { Type = etype };
571 case ElementType.I1:
572 return new ValueImpl { Type = etype, Value = (sbyte)ReadInt () };
573 case ElementType.U1:
574 return new ValueImpl { Type = etype, Value = (byte)ReadInt () };
575 case ElementType.Boolean:
576 return new ValueImpl { Type = etype, Value = ReadInt () != 0 };
577 case ElementType.I2:
578 return new ValueImpl { Type = etype, Value = (short)ReadInt () };
579 case ElementType.U2:
580 return new ValueImpl { Type = etype, Value = (ushort)ReadInt () };
581 case ElementType.Char:
582 return new ValueImpl { Type = etype, Value = (char)ReadInt () };
583 case ElementType.I4:
584 return new ValueImpl { Type = etype, Value = ReadInt () };
585 case ElementType.U4:
586 return new ValueImpl { Type = etype, Value = (uint)ReadInt () };
587 case ElementType.I8:
588 return new ValueImpl { Type = etype, Value = ReadLong () };
589 case ElementType.U8:
590 return new ValueImpl { Type = etype, Value = (ulong)ReadLong () };
591 case ElementType.R4:
592 return new ValueImpl { Type = etype, Value = ReadFloat () };
593 case ElementType.R8:
594 return new ValueImpl { Type = etype, Value = ReadDouble () };
595 case ElementType.I:
596 case ElementType.U:
597 case ElementType.Ptr:
598 // FIXME: The client and the debuggee might have different word sizes
599 return new ValueImpl { Type = etype, Value = ReadLong () };
600 case ElementType.String:
601 case ElementType.SzArray:
602 case ElementType.Class:
603 case ElementType.Array:
604 case ElementType.Object:
605 long objid = ReadId ();
606 return new ValueImpl () { Type = etype, Objid = objid };
607 case ElementType.ValueType:
608 bool is_enum = ReadByte () == 1;
609 long klass = ReadId ();
610 long nfields = ReadInt ();
611 ValueImpl[] fields = new ValueImpl [nfields];
612 for (int i = 0; i < nfields; ++i)
613 fields [i] = ReadValue ();
614 return new ValueImpl () { Type = etype, Klass = klass, Fields = fields, IsEnum = is_enum };
615 case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
616 return new ValueImpl { Type = etype };
617 case (ElementType)ValueTypeId.VALUE_TYPE_ID_TYPE:
618 return new ValueImpl () { Type = etype, Id = ReadId () };
619 default:
620 throw new NotImplementedException ("Unable to handle type " + etype);
625 class PacketWriter {
627 byte[] data;
628 int offset;
630 public PacketWriter () {
631 // FIXME:
632 data = new byte [1024];
633 offset = 0;
636 public PacketWriter WriteByte (byte val) {
637 encode_byte (data, val, ref offset);
638 return this;
641 public PacketWriter WriteInt (int val) {
642 encode_int (data, val, ref offset);
643 return this;
646 public PacketWriter WriteId (long id) {
647 encode_id (data, id, ref offset);
648 return this;
651 public PacketWriter WriteLong (long val) {
652 encode_long (data, val, ref offset);
653 return this;
656 public PacketWriter WriteFloat (float f) {
657 byte[] b = DataConverter.GetBytesBE (f);
658 for (int i = 0; i < 4; ++i)
659 data [offset + i] = b [i];
660 offset += 4;
661 return this;
664 public PacketWriter WriteDouble (double d) {
665 byte[] b = DataConverter.GetBytesBE (d);
666 for (int i = 0; i < 8; ++i)
667 data [offset + i] = b [i];
668 offset += 8;
669 return this;
672 public PacketWriter WriteInts (int[] ids) {
673 for (int i = 0; i < ids.Length; ++i)
674 WriteInt (ids [i]);
675 return this;
678 public PacketWriter WriteIds (long[] ids) {
679 for (int i = 0; i < ids.Length; ++i)
680 WriteId (ids [i]);
681 return this;
684 public PacketWriter WriteString (string s) {
685 encode_int (data, s.Length, ref offset);
686 byte[] b = Encoding.UTF8.GetBytes (s);
687 Buffer.BlockCopy (b, 0, data, offset, b.Length);
688 offset += b.Length;
689 return this;
692 public PacketWriter WriteBool (bool val) {
693 WriteByte (val ? (byte)1 : (byte)0);
694 return this;
697 public PacketWriter WriteValue (ValueImpl v) {
698 ElementType t;
700 if (v.Value != null)
701 t = TypeCodeToElementType (Type.GetTypeCode (v.Value.GetType ()));
702 else
703 t = v.Type;
704 WriteByte ((byte)t);
705 switch (t) {
706 case ElementType.Boolean:
707 WriteInt ((bool)v.Value ? 1 : 0);
708 break;
709 case ElementType.Char:
710 WriteInt ((int)(char)v.Value);
711 break;
712 case ElementType.I1:
713 WriteInt ((int)(sbyte)v.Value);
714 break;
715 case ElementType.U1:
716 WriteInt ((int)(byte)v.Value);
717 break;
718 case ElementType.I2:
719 WriteInt ((int)(short)v.Value);
720 break;
721 case ElementType.U2:
722 WriteInt ((int)(ushort)v.Value);
723 break;
724 case ElementType.I4:
725 WriteInt ((int)(int)v.Value);
726 break;
727 case ElementType.U4:
728 WriteInt ((int)(uint)v.Value);
729 break;
730 case ElementType.I8:
731 WriteLong ((long)(long)v.Value);
732 break;
733 case ElementType.U8:
734 WriteLong ((long)(ulong)v.Value);
735 break;
736 case ElementType.R4:
737 WriteFloat ((float)v.Value);
738 break;
739 case ElementType.R8:
740 WriteDouble ((double)v.Value);
741 break;
742 case ElementType.String:
743 case ElementType.SzArray:
744 case ElementType.Class:
745 case ElementType.Array:
746 case ElementType.Object:
747 WriteId (v.Objid);
748 break;
749 case ElementType.ValueType:
750 // FIXME:
751 if (v.IsEnum)
752 throw new NotImplementedException ();
753 WriteByte (0);
754 WriteId (v.Klass);
755 WriteInt (v.Fields.Length);
756 for (int i = 0; i < v.Fields.Length; ++i)
757 WriteValue (v.Fields [i]);
758 break;
759 case (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL:
760 break;
761 default:
762 throw new NotImplementedException ();
765 return this;
768 public PacketWriter WriteValues (ValueImpl[] values) {
769 for (int i = 0; i < values.Length; ++i)
770 WriteValue (values [i]);
771 return this;
774 public byte[] Data {
775 get {
776 return data;
780 public int Offset {
781 get {
782 return offset;
787 Socket socket;
788 bool closed;
789 Thread receiver_thread;
790 Dictionary<int, byte[]> reply_packets;
791 object reply_packets_monitor;
793 public event EventHandler<ErrorHandlerEventArgs> ErrorHandler;
795 public Connection (Socket socket) {
796 this.socket = socket;
797 //socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.NoDelay, 1);
798 closed = false;
799 reply_packets = new Dictionary<int, byte[]> ();
800 reply_packets_monitor = new Object ();
803 int Receive (byte[] buf, int buf_offset, int len) {
804 int offset = 0;
806 while (offset < len) {
807 int n = socket.Receive (buf, buf_offset + offset, len - offset, SocketFlags.None);
809 if (n == 0)
810 return offset;
811 offset += n;
814 return offset;
817 public VersionInfo Version;
819 // Do the wire protocol handshake
820 public void Connect () {
821 byte[] buf = new byte [HANDSHAKE_STRING.Length];
822 char[] cbuf = new char [buf.Length];
824 // FIXME: Add a timeout
825 int n = Receive (buf, 0, buf.Length);
826 if (n == 0)
827 throw new IOException ("DWP Handshake failed.");
828 for (int i = 0; i < buf.Length; ++i)
829 cbuf [i] = (char)buf [i];
831 if (new String (cbuf) != HANDSHAKE_STRING)
832 throw new IOException ("DWP Handshake failed.");
834 socket.Send (buf);
836 receiver_thread = new Thread (new ThreadStart (receiver_thread_main));
837 receiver_thread.Start ();
839 Version = VM_GetVersion ();
842 public EndPoint EndPoint {
843 get {
844 return socket.RemoteEndPoint;
848 public byte[] ReadPacket () {
849 // FIXME: Throw ClosedConnectionException () if the connection is closed
850 // FIXME: Throw ClosedConnectionException () if another thread closes the connection
851 // FIXME: Locking
852 byte[] header = new byte [HEADER_LENGTH];
854 int len = Receive (header, 0, header.Length);
855 if (len == 0)
856 return new byte [0];
857 if (len != HEADER_LENGTH) {
858 // FIXME:
859 throw new IOException ("Packet of length " + len + " is read.");
862 int packetLength = GetPacketLength (header);
863 if (packetLength < 11)
864 throw new IOException ("Invalid packet length.");
866 if (packetLength == 11) {
867 return header;
868 } else {
869 byte[] buf = new byte [packetLength];
870 for (int i = 0; i < header.Length; ++i)
871 buf [i] = header [i];
872 len = Receive (buf, header.Length, packetLength - header.Length);
873 if (len != packetLength - header.Length)
874 throw new IOException ();
875 return buf;
879 public void WritePacket (byte[] packet) {
880 // FIXME: Throw ClosedConnectionException () if the connection is closed
881 // FIXME: Throw ClosedConnectionException () if another thread closes the connection
882 // FIXME: Locking
883 socket.Send (packet);
886 public void Close () {
887 closed = true;
890 public bool IsClosed {
891 get {
892 return closed;
896 bool disconnected;
898 void receiver_thread_main () {
899 while (true) {
900 try {
901 bool res = ReceivePacket ();
902 if (!res)
903 break;
904 } catch (Exception ex) {
905 Console.WriteLine (ex);
906 break;
910 lock (reply_packets_monitor) {
911 disconnected = true;
912 Monitor.PulseAll (reply_packets_monitor);
914 EventHandler.VMDisconnect (0, 0, null);
917 bool ReceivePacket () {
918 byte[] packet = ReadPacket ();
920 if (packet.Length == 0) {
921 return false;
924 if (IsReplyPacket (packet)) {
925 int id = GetPacketId (packet);
926 lock (reply_packets_monitor) {
927 reply_packets [id] = packet;
928 Monitor.PulseAll (reply_packets_monitor);
930 } else {
931 PacketReader r = new PacketReader (packet);
933 if (r.CommandSet == CommandSet.EVENT && r.Command == (int)CmdEvent.COMPOSITE) {
934 r.ReadByte (); // suspend_policy
935 int nevents = r.ReadInt ();
937 for (int i = 0; i < nevents; ++i) {
938 EventKind kind = (EventKind)r.ReadByte ();
939 int req_id = r.ReadInt ();
941 if (kind == EventKind.VM_START) {
942 long thread_id = r.ReadId ();
943 EventHandler.VMStart (req_id, thread_id, null);
944 } else if (kind == EventKind.VM_DEATH) {
945 EventHandler.VMDeath (req_id, 0, null);
946 } else if (kind == EventKind.THREAD_START) {
947 long thread_id = r.ReadId ();
948 EventHandler.ThreadStart (req_id, thread_id, thread_id);
949 } else if (kind == EventKind.THREAD_DEATH) {
950 long thread_id = r.ReadId ();
951 EventHandler.ThreadDeath (req_id, thread_id, thread_id);
952 } else if (kind == EventKind.ASSEMBLY_LOAD) {
953 long thread_id = r.ReadId ();
954 long id = r.ReadId ();
955 EventHandler.AssemblyLoad (req_id, thread_id, id);
956 } else if (kind == EventKind.TYPE_LOAD) {
957 long thread_id = r.ReadId ();
958 long id = r.ReadId ();
959 EventHandler.TypeLoad (req_id, thread_id, id);
960 } else if (kind == EventKind.METHOD_ENTRY) {
961 long thread_id = r.ReadId ();
962 long id = r.ReadId ();
963 EventHandler.MethodEntry (req_id, thread_id, id);
964 } else if (kind == EventKind.METHOD_EXIT) {
965 long thread_id = r.ReadId ();
966 long id = r.ReadId ();
967 EventHandler.MethodExit (req_id, thread_id, id);
968 } else if (kind == EventKind.BREAKPOINT) {
969 long thread_id = r.ReadId ();
970 long id = r.ReadId ();
971 long loc = r.ReadLong ();
972 EventHandler.Breakpoint (req_id, thread_id, id, loc);
973 } else if (kind == EventKind.STEP) {
974 long thread_id = r.ReadId ();
975 long id = r.ReadId ();
976 long loc = r.ReadLong ();
977 EventHandler.Step (req_id, thread_id, id, loc);
978 } else if (kind == EventKind.EXCEPTION) {
979 long thread_id = r.ReadId ();
980 long id = r.ReadId ();
981 long loc = 0; // FIXME
982 EventHandler.Exception (req_id, thread_id, id, loc);
983 } else if (kind == EventKind.APPDOMAIN_CREATE) {
984 long thread_id = r.ReadId ();
985 long id = r.ReadId ();
986 EventHandler.AppDomainCreate (req_id, thread_id, id);
987 } else if (kind == EventKind.APPDOMAIN_UNLOAD) {
988 long thread_id = r.ReadId ();
989 long id = r.ReadId ();
990 EventHandler.AppDomainUnload (req_id, thread_id, id);
991 } else {
992 throw new NotImplementedException ("Unknown event kind: " + kind);
998 return true;
1001 public IEventHandler EventHandler {
1002 get; set;
1005 PacketReader SendReceive (CommandSet command_set, int command, PacketWriter packet) {
1006 int id = IdGenerator;
1008 if (packet == null)
1009 WritePacket (EncodePacket (id, (int)command_set, command, null, 0));
1010 else
1011 WritePacket (EncodePacket (id, (int)command_set, command, packet.Data, packet.Offset));
1013 int packetId = id;
1015 /* Wait for the reply packet */
1016 while (true) {
1017 lock (reply_packets_monitor) {
1018 if (reply_packets.ContainsKey (packetId)) {
1019 byte[] reply = reply_packets [packetId];
1020 reply_packets.Remove (packetId);
1021 PacketReader r = new PacketReader (reply);
1022 if (r.ErrorCode != 0) {
1023 if (ErrorHandler != null)
1024 ErrorHandler (this, new ErrorHandlerEventArgs () { ErrorCode = (ErrorCode)r.ErrorCode });
1025 throw new NotImplementedException ("No error handler set.");
1026 } else {
1027 return r;
1029 } else {
1030 if (disconnected)
1031 throw new VMDisconnectedException ();
1032 Monitor.Wait (reply_packets_monitor);
1038 PacketReader SendReceive (CommandSet command_set, int command) {
1039 return SendReceive (command_set, command, null);
1042 int packet_id_generator;
1044 int IdGenerator {
1045 get {
1046 return Interlocked.Increment (ref packet_id_generator);
1050 CattrInfo[] ReadCattrs (PacketReader r) {
1051 CattrInfo[] res = new CattrInfo [r.ReadInt ()];
1052 for (int i = 0; i < res.Length; ++i) {
1053 CattrInfo info = new CattrInfo ();
1054 info.ctor_id = r.ReadId ();
1055 info.ctor_args = new ValueImpl [r.ReadInt ()];
1056 for (int j = 0; j < info.ctor_args.Length; ++j) {
1057 info.ctor_args [j] = r.ReadValue ();
1059 info.named_args = new CattrNamedArgInfo [r.ReadInt ()];
1060 for (int j = 0; j < info.named_args.Length; ++j) {
1061 CattrNamedArgInfo arg = new CattrNamedArgInfo ();
1062 int arg_type = r.ReadByte ();
1063 arg.is_property = arg_type == 0x54;
1064 arg.id = r.ReadId ();
1065 arg.value = r.ReadValue ();
1066 info.named_args [j] = arg;
1068 res [i] = info;
1070 return res;
1073 static ElementType TypeCodeToElementType (TypeCode c) {
1074 switch (c) {
1075 case TypeCode.Boolean:
1076 return ElementType.Boolean;
1077 case TypeCode.Char:
1078 return ElementType.Char;
1079 case TypeCode.SByte:
1080 return ElementType.I1;
1081 case TypeCode.Byte:
1082 return ElementType.U1;
1083 case TypeCode.Int16:
1084 return ElementType.I2;
1085 case TypeCode.UInt16:
1086 return ElementType.U2;
1087 case TypeCode.Int32:
1088 return ElementType.I4;
1089 case TypeCode.UInt32:
1090 return ElementType.U4;
1091 case TypeCode.Int64:
1092 return ElementType.I8;
1093 case TypeCode.UInt64:
1094 return ElementType.U8;
1095 case TypeCode.Single:
1096 return ElementType.R4;
1097 case TypeCode.Double:
1098 return ElementType.R8;
1099 default:
1100 throw new NotImplementedException ();
1105 * Implementation of debugger commands
1108 public VersionInfo VM_GetVersion () {
1109 var res = SendReceive (CommandSet.VM, (int)CmdVM.VERSION, null);
1110 VersionInfo info = new VersionInfo ();
1111 info.VMVersion = res.ReadString ();
1112 info.MajorVersion = res.ReadInt ();
1113 info.MinorVersion = res.ReadInt ();
1114 return info;
1117 public long[] VM_GetThreads () {
1118 var res = SendReceive (CommandSet.VM, (int)CmdVM.ALL_THREADS, null);
1119 int len = res.ReadInt ();
1120 long[] arr = new long [len];
1121 for (int i = 0; i < len; ++i)
1122 arr [i] = res.ReadId ();
1123 return arr;
1126 public void VM_Suspend () {
1127 SendReceive (CommandSet.VM, (int)CmdVM.SUSPEND);
1130 public void VM_Resume () {
1131 SendReceive (CommandSet.VM, (int)CmdVM.RESUME);
1134 public void VM_Exit (int exitCode) {
1135 SendReceive (CommandSet.VM, (int)CmdVM.EXIT, new PacketWriter ().WriteInt (exitCode));
1138 public void VM_Dispose () {
1139 SendReceive (CommandSet.VM, (int)CmdVM.DISPOSE);
1142 public ValueImpl VM_InvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, out ValueImpl exc) {
1143 exc = null;
1144 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));
1145 if (r.ReadByte () == 0) {
1146 exc = r.ReadValue ();
1147 return null;
1148 } else {
1149 return r.ReadValue ();
1154 * DOMAIN
1157 public long RootDomain {
1158 get {
1159 return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ROOT_DOMAIN, null).ReadId ();
1163 public string Domain_GetName (long id) {
1164 return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_FRIENDLY_NAME, new PacketWriter ().WriteId (id)).ReadString ();
1167 public long[] Domain_GetAssemblies (long id) {
1168 var res = SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ASSEMBLIES, new PacketWriter ().WriteId (id));
1169 int count = res.ReadInt ();
1170 long[] assemblies = new long [count];
1171 for (int i = 0; i < count; ++i)
1172 assemblies [i] = res.ReadId ();
1173 return assemblies;
1176 public long Domain_GetEntryAssembly (long id) {
1177 return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_ENTRY_ASSEMBLY, new PacketWriter ().WriteId (id)).ReadId ();
1180 public long Domain_GetCorlib (long id) {
1181 return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.GET_CORLIB, new PacketWriter ().WriteId (id)).ReadId ();
1184 public long Domain_CreateString (long id, string s) {
1185 return SendReceive (CommandSet.APPDOMAIN, (int)CmdAppDomain.CREATE_STRING, new PacketWriter ().WriteId (id).WriteString (s)).ReadId ();
1189 * METHOD
1192 public string Method_GetName (long id) {
1193 return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
1196 public long Method_GetDeclaringType (long id) {
1197 return SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_DECLARING_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
1200 public DebugInfo Method_GetDebugInfo (long id) {
1201 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_DEBUG_INFO, new PacketWriter ().WriteId (id));
1203 DebugInfo info = new DebugInfo ();
1204 info.max_il_offset = res.ReadInt ();
1205 info.filename = res.ReadString ();
1207 int n_il_offsets = res.ReadInt ();
1208 info.il_offsets = new int [n_il_offsets];
1209 info.line_numbers = new int [n_il_offsets];
1210 for (int i = 0; i < n_il_offsets; ++i) {
1211 info.il_offsets [i] = res.ReadInt ();
1212 info.line_numbers [i] = res.ReadInt ();
1215 return info;
1218 public ParamInfo Method_GetParamInfo (long id) {
1219 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_PARAM_INFO, new PacketWriter ().WriteId (id));
1221 ParamInfo info = new ParamInfo ();
1222 info.call_conv = res.ReadInt ();
1223 info.param_count = res.ReadInt ();
1224 info.generic_param_count = res.ReadInt ();
1225 info.ret_type = res.ReadId ();
1226 info.param_types = new long [info.param_count];
1227 for (int i = 0; i < info.param_count; ++i)
1228 info.param_types [i] = res.ReadId ();
1229 info.param_names = new string [info.param_count];
1230 for (int i = 0; i < info.param_count; ++i)
1231 info.param_names [i] = res.ReadString ();
1233 return info;
1236 public LocalsInfo Method_GetLocalsInfo (long id) {
1237 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_LOCALS_INFO, new PacketWriter ().WriteId (id));
1239 LocalsInfo info = new LocalsInfo ();
1240 int nlocals = res.ReadInt ();
1241 info.types = new long [nlocals];
1242 for (int i = 0; i < nlocals; ++i)
1243 info.types [i] = res.ReadId ();
1244 info.names = new string [nlocals];
1245 for (int i = 0; i < nlocals; ++i)
1246 info.names [i] = res.ReadString ();
1247 info.live_range_start = new int [nlocals];
1248 info.live_range_end = new int [nlocals];
1249 for (int i = 0; i < nlocals; ++i) {
1250 info.live_range_start [i] = res.ReadInt ();
1251 info.live_range_end [i] = res.ReadInt ();
1254 return info;
1257 public MethodInfo Method_GetInfo (long id) {
1258 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_INFO, new PacketWriter ().WriteId (id));
1260 MethodInfo info = new MethodInfo ();
1261 info.attributes = res.ReadInt ();
1262 info.iattributes = res.ReadInt ();
1263 info.token = res.ReadInt ();
1265 return info;
1268 public MethodBodyInfo Method_GetBody (long id) {
1269 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_BODY, new PacketWriter ().WriteId (id));
1271 MethodBodyInfo info = new MethodBodyInfo ();
1272 info.il = new byte [res.ReadInt ()];
1273 for (int i = 0; i < info.il.Length; ++i)
1274 info.il [i] = (byte)res.ReadByte ();
1276 return info;
1279 public ResolvedToken Method_ResolveToken (long id, int token) {
1280 var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.RESOLVE_TOKEN, new PacketWriter ().WriteId (id).WriteInt (token));
1282 TokenType type = (TokenType)res.ReadByte ();
1283 switch (type) {
1284 case TokenType.STRING:
1285 return new ResolvedToken () { Type = type, Str = res.ReadString () };
1286 case TokenType.TYPE:
1287 case TokenType.METHOD:
1288 case TokenType.FIELD:
1289 return new ResolvedToken () { Type = type, Id = res.ReadId () };
1290 case TokenType.UNKNOWN:
1291 return new ResolvedToken () { Type = type };
1292 default:
1293 throw new NotImplementedException ();
1298 * THREAD
1301 public string Thread_GetName (long id) {
1302 return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
1305 public FrameInfo[] Thread_GetFrameInfo (long id, int start_frame, int length) {
1306 var res = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length));
1307 int count = res.ReadInt ();
1309 var frames = new FrameInfo [count];
1310 for (int i = 0; i < count; ++i) {
1311 frames [i].id = res.ReadInt ();
1312 frames [i].method = res.ReadId ();
1313 frames [i].il_offset = res.ReadInt ();
1314 frames [i].flags = (StackFrameFlags)res.ReadByte ();
1316 return frames;
1319 public int Thread_GetState (long id) {
1320 return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_STATE, new PacketWriter ().WriteId (id)).ReadInt ();
1323 public ThreadInfo Thread_GetInfo (long id) {
1324 PacketReader r = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_INFO, new PacketWriter ().WriteId (id));
1326 ThreadInfo res = new ThreadInfo () { is_thread_pool = r.ReadByte () > 0 ? true : false };
1328 return res;
1332 * MODULE
1335 public ModuleInfo Module_GetInfo (long id) {
1336 PacketReader r = SendReceive (CommandSet.MODULE, (int)CmdModule.GET_INFO, new PacketWriter ().WriteId (id));
1337 ModuleInfo info = new ModuleInfo { Name = r.ReadString (), ScopeName = r.ReadString (), FQName = r.ReadString (), Guid = r.ReadString (), Assembly = r.ReadId () };
1338 return info;
1342 * ASSEMBLY
1345 public string Assembly_GetLocation (long id) {
1346 return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_LOCATION, new PacketWriter ().WriteId (id)).ReadString ();
1349 public long Assembly_GetEntryPoint (long id) {
1350 return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_ENTRY_POINT, new PacketWriter ().WriteId (id)).ReadId ();
1353 public long Assembly_GetManifestModule (long id) {
1354 return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_MANIFEST_MODULE, new PacketWriter ().WriteId (id)).ReadId ();
1357 public long Assembly_GetObject (long id) {
1358 return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
1361 public long Assembly_GetType (long id, string name, bool ignoreCase) {
1362 return SendReceive (CommandSet.ASSEMBLY, (int)CmdAssembly.GET_TYPE, new PacketWriter ().WriteId (id).WriteString (name).WriteBool (ignoreCase)).ReadId ();
1366 * TYPE
1369 public TypeInfo Type_GetInfo (long id) {
1370 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_INFO, new PacketWriter ().WriteId (id));
1371 TypeInfo res = new TypeInfo ();
1373 res.ns = r.ReadString ();
1374 res.name = r.ReadString ();
1375 res.full_name = r.ReadString ();
1376 res.assembly = r.ReadId ();
1377 res.module = r.ReadId ();
1378 res.base_type = r.ReadId ();
1379 res.element_type = r.ReadId ();
1380 res.token = r.ReadInt ();
1381 res.rank = r.ReadByte ();
1382 res.attributes = r.ReadInt ();
1383 int b = r.ReadByte ();
1384 res.is_byref = (b & 1) != 0;
1385 res.is_pointer = (b & 2) != 0;
1386 res.is_primitive = (b & 4) != 0;
1387 res.is_valuetype = (b & 8) != 0;
1389 int nested_len = r.ReadInt ();
1390 res.nested = new long [nested_len];
1391 for (int i = 0; i < nested_len; ++i)
1392 res.nested [i] = r.ReadId ();
1394 return res;
1397 public long[] Type_GetMethods (long id) {
1398 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_METHODS, new PacketWriter ().WriteId (id));
1400 int n = r.ReadInt ();
1401 long[] res = new long [n];
1402 for (int i = 0; i < n; ++i)
1403 res [i] = r.ReadId ();
1404 return res;
1407 public long[] Type_GetFields (long id, out string[] names, out long[] types, out int[] attrs) {
1408 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_FIELDS, new PacketWriter ().WriteId (id));
1410 int n = r.ReadInt ();
1411 long[] res = new long [n];
1412 names = new string [n];
1413 types = new long [n];
1414 attrs = new int [n];
1415 for (int i = 0; i < n; ++i) {
1416 res [i] = r.ReadId ();
1417 names [i] = r.ReadString ();
1418 types [i] = r.ReadId ();
1419 attrs [i] = r.ReadInt ();
1421 return res;
1424 public PropInfo[] Type_GetProperties (long id) {
1425 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_PROPERTIES, new PacketWriter ().WriteId (id));
1427 int n = r.ReadInt ();
1428 PropInfo[] res = new PropInfo [n];
1429 for (int i = 0; i < n; ++i) {
1430 res [i] = new PropInfo ();
1431 res [i].id = r.ReadId ();
1432 res [i].name = r.ReadString ();
1433 res [i].get_method = r.ReadId ();
1434 res [i].set_method = r.ReadId ();
1435 res [i].attrs = r.ReadInt ();
1438 return res;
1441 public long Type_GetObject (long id) {
1442 return SendReceive (CommandSet.TYPE, (int)CmdType.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
1445 public ValueImpl[] Type_GetValues (long id, long[] fields) {
1446 int len = fields.Length;
1447 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
1449 ValueImpl[] res = new ValueImpl [len];
1450 for (int i = 0; i < len; ++i)
1451 res [i] = r.ReadValue ();
1452 return res;
1455 public void Type_SetValues (long id, long[] fields, ValueImpl[] values) {
1456 SendReceive (CommandSet.TYPE, (int)CmdType.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (fields.Length).WriteIds (fields).WriteValues (values));
1459 public string[] Type_GetSourceFiles (long id) {
1460 var r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_SOURCE_FILES, new PacketWriter ().WriteId (id));
1461 int len = r.ReadInt ();
1462 string[] res = new string [len];
1463 for (int i = 0; i < len; ++i)
1464 res [i] = r.ReadString ();
1465 return res;
1468 public bool Type_IsAssignableFrom (long id, long c_id) {
1469 return SendReceive (CommandSet.TYPE, (int)CmdType.IS_ASSIGNABLE_FROM, new PacketWriter ().WriteId (id).WriteId (c_id)).ReadByte () > 0;
1472 public CattrInfo[] Type_GetCustomAttributes (long id, long attr_type_id, bool inherit) {
1473 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_CATTRS, new PacketWriter ().WriteId (id).WriteId (attr_type_id));
1474 return ReadCattrs (r);
1477 public CattrInfo[] Type_GetFieldCustomAttributes (long id, long field_id, long attr_type_id, bool inherit) {
1478 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_FIELD_CATTRS, new PacketWriter ().WriteId (id).WriteId (field_id).WriteId (attr_type_id));
1479 return ReadCattrs (r);
1482 public CattrInfo[] Type_GetPropertyCustomAttributes (long id, long field_id, long attr_type_id, bool inherit) {
1483 PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_PROPERTY_CATTRS, new PacketWriter ().WriteId (id).WriteId (field_id).WriteId (attr_type_id));
1484 return ReadCattrs (r);
1488 * EVENTS
1491 public int EnableEvent (EventType etype, SuspendPolicy suspend_policy, List<Modifier> mods) {
1492 var w = new PacketWriter ().WriteByte ((byte)etype).WriteByte ((byte)suspend_policy);
1493 if (mods != null) {
1494 if (mods.Count > 255)
1495 throw new NotImplementedException ();
1496 w.WriteByte ((byte)mods.Count);
1497 foreach (Modifier mod in mods) {
1498 if (mod is CountModifier) {
1499 w.WriteByte ((byte)ModifierKind.COUNT);
1500 w.WriteInt ((mod as CountModifier).Count);
1501 } else if (mod is LocationModifier) {
1502 w.WriteByte ((byte)ModifierKind.LOCATION_ONLY);
1503 w.WriteId ((mod as LocationModifier).Method);
1504 w.WriteLong ((mod as LocationModifier).Location);
1505 } else if (mod is StepModifier) {
1506 w.WriteByte ((byte)ModifierKind.STEP);
1507 w.WriteId ((mod as StepModifier).Thread);
1508 w.WriteInt ((mod as StepModifier).Size);
1509 w.WriteInt ((mod as StepModifier).Depth);
1510 } else if (mod is ThreadModifier) {
1511 w.WriteByte ((byte)ModifierKind.THREAD_ONLY);
1512 w.WriteId ((mod as ThreadModifier).Thread);
1513 } else if (mod is ExceptionModifier) {
1514 w.WriteByte ((byte)ModifierKind.EXCEPTION_ONLY);
1515 w.WriteId ((mod as ExceptionModifier).Type);
1516 } else if (mod is AssemblyModifier) {
1517 w.WriteByte ((byte)ModifierKind.ASSEMBLY_ONLY);
1518 var amod = (mod as AssemblyModifier);
1519 w.WriteInt (amod.Assemblies.Length);
1520 foreach (var id in amod.Assemblies)
1521 w.WriteId (id);
1522 } else {
1523 throw new NotImplementedException ();
1526 } else {
1527 w.WriteByte (0);
1529 return SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.SET, w).ReadInt ();
1532 public void ClearEventRequest (EventType etype, int req_id) {
1533 SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR, new PacketWriter ().WriteByte ((byte)etype).WriteInt (req_id));
1536 public void ClearAllBreakpoints () {
1537 SendReceive (CommandSet.EVENT_REQUEST, (int)CmdEventRequest.CLEAR_ALL_BREAKPOINTS, new PacketWriter ());
1541 * STACK FRAME
1543 public ValueImpl StackFrame_GetThis (long thread_id, long id) {
1544 PacketReader r = SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.GET_THIS, new PacketWriter ().WriteId (thread_id).WriteId (id));
1545 return r.ReadValue ();
1548 public ValueImpl[] StackFrame_GetValues (long thread_id, long id, int[] pos) {
1549 /* pos < 0 -> argument at pos (-pos) - 1 */
1550 /* pos >= 0 -> local at pos */
1551 int len = pos.Length;
1552 PacketReader r = SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.GET_VALUES, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteInt (len).WriteInts (pos));
1554 ValueImpl[] res = new ValueImpl [len];
1555 for (int i = 0; i < len; ++i)
1556 res [i] = r.ReadValue ();
1557 return res;
1560 public void StackFrame_SetValues (long thread_id, long id, int[] pos, ValueImpl[] values) {
1561 /* pos < 0 -> argument at pos (-pos) - 1 */
1562 /* pos >= 0 -> local at pos */
1563 int len = pos.Length;
1564 SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.SET_VALUES, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteInt (len).WriteInts (pos).WriteValues (values));
1568 * ARRAYS
1570 public int[] Array_GetLength (long id, out int rank, out int[] lower_bounds) {
1571 var r = SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.GET_LENGTH, new PacketWriter ().WriteId (id));
1572 rank = r.ReadInt ();
1573 int[] res = new int [rank];
1574 lower_bounds = new int [rank];
1575 for (int i = 0; i < rank; ++i) {
1576 res [i] = r.ReadInt ();
1577 lower_bounds [i] = r.ReadInt ();
1579 return res;
1582 public ValueImpl[] Array_GetValues (long id, int index, int len) {
1583 var r = SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (index).WriteInt (len));
1584 ValueImpl[] res = new ValueImpl [len];
1585 for (int i = 0; i < len; ++i)
1586 res [i] = r.ReadValue ();
1587 return res;
1590 public void Array_SetValues (long id, int index, ValueImpl[] values) {
1591 SendReceive (CommandSet.ARRAY_REF, (int)CmdArrayRef.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (index).WriteInt (values.Length).WriteValues (values));
1595 * STRINGS
1597 public string String_GetValue (long id) {
1598 return SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_VALUE, new PacketWriter ().WriteId (id)).ReadString ();
1602 * OBJECTS
1604 public long Object_GetType (long id) {
1605 return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_TYPE, new PacketWriter ().WriteId (id)).ReadId ();
1608 public long Object_GetDomain (long id) {
1609 return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_DOMAIN, new PacketWriter ().WriteId (id)).ReadId ();
1612 public ValueImpl[] Object_GetValues (long id, long[] fields) {
1613 int len = fields.Length;
1614 PacketReader r = SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
1616 ValueImpl[] res = new ValueImpl [len];
1617 for (int i = 0; i < len; ++i)
1618 res [i] = r.ReadValue ();
1619 return res;
1622 public void Object_SetValues (long id, long[] fields, ValueImpl[] values) {
1623 SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.SET_VALUES, new PacketWriter ().WriteId (id).WriteInt (fields.Length).WriteIds (fields).WriteValues (values));
1626 public bool Object_IsCollected (long id) {
1627 return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.IS_COLLECTED, new PacketWriter ().WriteId (id)).ReadInt () == 1;
1630 public long Object_GetAddress (long id) {
1631 return SendReceive (CommandSet.OBJECT_REF, (int)CmdObjectRef.GET_ADDRESS, new PacketWriter ().WriteId (id)).ReadLong ();
1636 /* This is the interface exposed by the debugger towards the debugger agent */
1637 interface IEventHandler
1639 void VMStart (int req_id, long thread_id, string vm_uri);
1641 void VMDeath (int req_id, long thread_id, string vm_uri);
1643 void VMDisconnect (int req_id, long thread_id, string vm_uri);
1645 void ThreadStart (int req_id, long thread_id, long id);
1647 void ThreadDeath (int req_id, long thread_id, long id);
1649 void AssemblyLoad (int req_id, long thread_id, long id);
1651 void TypeLoad (int req_id, long thread_id, long id);
1653 void MethodEntry (int req_id, long thread_id, long id);
1655 void MethodExit (int req_id, long thread_id, long id);
1657 void Breakpoint (int req_id, long thread_id, long method_id, long loc);
1659 void Step (int req_id, long thread_id, long method_id, long loc);
1661 void Exception (int req_id, long thread_id, long exc_id, long loc);
1663 void AppDomainCreate (int req_id, long thread_id, long id);
1665 void AppDomainUnload (int req_id, long thread_id, long id);