Merge pull request #3609 from xmcclure/checked-imageset
[mono.git] / mcs / class / Mono.Debugger.Soft / Mono.Debugger.Soft / Connection.cs
index 6d196aabbab374ff4ff9f70ce974cd3e7c9210eb..a5b902db57322eaff402889d0becf162902b735b 100644 (file)
@@ -117,6 +117,8 @@ namespace Mono.Debugger.Soft
                public string[] names;
                public int[] live_range_start;
                public int[] live_range_end;
+               public int[] scopes_start;
+               public int[] scopes_end;
        }
 
        struct PropInfo {
@@ -155,9 +157,12 @@ namespace Mono.Debugger.Soft
 
        [Flags]
        enum InvokeFlags {
-               NONE = 0x0,
-               DISABLE_BREAKPOINTS = 0x1,
-               SINGLE_THREADED = 0x2
+               NONE = 0,
+               DISABLE_BREAKPOINTS = 1,
+               SINGLE_THREADED = 2,
+               OUT_THIS = 4,
+               OUT_ARGS = 8,
+               VIRTUAL = 16,
        }
 
        enum ElementType {
@@ -379,7 +384,8 @@ namespace Mono.Debugger.Soft
                ERR_UNLOADED = 103,
                ERR_NO_INVOCATION = 104,
                ABSENT_INFORMATION = 105,
-               NO_SEQ_POINT_AT_IL_OFFSET = 106
+               NO_SEQ_POINT_AT_IL_OFFSET = 106,
+               INVOKE_ABORTED = 107
        }
 
        public class ErrorHandlerEventArgs : EventArgs {
@@ -404,8 +410,7 @@ namespace Mono.Debugger.Soft
 
                static readonly bool EnableConnectionLogging = !String.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONO_SDB_LOG"));
                static int ConnectionId;
-               readonly StreamWriter LoggingStream = EnableConnectionLogging ? 
-                       new StreamWriter (string.Format ("/tmp/sdb_conn_log_{0}", ConnectionId++), false) : null;
+               readonly StreamWriter LoggingStream;
 
                /*
                 * Th version of the wire-protocol implemented by the library. The library
@@ -415,7 +420,7 @@ namespace Mono.Debugger.Soft
                 * with newer runtimes, and vice versa.
                 */
                internal const int MAJOR_VERSION = 2;
-               internal const int MINOR_VERSION = 34;
+               internal const int MINOR_VERSION = 44;
 
                enum WPSuspendPolicy {
                        NONE = 0,
@@ -583,7 +588,9 @@ namespace Mono.Debugger.Soft
                enum CmdStackFrame {
                        GET_VALUES = 1,
                        GET_THIS = 2,
-                       SET_VALUES = 3
+                       SET_VALUES = 3,
+                       GET_DOMAIN = 4,
+                       SET_THIS = 5,
                }
 
                enum CmdArrayRef {
@@ -798,6 +805,13 @@ namespace Mono.Debugger.Soft
                                return res;
                        }
 
+                       public string ReadUTF16String () {
+                               int len = decode_int (packet, ref offset);
+                               string res = new String (Encoding.Unicode.GetChars (packet, offset, len));
+                               offset += len;
+                               return res;
+                       }
+
                        public ValueImpl ReadValue () {
                                ElementType etype = (ElementType)ReadByte ();
 
@@ -1068,6 +1082,19 @@ namespace Mono.Debugger.Soft
                        reply_cbs = new Dictionary<int, ReplyCallback> ();
                        reply_cb_counts = new Dictionary<int, int> ();
                        reply_packets_monitor = new Object ();
+                       if (EnableConnectionLogging) {
+                               var path = Environment.GetEnvironmentVariable ("MONO_SDB_LOG");
+                               if (path.Contains ("{0}")) {
+                                       //C:\SomeDir\sdbLog{0}.txt -> C:\SomeDir\sdbLog1.txt
+                                       LoggingStream = new StreamWriter (string.Format (path, ConnectionId++), false);
+                               } else if (Path.HasExtension (path)) {
+                                       //C:\SomeDir\sdbLog.txt -> C:\SomeDir\sdbLog1.txt
+                                       LoggingStream = new StreamWriter (Path.GetDirectoryName (path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension (path) + ConnectionId++ + "." + Path.GetExtension (path), false);
+                               } else {
+                                       //C:\SomeDir\sdbLog -> C:\SomeDir\sdbLog1
+                                       LoggingStream = new StreamWriter (path + ConnectionId++, false);
+                               }
+                       }
                }
                
                protected abstract int TransportReceive (byte[] buf, int buf_offset, int len);
@@ -1200,6 +1227,8 @@ namespace Mono.Debugger.Soft
 
                bool disconnected;
 
+               internal ManualResetEvent DisconnectedEvent = new ManualResetEvent (false);
+
                void receiver_thread_main () {
                        while (!closed) {
                                try {
@@ -1216,6 +1245,7 @@ namespace Mono.Debugger.Soft
 
                        lock (reply_packets_monitor) {
                                disconnected = true;
+                               DisconnectedEvent.Set ();
                                Monitor.PulseAll (reply_packets_monitor);
                                TransportClose ();
                        }
@@ -1432,18 +1462,18 @@ namespace Mono.Debugger.Soft
                //
                public void StartBuffering () {
                        buffer_packets = true;
-                       if (Version.AtLeast (3, 34))
+                       if (Version.AtLeast (2, 34))
                                VM_StartBuffering ();
                }
 
                public void StopBuffering () {
-                       if (Version.AtLeast (3, 34))
+                       if (Version.AtLeast (2, 34))
                                VM_StopBuffering ();
                        buffer_packets = false;
 
                        WritePackets (buffered_packets);
                        if (EnableConnectionLogging) {
-                               LoggingStream.WriteLine (String.Format ("Sent {1} packets.", buffered_packets.Count));
+                               LoggingStream.WriteLine (String.Format ("Sent {0} packets.", buffered_packets.Count));
                                LoggingStream.Flush ();
                        }
                        buffered_packets.Clear ();
@@ -1619,13 +1649,14 @@ namespace Mono.Debugger.Soft
                        SendReceive (CommandSet.VM, (int)CmdVM.SET_PROTOCOL_VERSION, new PacketWriter ().WriteInt (major).WriteInt (minor));
                }
 
-               internal long[] VM_GetThreads () {
-                       var res = SendReceive (CommandSet.VM, (int)CmdVM.ALL_THREADS, null);
-                       int len = res.ReadInt ();
-                       long[] arr = new long [len];
-                       for (int i = 0; i < len; ++i)
-                               arr [i] = res.ReadId ();
-                       return arr;
+               internal void VM_GetThreads (Action<long[]> resultCallaback) {
+                       Send (CommandSet.VM, (int)CmdVM.ALL_THREADS, null, (res) => {
+                               int len = res.ReadInt ();
+                               long[] arr = new long [len];
+                               for (int i = 0; i < len; ++i)
+                                       arr [i] = res.ReadId ();
+                               resultCallaback(arr);
+                       }, 1);
                }
 
                internal void VM_Suspend () {
@@ -1655,24 +1686,39 @@ namespace Mono.Debugger.Soft
                        }
                }
 
-               internal delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ErrorCode error, object state);
+               internal delegate void InvokeMethodCallback (ValueImpl v, ValueImpl exc, ValueImpl out_this, ValueImpl[] out_args, ErrorCode error, object state);
+
+               void read_invoke_res (PacketReader r, out ValueImpl v, out ValueImpl exc, out ValueImpl out_this, out ValueImpl[] out_args) {
+                       int resflags = r.ReadByte ();
+                       v = null;
+                       exc = null;
+                       out_this = null;
+                       out_args = null;
+                       if (resflags == 0) {
+                               exc = r.ReadValue ();
+                       } else {
+                               v = r.ReadValue ();
+                               if ((resflags & 2) != 0)
+                                       out_this = r.ReadValue ();
+                               if ((resflags & 4) != 0) {
+                                       int nargs = r.ReadInt ();
+                                       out_args = new ValueImpl [nargs];
+                                       for (int i = 0; i < nargs; ++i)
+                                               out_args [i] = r.ReadValue ();
+                               }
+                       }
+               }
 
                internal int VM_BeginInvokeMethod (long thread, long method, ValueImpl this_arg, ValueImpl[] arguments, InvokeFlags flags, InvokeMethodCallback callback, object state) {
                        return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHOD, new PacketWriter ().WriteId (thread).WriteInt ((int)flags).WriteId (method).WriteValue (this_arg).WriteInt (arguments.Length).WriteValues (arguments), delegate (PacketReader r) {
-                                       ValueImpl v, exc;
+                                       ValueImpl v, exc, out_this = null;
+                                       ValueImpl[] out_args = null;
 
                                        if (r.ErrorCode != 0) {
-                                               callback (null, null, (ErrorCode)r.ErrorCode, state);
+                                               callback (null, null, 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);
+                                               read_invoke_res (r, out v, out exc, out out_this, out out_args);
+                                               callback (v, exc, out_this, out_args, 0, state);
                                        }
                                }, 1);
                }
@@ -1690,20 +1736,14 @@ namespace Mono.Debugger.Soft
                                w.WriteValues (arguments [i]);
                        }
                        return Send (CommandSet.VM, (int)CmdVM.INVOKE_METHODS, w, delegate (PacketReader r) {
-                                       ValueImpl v, exc;
+                                       ValueImpl v, exc, out_this = null;
+                                       ValueImpl[] out_args = null;
 
                                        if (r.ErrorCode != 0) {
-                                               callback (null, null, (ErrorCode)r.ErrorCode, state);
+                                               callback (null, null, 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);
+                                               read_invoke_res (r, out v, out exc, out out_this, out out_args);
+                                               callback (v, exc, out_this, out_args, 0, state);
                                        }
                                }, methods.Length);
                }
@@ -1873,6 +1913,19 @@ namespace Mono.Debugger.Soft
                        var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_LOCALS_INFO, new PacketWriter ().WriteId (id));
 
                        LocalsInfo info = new LocalsInfo ();
+
+                       if (Version.AtLeast (2, 43)) {
+                               int nscopes = res.ReadInt ();
+                               info.scopes_start = new int [nscopes];
+                               info.scopes_end = new int [nscopes];
+                               int last_start = 0;
+                               for (int i = 0; i < nscopes; ++i) {
+                                       info.scopes_start [i] = last_start + res.ReadInt ();
+                                       info.scopes_end [i] = info.scopes_start [i] + res.ReadInt ();
+                                       last_start = info.scopes_start [i];
+                               }
+                       }
+
                        int nlocals = res.ReadInt ();
                        info.types = new long [nlocals];
                        for (int i = 0; i < nlocals; ++i)
@@ -1983,21 +2036,20 @@ namespace Mono.Debugger.Soft
                        return SendReceive (CommandSet.THREAD, (int)CmdThread.GET_NAME, new PacketWriter ().WriteId (id)).ReadString ();
                }
 
-               internal FrameInfo[] Thread_GetFrameInfo (long id, int start_frame, int length) {
-                       var res = SendReceive (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length));
-                       int count = res.ReadInt ();
-
-                       var frames = new FrameInfo [count];
-                       for (int i = 0; i < count; ++i) {
-                               var f = new FrameInfo ();
-                               f.id = res.ReadInt ();
-                               f.method = res.ReadId ();
-                               f.il_offset = res.ReadInt ();
-                               f.flags = (StackFrameFlags)res.ReadByte ();
-                               frames [i] = f;
-                       }
-
-                       return frames;
+               internal void Thread_GetFrameInfo (long id, int start_frame, int length, Action<FrameInfo[]> resultCallaback) {
+                       Send (CommandSet.THREAD, (int)CmdThread.GET_FRAME_INFO, new PacketWriter ().WriteId (id).WriteInt (start_frame).WriteInt (length), (res) => {
+                               int count = res.ReadInt ();
+                               var frames = new FrameInfo[count];
+                               for (int i = 0; i < count; ++i) {
+                                       var f = new FrameInfo ();
+                                       f.id = res.ReadInt ();
+                                       f.method = res.ReadId ();
+                                       f.il_offset = res.ReadInt ();
+                                       f.flags = (StackFrameFlags)res.ReadByte ();
+                                       frames [i] = f;
+                               }
+                               resultCallaback (frames);
+                       }, 1);
                }
 
                internal int Thread_GetState (long id) {
@@ -2355,6 +2407,14 @@ namespace Mono.Debugger.Soft
                        SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.SET_VALUES, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteInt (len).WriteInts (pos).WriteValues (values));
                }
 
+               internal long StackFrame_GetDomain (long thread_id, long id) {
+                       return SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.GET_DOMAIN, new PacketWriter ().WriteId (thread_id).WriteId (id)).ReadId ();
+               }
+
+               internal void StackFrame_SetThis (long thread_id, long id, ValueImpl value) {
+                       SendReceive (CommandSet.STACK_FRAME, (int)CmdStackFrame.SET_THIS, new PacketWriter ().WriteId (thread_id).WriteId (id).WriteValue (value));
+               }
+
                /*
                 * ARRAYS
                 */
@@ -2386,7 +2446,16 @@ namespace Mono.Debugger.Soft
                 * STRINGS
                 */
                internal string String_GetValue (long id) {
-                       return SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_VALUE, new PacketWriter ().WriteId (id)).ReadString ();
+                       var r = SendReceive (CommandSet.STRING_REF, (int)CmdStringRef.GET_VALUE, new PacketWriter ().WriteId (id));
+
+                       bool is_utf16 = false;
+                       if (Version.AtLeast (2, 41))
+                               is_utf16 = r.ReadByte () == 1;
+
+                       if (is_utf16)
+                               return r.ReadUTF16String ();
+                       else
+                               return r.ReadString ();
                }                       
 
                internal int String_GetLength (long id) {
@@ -2447,6 +2516,7 @@ namespace Mono.Debugger.Soft
                {
                        closed = true;
                        disconnected = true;
+                       DisconnectedEvent.Set ();
                        TransportClose ();
                }
        }