Revert "Revert "Merge branch 'master' of https://github.com/mono/mono""
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / Connection.cs
index 1192cfb2223e5ca0074d044b3e44ef5ba649fe4b..60b7e2c384ca72c99479b4d5d4ce6aa55aa807ab 100644 (file)
@@ -93,6 +93,7 @@ namespace Mono.Debugger.Soft
                public long catch_type_id;
        }
 
+       [Flags]
        enum ExceptionClauseFlags {
                None = 0x0,
                Filter = 0x1,
@@ -149,6 +150,7 @@ namespace Mono.Debugger.Soft
                VALUE_TYPE_ID_TYPE = 0xf1
        }
 
+       [Flags]
        enum InvokeFlags {
                NONE = 0x0,
                DISABLE_BREAKPOINTS = 0x1,
@@ -212,6 +214,12 @@ namespace Mono.Debugger.Soft
                public long Assembly;
        }               
 
+       class FieldMirrorInfo {
+               public string Name;
+               public long Parent, TypeId;
+               public int Attrs;
+       }
+
        enum TokenType {
                STRING = 0,
                TYPE = 1,
@@ -220,6 +228,7 @@ namespace Mono.Debugger.Soft
                UNKNOWN = 4
        }
 
+       [Flags]
        enum StackFrameFlags {
                NONE = 0,
                DEBUGGER_INVOKE = 1,
@@ -285,6 +294,9 @@ namespace Mono.Debugger.Soft
                public bool Uncaught {
                        get; set;
                }
+               public bool Subclasses {
+                       get; set;
+               }
        }
 
        class AssemblyModifier : Modifier {
@@ -342,6 +354,10 @@ namespace Mono.Debugger.Soft
                        get; set;
                }
 
+               public int ExitCode {
+                       get; set;
+               }
+
                public EventInfo (EventType type, int req_id) {
                        EventType = type;
                        ReqId = req_id;
@@ -395,7 +411,7 @@ namespace Mono.Debugger.Soft
                 * with newer runtimes, and vice versa.
                 */
                internal const int MAJOR_VERSION = 2;
-               internal const int MINOR_VERSION = 19;
+               internal const int MINOR_VERSION = 30;
 
                enum WPSuspendPolicy {
                        NONE = 0,
@@ -416,6 +432,7 @@ namespace Mono.Debugger.Soft
                        METHOD = 22,
                        TYPE = 23,
                        MODULE = 24,
+                       FIELD = 25,
                        EVENT = 64
                }
 
@@ -462,7 +479,8 @@ namespace Mono.Debugger.Soft
                        ABORT_INVOKE = 9,
                        SET_KEEPALIVE = 10,
                        GET_TYPES_FOR_SOURCE_FILE = 11,
-                       GET_TYPES = 12
+                       GET_TYPES = 12,
+                       INVOKE_METHODS = 13
                }
 
                enum CmdEvent {
@@ -477,7 +495,8 @@ namespace Mono.Debugger.Soft
                        /* FIXME: Merge into GET_INFO when the major protocol version is increased */
                        GET_ID = 5,
                        /* Ditto */
-                       GET_TID = 6
+                       GET_TID = 6,
+                       SET_IP = 7
                }
 
                enum CmdEventRequest {
@@ -517,7 +536,9 @@ namespace Mono.Debugger.Soft
                        GET_LOCALS_INFO = 5,
                        GET_INFO = 6,
                        GET_BODY = 7,
-                       RESOLVE_TOKEN = 8
+                       RESOLVE_TOKEN = 8,
+                       GET_CATTRS = 9,
+                       MAKE_GENERIC_METHOD = 10
                }
 
                enum CmdType {
@@ -539,9 +560,15 @@ namespace Mono.Debugger.Soft
                        GET_VALUES_2 = 14,
                        CMD_TYPE_GET_METHODS_BY_NAME_FLAGS = 15,
                        GET_INTERFACES = 16,
-                       GET_INTERFACE_MAP = 17
+                       GET_INTERFACE_MAP = 17,
+                       IS_INITIALIZED = 18
+               }
+
+               enum CmdField {
+                       GET_INFO = 1
                }
 
+               [Flags]
                enum BindingFlagsExtensions {
                        BINDING_FLAGS_IGNORE_CASE = 0x70000000,
                }
@@ -1021,6 +1048,7 @@ namespace Mono.Debugger.Soft
                Thread receiver_thread;
                Dictionary<int, byte[]> reply_packets;
                Dictionary<int, ReplyCallback> reply_cbs;
+               Dictionary<int, int> reply_cb_counts;
                object reply_packets_monitor;
 
                internal event EventHandler<ErrorHandlerEventArgs> ErrorHandler;
@@ -1029,6 +1057,7 @@ namespace Mono.Debugger.Soft
                        closed = false;
                        reply_packets = new Dictionary<int, byte[]> ();
                        reply_cbs = new Dictionary<int, ReplyCallback> ();
+                       reply_cb_counts = new Dictionary<int, int> ();
                        reply_packets_monitor = new Object ();
                }
                
@@ -1071,6 +1100,8 @@ namespace Mono.Debugger.Soft
                        TransportSend (buf, 0, buf.Length);
 
                        receiver_thread = new Thread (new ThreadStart (receiver_thread_main));
+                       receiver_thread.Name = "SDB Receiver";
+                       receiver_thread.IsBackground = true;
                        receiver_thread.Start ();
 
                        Version = VM_GetVersion ();
@@ -1181,6 +1212,13 @@ namespace Mono.Debugger.Soft
                                                if (cb == null) {
                                                        reply_packets [id] = packet;
                                                        Monitor.PulseAll (reply_packets_monitor);
+                                               } else {
+                                                       int c = reply_cb_counts [id];
+                                                       c --;
+                                                       if (c == 0) {
+                                                               reply_cbs.Remove (id);
+                                                               reply_cb_counts.Remove (id);
+                                                       }
                                                }
                                        }
 
@@ -1203,82 +1241,71 @@ namespace Mono.Debugger.Soft
 
                                                        EventType etype = (EventType)kind;
 
+                                                       long thread_id = r.ReadId ();
                                                        if (kind == EventKind.VM_START) {
-                                                               long thread_id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id };
                                                                //EventHandler.VMStart (req_id, thread_id, null);
                                                        } else if (kind == EventKind.VM_DEATH) {
+                                                               int exit_code = 0;
+                                                               if (Version.AtLeast (2, 27))
+                                                                       exit_code = r.ReadInt ();
                                                                //EventHandler.VMDeath (req_id, 0, null);
-                                                               events [i] = new EventInfo (etype, req_id) { };
+                                                               events [i] = new EventInfo (etype, req_id) { ExitCode = exit_code };
                                                        } else if (kind == EventKind.THREAD_START) {
-                                                               long thread_id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
                                                                //EventHandler.ThreadStart (req_id, thread_id, thread_id);
                                                        } else if (kind == EventKind.THREAD_DEATH) {
-                                                               long thread_id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
                                                                //EventHandler.ThreadDeath (req_id, thread_id, thread_id);
                                                        } else if (kind == EventKind.ASSEMBLY_LOAD) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.AssemblyLoad (req_id, thread_id, id);
                                                        } else if (kind == EventKind.ASSEMBLY_UNLOAD) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.AssemblyUnload (req_id, thread_id, id);
                                                        } else if (kind == EventKind.TYPE_LOAD) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.TypeLoad (req_id, thread_id, id);
                                                        } else if (kind == EventKind.METHOD_ENTRY) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.MethodEntry (req_id, thread_id, id);
                                                        } else if (kind == EventKind.METHOD_EXIT) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.MethodExit (req_id, thread_id, id);
                                                        } else if (kind == EventKind.BREAKPOINT) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                long loc = r.ReadLong ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
                                                                //EventHandler.Breakpoint (req_id, thread_id, id, loc);
                                                        } else if (kind == EventKind.STEP) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                long loc = r.ReadLong ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
                                                                //EventHandler.Step (req_id, thread_id, id, loc);
                                                        } else if (kind == EventKind.EXCEPTION) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                long loc = 0; // FIXME
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
                                                                //EventHandler.Exception (req_id, thread_id, id, loc);
                                                        } else if (kind == EventKind.APPDOMAIN_CREATE) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.AppDomainCreate (req_id, thread_id, id);
                                                        } else if (kind == EventKind.APPDOMAIN_UNLOAD) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = r.ReadId ();
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
                                                                //EventHandler.AppDomainUnload (req_id, thread_id, id);
                                                        } else if (kind == EventKind.USER_BREAK) {
-                                                               long thread_id = r.ReadId ();
                                                                long id = 0;
                                                                long loc = 0;
                                                                events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
                                                                //EventHandler.Exception (req_id, thread_id, id, loc);
                                                        } else if (kind == EventKind.USER_LOG) {
-                                                               long thread_id = r.ReadId ();
                                                                int level = r.ReadInt ();
                                                                string category = r.ReadString ();
                                                                string message = r.ReadString ();
@@ -1342,6 +1369,9 @@ namespace Mono.Debugger.Soft
                        case CommandSet.MODULE:
                                cmd = ((CmdModule)command).ToString ();
                                break;
+                       case CommandSet.FIELD:
+                               cmd = ((CmdField)command).ToString ();
+                               break;
                        case CommandSet.EVENT:
                                cmd = ((CmdEvent)command).ToString ();
                                break;
@@ -1368,7 +1398,7 @@ namespace Mono.Debugger.Soft
                }
 
                /* Send a request and call cb when a result is received */
-               int Send (CommandSet command_set, int command, PacketWriter packet, Action<PacketReader> cb) {
+               int Send (CommandSet command_set, int command, PacketWriter packet, Action<PacketReader> cb, int count) {
                        int id = IdGenerator;
 
                        Stopwatch watch = null;
@@ -1389,6 +1419,7 @@ namespace Mono.Debugger.Soft
                                        PacketReader r = new PacketReader (p);
                                        cb.BeginInvoke (r, null, null);
                                };
+                               reply_cb_counts [id] = count;
                        }
 
                        WritePacket (encoded_packet);
@@ -1581,7 +1612,38 @@ namespace Mono.Debugger.Soft
 
                                                callback (v, exc, 0, state);
                                        }
-                               });
+                               }, 1);
+               }
+
+               internal int VM_BeginInvokeMethods (long thread, long[] methods, ValueImpl this_arg, List<ValueImpl[]> arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
+                       // FIXME: Merge this with INVOKE_METHOD
+                       var w = new PacketWriter ();
+                       w.WriteId (thread);
+                       w.WriteInt ((int)flags);
+                       w.WriteInt (methods.Length);
+                       for (int i = 0; i < methods.Length; ++i) {
+                               w.WriteId (methods [i]);
+                               w.WriteValue (this_arg);
+                               w.WriteInt (arguments [i].Length);
+                               w.WriteValues (arguments [i]);
+                       }
+                       return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHODS, w, delegate (PacketReader r) {
+                                       ValueImpl v, exc;
+
+                                       if (r.ErrorCode != 0) {
+                                               callback (null, null, (ErrorCode)r.ErrorCode, state);
+                                       } else {
+                                               if (r.ReadByte () == 0) {
+                                                       exc = r.ReadValue ();
+                                                       v = null;
+                                               } else {
+                                                       v = r.ReadValue ();
+                                                       exc = null;
+                                               }
+
+                                               callback (v, exc, 0, state);
+                                       }
+                               }, methods.Length);
                }
 
                internal void VM_AbortInvoke (long thread, int id)
@@ -1824,6 +1886,16 @@ namespace Mono.Debugger.Soft
                        }
                }
 
+               internal CattrInfo[] Method_GetCustomAttributes (long id, long attr_type_id, bool inherit) {
+                       PacketReader r = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_CATTRS, new PacketWriter ().WriteId (id).WriteId (attr_type_id));
+                       return ReadCattrs (r);
+               }
+
+               internal long Method_MakeGenericMethod (long id, long[] args) {
+                       PacketReader r = SendReceive (CommandSet.METHOD, (int)CmdMethod.MAKE_GENERIC_METHOD, new PacketWriter ().WriteId (id).WriteInt (args.Length).WriteIds (args));
+                       return r.ReadId ();
+               }
+
                /*
                 * THREAD
                 */
@@ -1869,6 +1941,10 @@ namespace Mono.Debugger.Soft
                        return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_TID, new PacketWriter ().WriteId (id)).ReadLong ();
                }
 
+               internal void Thread_SetIP (long id, long method_id, long il_offset) {
+                       SendReceive (CommandSet.THREAD, (int)CmdThread.SET_IP, new PacketWriter ().WriteId (id).WriteId (method_id).WriteLong (il_offset));
+               }
+
                /*
                 * MODULE
                 */
@@ -2073,6 +2149,21 @@ namespace Mono.Debugger.Soft
                        return res;
                }
 
+               internal bool Type_IsInitialized (long id) {
+                       PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.IS_INITIALIZED, new PacketWriter ().WriteId (id));
+                       return r.ReadInt () == 1;
+               }
+
+               /*
+                * FIELD
+                */
+
+               internal FieldMirrorInfo Field_GetInfo (long id) {
+                       PacketReader r = SendReceive (CommandSet.FIELD, (int)CmdField.GET_INFO, new PacketWriter ().WriteId (id));
+                       FieldMirrorInfo info = new FieldMirrorInfo { Name = r.ReadString (), Parent = r.ReadId (), TypeId = r.ReadId (), Attrs = r.ReadInt () };
+                       return info;
+               }
+
                /*
                 * EVENTS
                 */
@@ -2112,6 +2203,11 @@ namespace Mono.Debugger.Soft
                                                } else if (!em.Caught || !em.Uncaught) {
                                                        throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
                                                }
+                                               if (Version.MajorVersion > 2 || Version.MinorVersion > 24) {
+                                                       w.WriteBool (em.Subclasses);
+                                               } else if (!em.Subclasses) {
+                                                       throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
+                                               }
                                        } else if (mod is AssemblyModifier) {
                                                w.WriteByte ((byte)ModifierKind.ASSEMBLY_ONLY);
                                                var amod = (mod as AssemblyModifier);
@@ -2265,6 +2361,8 @@ namespace Mono.Debugger.Soft
 
                public void ForceDisconnect ()
                {
+                       closed = true;
+                       disconnected = true;
                        TransportClose ();
                }
        }