diff options
author | Jeffrey Stedfast <jeff@xamarin.com> | 2012-09-19 02:11:59 +0400 |
---|---|---|
committer | Jeffrey Stedfast <jeff@xamarin.com> | 2012-09-19 02:16:24 +0400 |
commit | f3b63f67a07ca85078427f3c56e48dbb48764279 (patch) | |
tree | 04532d684b6ec997e844a576f48c9e64e9c319f5 /main/contrib | |
parent | e245c931087a122694a72829a7db44c411732fee (diff) |
[Mono.Debugger.Soft] Updated to get escaped disassembly strings
Diffstat (limited to 'main/contrib')
4 files changed, 176 insertions, 7 deletions
diff --git a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 942c08366c..be1a41ccbc 100644 --- a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -395,7 +395,7 @@ namespace Mono.Debugger.Soft * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 21; + internal const int MINOR_VERSION = 22; enum WPSuspendPolicy { NONE = 0, @@ -462,7 +462,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 { @@ -1022,6 +1023,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; @@ -1030,6 +1032,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 (); } @@ -1182,6 +1185,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); + } } } @@ -1369,7 +1379,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; @@ -1390,6 +1400,7 @@ namespace Mono.Debugger.Soft PacketReader r = new PacketReader (p); cb.BeginInvoke (r, null, null); }; + reply_cb_counts [id] = count; } WritePacket (encoded_packet); @@ -1582,7 +1593,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) diff --git a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs index c383005a0d..42ca3a27a5 100644 --- a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs +++ b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodBodyMirror.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Collections.Generic; using System.Text; using Mono.Cecil.Cil; @@ -56,8 +57,38 @@ namespace Mono.Debugger.Soft static OpCode [] OneByteOpCode = new OpCode [0xe0 + 1]; static OpCode [] TwoBytesOpCode = new OpCode [0x1e + 1]; + static string EscapeString (string text) + { + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < text.Length; i++) { + char c = text[i]; + string txt; + switch (c) { + case '"': txt = "\\\""; break; + case '\0': txt = @"\0"; break; + case '\\': txt = @"\\"; break; + case '\a': txt = @"\a"; break; + case '\b': txt = @"\b"; break; + case '\f': txt = @"\f"; break; + case '\v': txt = @"\v"; break; + case '\n': txt = @"\n"; break; + case '\r': txt = @"\r"; break; + case '\t': txt = @"\t"; break; + default: + if (char.GetUnicodeCategory (c) == UnicodeCategory.OtherNotAssigned) { + sb.AppendFormat ("\\u{0:x4}", (int) c); + } else { + sb.Append (c); + } + continue; + } + sb.Append (txt); + } + return sb.ToString (); + } + // Adapted from Cecil - List<ILInstruction> ReadCilBody (BinaryReader br, int code_size) + List<ILInstruction> ReadCilBody (BinaryReader br, int code_size) { long start = br.BaseStream.Position; ILInstruction last = null; @@ -153,7 +184,7 @@ namespace Mono.Debugger.Soft token = br.ReadInt32 (); t = vm.conn.Method_ResolveToken (Method.Id, token); if (t.Type == TokenType.STRING) - instr.Operand = t.Str; + instr.Operand = EscapeString (t.Str); break; case OperandType.InlineField : case OperandType.InlineMethod : diff --git a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs index f252fb6b1c..18611ba327 100644 --- a/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs +++ b/main/contrib/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs @@ -144,6 +144,19 @@ namespace Mono.Debugger.Soft return EndInvokeMethodInternal (asyncResult); } + // + // Invoke the members of METHODS one-by-one, calling CALLBACK after each invoke was finished. The IAsyncResult will be marked as completed after all invokes have + // finished. The callback will be called with a different IAsyncResult that represents one method invocation. + // From protocol version 2.22. + // + public IAsyncResult BeginInvokeMultiple (ThreadMirror thread, MethodMirror[] methods, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) { + return BeginInvokeMultiple (vm, thread, methods, this, arguments, options, callback, state); + } + + public void EndInvokeMultiple (IAsyncResult asyncResult) { + EndInvokeMultipleInternal (asyncResult); + } + /* * Common implementation for invokes */ @@ -196,6 +209,12 @@ namespace Mono.Debugger.Soft get; set; } + public bool IsMultiple { + get; set; + } + + public int NumPending; + public void Abort () { if (ID == 0) // Ooops @@ -272,6 +291,16 @@ namespace Mono.Debugger.Soft } } + internal static void EndInvokeMultipleInternal (IAsyncResult asyncResult) { + if (asyncResult == null) + throw new ArgumentNullException ("asyncResult"); + + InvokeAsyncResult r = (InvokeAsyncResult)asyncResult; + + if (!r.IsCompleted) + r.AsyncWaitHandle.WaitOne (); + } + 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)); } @@ -280,5 +309,72 @@ namespace Mono.Debugger.Soft { vm.conn.VM_AbortInvoke (thread.Id, id); } + + // + // Implementation of InvokeMultiple + // + + internal static IInvokeAsyncResult BeginInvokeMultiple (VirtualMachine vm, ThreadMirror thread, MethodMirror[] methods, Value this_obj, IList<IList<Value>> arguments, InvokeOptions options, AsyncCallback callback, object state) { + if (thread == null) + throw new ArgumentNullException ("thread"); + if (methods == null) + throw new ArgumentNullException ("methods"); + foreach (var m in methods) + if (m == null) + throw new ArgumentNullException ("method"); + if (arguments == null) { + arguments = new List<IList<Value>> (); + for (int i = 0; i < methods.Length; ++i) + arguments.Add (new Value [0]); + } else { + // FIXME: Not needed for property evaluation + throw new NotImplementedException (); + } + if (callback == null) + throw new ArgumentException ("A callback argument is required for this method.", "callback"); + + InvokeFlags f = InvokeFlags.NONE; + + if ((options & InvokeOptions.DisableBreakpoints) != 0) + f |= InvokeFlags.DISABLE_BREAKPOINTS; + if ((options & InvokeOptions.SingleThreaded) != 0) + f |= InvokeFlags.SINGLE_THREADED; + + InvokeAsyncResult r = new InvokeAsyncResult { AsyncState = state, AsyncWaitHandle = new ManualResetEvent (false), VM = vm, Thread = thread, Callback = callback, NumPending = methods.Length, IsMultiple = true }; + + var mids = new long [methods.Length]; + for (int i = 0; i < methods.Length; ++i) + mids [i] = methods [i].Id; + var args = new List<ValueImpl[]> (); + for (int i = 0; i < methods.Length; ++i) + args.Add (vm.EncodeValues (arguments [i])); + r.ID = vm.conn.VM_BeginInvokeMethods (thread.Id, mids, this_obj != null ? vm.EncodeValue (this_obj) : vm.EncodeValue (vm.CreateValue (null)), args, f, InvokeMultipleCB, r); + + return r; + } + + // This is called when the result of an invoke is received + static void InvokeMultipleCB (ValueImpl v, ValueImpl exc, ErrorCode error, object state) { + var r = (InvokeAsyncResult)state; + + Interlocked.Decrement (ref r.NumPending); + + if (r.NumPending == 0) { + r.IsCompleted = true; + ((ManualResetEvent)r.AsyncWaitHandle).Set (); + } + + // Have to pass another asyncresult to the callback since multiple threads can execute it concurrently with results of multiple invocations + var r2 = new InvokeAsyncResult { AsyncState = r.AsyncState, AsyncWaitHandle = null, VM = r.VM, Thread = r.Thread, Callback = r.Callback, IsCompleted = true }; + + if (error != 0) { + r2.ErrorCode = error; + } else { + r2.Value = v; + r2.Exception = exc; + } + + r.Callback.BeginInvoke (r2, null, null); + } } } diff --git a/main/contrib/Mono.Debugger.Soft/mono-git-revision b/main/contrib/Mono.Debugger.Soft/mono-git-revision index f9bc9925ac..9ef02de113 100644 --- a/main/contrib/Mono.Debugger.Soft/mono-git-revision +++ b/main/contrib/Mono.Debugger.Soft/mono-git-revision @@ -1 +1 @@ -bfdb8242d92017f0c1c34da9c976622c959b2da1 +3536222a62b149e4b3cda679d786e3cb534a5921 |