diff options
Diffstat (limited to 'mcs/class/Mono.Debugger.Soft')
11 files changed, 364 insertions, 104 deletions
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs index 105ff4fb67..13096f0594 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -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, @@ -220,6 +222,7 @@ namespace Mono.Debugger.Soft UNKNOWN = 4 } + [Flags] enum StackFrameFlags { NONE = 0, DEBUGGER_INVOKE = 1, @@ -285,6 +288,9 @@ namespace Mono.Debugger.Soft public bool Uncaught { get; set; } + public bool Subclasses { + get; set; + } } class AssemblyModifier : Modifier { @@ -342,6 +348,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 +405,7 @@ namespace Mono.Debugger.Soft * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 24; + internal const int MINOR_VERSION = 27; enum WPSuspendPolicy { NONE = 0, @@ -546,6 +556,7 @@ namespace Mono.Debugger.Soft IS_INITIALIZED = 18 } + [Flags] enum BindingFlagsExtensions { BINDING_FLAGS_IGNORE_CASE = 0x70000000, } @@ -1218,82 +1229,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 (); @@ -2174,6 +2174,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); diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs index 07d4d8ccdd..906b43fd83 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ExceptionEventRequest.cs @@ -6,7 +6,7 @@ namespace Mono.Debugger.Soft public sealed class ExceptionEventRequest : EventRequest { TypeMirror exc_type; - bool caught, uncaught; + bool caught, uncaught, subclasses; internal ExceptionEventRequest (VirtualMachine vm, TypeMirror exc_type, bool caught, bool uncaught) : base (vm, EventType.Exception) { if (exc_type != null) { @@ -18,6 +18,7 @@ namespace Mono.Debugger.Soft this.exc_type = exc_type; this.caught = caught; this.uncaught = uncaught; + this.subclasses = true; } public TypeMirror ExceptionType { @@ -26,9 +27,21 @@ namespace Mono.Debugger.Soft } } + // Defaults to true + // Supported since protocol version 2.25 + public bool IncludeSubclasses { + get { + return subclasses; + } + set { + vm.CheckProtocolVersion (2, 25); + subclasses = value; + } + } + public override void Enable () { var mods = new List <Modifier> (); - mods.Add (new ExceptionModifier () { Type = exc_type != null ? exc_type.Id : 0, Caught = caught, Uncaught = uncaught }); + mods.Add (new ExceptionModifier () { Type = exc_type != null ? exc_type.Id : 0, Caught = caught, Uncaught = uncaught, Subclasses = subclasses }); SendReq (mods); } } diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs index 18611ba327..8a060a2df9 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ObjectMirror.cs @@ -2,6 +2,9 @@ using System; using System.Collections.Generic; using System.Runtime.Remoting.Messaging; using System.Threading; +#if NET_4_5 +using System.Threading.Tasks; +#endif namespace Mono.Debugger.Soft { @@ -144,6 +147,23 @@ namespace Mono.Debugger.Soft return EndInvokeMethodInternal (asyncResult); } +#if NET_4_5 + public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) { + var tcs = new TaskCompletionSource<Value> (); + BeginInvokeMethod (thread, method, arguments, options, iar => + { + try { + tcs.SetResult (EndInvokeMethod (iar)); + } catch (OperationCanceledException) { + tcs.TrySetCanceled (); + } catch (Exception ex) { + tcs.TrySetException (ex); + } + }, null); + return tcs.Task; + } +#endif + // // 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. diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs index cb3c79231b..035fbcee56 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StepEventRequest.cs @@ -23,7 +23,11 @@ namespace Mono.Debugger.Soft StaticCtor = 1, /* Since protocol version 2.20 */ /* Methods which have the [DebuggerHidden] attribute */ + /* Before protocol version 2.26, this includes [DebuggerStepThrough] as well */ DebuggerHidden = 2, + /* Since protocol version 2.26 */ + /* Methods which have the [DebuggerStepThrough] attribute */ + DebuggerStepThrough = 4, } public sealed class StepEventRequest : EventRequest { diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs index 1db6037972..7307b0ea89 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/StructMirror.cs @@ -41,6 +41,20 @@ namespace Mono.Debugger.Soft } throw new ArgumentException ("Unknown struct field '" + field + "'.", "field"); } + set { + FieldInfoMirror[] field_info = Type.GetFields (); + int nf = 0; + for (int i = 0; i < field_info.Length; ++i) { + if (!field_info [i].IsStatic) { + if (field_info [i].Name == field) { + fields [nf] = value; + return; + } + nf++; + } + } + throw new ArgumentException ("Unknown struct field '" + field + "'.", "field"); + } } internal void SetField (int index, Value value) { diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs index 3cd1edeadf..e7baa44fae 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs @@ -3,6 +3,9 @@ using System.Collections.Generic; using System.Reflection; using C = Mono.Cecil; using Mono.Cecil.Metadata; +#if NET_4_5 +using System.Threading.Tasks; +#endif namespace Mono.Debugger.Soft { @@ -26,6 +29,7 @@ namespace Mono.Debugger.Soft TypeMirror[] ifaces; Dictionary<TypeMirror, InterfaceMappingMirror> iface_map; TypeMirror[] type_args; + bool cached_base_type; bool inited; internal const BindingFlags DefaultBindingFlags = @@ -78,9 +82,9 @@ namespace Mono.Debugger.Soft public TypeMirror BaseType { get { - // FIXME: base_type could be null for object/interfaces - if (base_type == null) { + if (!cached_base_type) { base_type = vm.GetType (GetInfo ().base_type); + cached_base_type = true; } return base_type; } @@ -591,11 +595,11 @@ namespace Mono.Debugger.Soft string[] source_files; string[] source_files_full_path; - public string[] GetSourceFiles (bool return_full_paths) { - string[] res = return_full_paths ? source_files_full_path : source_files; + public string[] GetSourceFiles (bool returnFullPaths) { + string[] res = returnFullPaths ? source_files_full_path : source_files; if (res == null) { - res = vm.conn.Type_GetSourceFiles (id, return_full_paths); - if (return_full_paths) + res = vm.conn.Type_GetSourceFiles (id, returnFullPaths); + if (returnFullPaths) source_files_full_path = res; else source_files = res; @@ -684,29 +688,38 @@ namespace Mono.Debugger.Soft * used by the reflection-only functionality on .net. */ public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) { - return GetCAttrs (null, inherit); + return GetCustomAttrs (null, inherit); } public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) { if (attributeType == null) throw new ArgumentNullException ("attributeType"); - return GetCAttrs (attributeType, inherit); + return GetCustomAttrs (attributeType, inherit); } - CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) { + void AppendCustomAttrs (IList<CustomAttributeDataMirror> attrs, TypeMirror type, bool inherit) + { if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes) cattrs = new CustomAttributeDataMirror [0]; - // FIXME: Handle inherit if (cattrs == null) { CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false); cattrs = CustomAttributeDataMirror.Create (vm, info); } - var res = new List<CustomAttributeDataMirror> (); - foreach (var attr in cattrs) + + foreach (var attr in cattrs) { if (type == null || attr.Constructor.DeclaringType == type) - res.Add (attr); - return res.ToArray (); + attrs.Add (attr); + } + + if (inherit && BaseType != null) + BaseType.AppendCustomAttrs (attrs, type, inherit); + } + + CustomAttributeDataMirror[] GetCustomAttrs (TypeMirror type, bool inherit) { + var attrs = new List<CustomAttributeDataMirror> (); + AppendCustomAttrs (attrs, type, inherit); + return attrs.ToArray (); } public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) { @@ -785,6 +798,23 @@ namespace Mono.Debugger.Soft return ObjectMirror.EndInvokeMethodInternal (asyncResult); } +#if NET_4_5 + public Task<Value> InvokeMethodAsync (ThreadMirror thread, MethodMirror method, IList<Value> arguments, InvokeOptions options = InvokeOptions.None) { + var tcs = new TaskCompletionSource<Value> (); + BeginInvokeMethod (thread, method, arguments, options, iar => + { + try { + tcs.SetResult (EndInvokeMethod (iar)); + } catch (OperationCanceledException) { + tcs.TrySetCanceled (); + } catch (Exception ex) { + tcs.TrySetException (ex); + } + }, null); + return tcs.Task; + } +#endif + public Value NewInstance (ThreadMirror thread, MethodMirror method, IList<Value> arguments) { return ObjectMirror.InvokeMethod (vm, thread, method, null, arguments, InvokeOptions.None); } diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs index 18eeb92ca7..40e60ad091 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VMDeathEvent.cs @@ -4,7 +4,18 @@ namespace Mono.Debugger.Soft { public class VMDeathEvent : Event { - public VMDeathEvent (VirtualMachine vm, int req_id) : base (EventType.VMDeath, vm, req_id, -1) { + int exit_code; + + public VMDeathEvent (VirtualMachine vm, int req_id, int exit_code) : base (EventType.VMDeath, vm, req_id, -1) { + this.exit_code = exit_code; + } + + // Since protocol version 2.27 + public int ExitCode { + get { + vm.CheckProtocolVersion (2, 27); + return exit_code; + } } } } diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs index b77458b441..cb2cafdb71 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs @@ -137,7 +137,7 @@ namespace Mono.Debugger.Soft public void Detach () { conn.VM_Dispose (); conn.Close (); - notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null); + notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null, 0); } [Obsolete ("This method was poorly named; use the Detach() method instead")] @@ -227,10 +227,14 @@ namespace Mono.Debugger.Soft } public void EnableEvents (params EventType[] events) { + EnableEvents (events, SuspendPolicy.All); + } + + public void EnableEvents (EventType[] events, SuspendPolicy suspendPolicy) { foreach (EventType etype in events) { if (etype == EventType.Breakpoint) throw new ArgumentException ("Breakpoint events cannot be requested using EnableEvents", "events"); - conn.EnableEvent (etype, SuspendPolicy.All, null); + conn.EnableEvent (etype, suspendPolicy, null); } } @@ -315,7 +319,7 @@ namespace Mono.Debugger.Soft root_domain = GetDomain (root_domain_id); } - internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri) { + internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri, int exit_code) { //Console.WriteLine ("Event: " + evtype + "(" + vm_uri + ")"); switch (evtype) { @@ -327,7 +331,7 @@ namespace Mono.Debugger.Soft queue_event_set (new EventSet (this, spolicy, new Event[] { new VMStartEvent (vm, req_id, thread_id) })); break; case EventType.VMDeath: - queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id) })); + queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id, exit_code) })); break; case EventType.VMDisconnect: queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDisconnectEvent (vm, req_id) })); @@ -620,10 +624,10 @@ namespace Mono.Debugger.Soft switch (ei.EventType) { case EventType.VMStart: - vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null); + vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null, 0); break; case EventType.VMDeath: - vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null); + vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null, ei.ExitCode); break; case EventType.ThreadStart: l.Add (new ThreadStartEvent (vm, req_id, id)); @@ -677,7 +681,7 @@ namespace Mono.Debugger.Soft } public void VMDisconnect (int req_id, long thread_id, string vm_uri) { - vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri); + vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri, 0); } } diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs index a5bdf4fc39..211a0df302 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachineManager.cs @@ -93,7 +93,8 @@ namespace Mono.Debugger.Soft if (options != null && options.Valgrind) info.FileName = "valgrind"; - + info.UseShellExecute = false; + ITargetProcess p; if (options != null && options.CustomProcessLauncher != null) p = new ProcessWrapper (options.CustomProcessLauncher (info)); diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 7cf688c0d2..e1d912ec4e 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -132,6 +132,13 @@ public struct GStruct<T> { } } +public struct NestedStruct { + NestedInner nested1, nested2; +} + +public struct NestedInner { +} + interface ITest { void Foo (); @@ -202,6 +209,7 @@ public class Tests : TestsBase, ITest2 [ThreadStatic] public static int tls_i; public static bool is_attached = Debugger.IsAttached; + public NestedStruct nested_struct; #pragma warning restore 0414 @@ -349,7 +357,10 @@ public class Tests : TestsBase, ITest2 } catch { } ss7 (); + ss_nested (); ss_regress_654694 (); + ss_step_through (); + ss_recursive (1); } [MethodImplAttribute (MethodImplOptions.NoInlining)] @@ -424,6 +435,57 @@ public class Tests : TestsBase, ITest2 } [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_nested () { + ss_nested_1 (ss_nested_2 ()); + ss_nested_1 (ss_nested_2 ()); + ss_nested_3 (); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_nested_1 (int i) { + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static int ss_nested_2 () { + return 0; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_nested_3 () { + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_step_through () { + step_through_1 (); + StepThroughClass.step_through_2 (); + step_through_3 (); + } + + [DebuggerStepThrough] + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void step_through_1 () { + } + + [DebuggerStepThrough] + class StepThroughClass { + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void step_through_2 () { + } + } + + [DebuggerStepThrough] + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void step_through_3 () { + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_recursive (int n) { + if (n == 10) + return; + ss_recursive (n + 1); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] public static bool is_even (int i) { return i % 2 == 0; } @@ -535,8 +597,9 @@ public class Tests : TestsBase, ITest2 [MethodImplAttribute (MethodImplOptions.NoInlining)] public static void locals () { string s = null; + var astruct = new AStruct () { i = 42 }; locals1 (null); - locals2<string> (null, 5, "ABC", ref s); + locals2<string> (null, 5, "ABC", ref s, ref astruct); locals3 (); locals6 (); locals7<int> (22); @@ -562,7 +625,7 @@ public class Tests : TestsBase, ITest2 #if NET_4_5 [StateMachine (typeof (int))] #endif - public static void locals2<T> (string[] args, int arg, T t, ref string rs) { + public static void locals2<T> (string[] args, int arg, T t, ref string rs, ref AStruct astruct) { long i = 42; string s = "AB"; @@ -571,6 +634,7 @@ public class Tests : TestsBase, ITest2 i ++; if (t != null) i ++; + astruct = new AStruct (); } rs = "A"; } @@ -840,6 +904,15 @@ public class Tests : TestsBase, ITest2 throw new OverflowException (); } catch (Exception) { } + // no subclasses + try { + throw new OverflowException (); + } catch (Exception) { + } + try { + throw new Exception (); + } catch (Exception) { + } object o = null; try { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index c8302274db..cc13107513 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -105,7 +105,7 @@ public class DebuggerTests MethodMirror m = entry_point.DeclaringType.GetMethod (name); Assert.IsNotNull (m); //Console.WriteLine ("X: " + name + " " + m.ILOffsets.Count + " " + m.Locations.Count); - vm.SetBreakpoint (m, m.ILOffsets [0]); + var req = vm.SetBreakpoint (m, m.ILOffsets [0]); Event e = null; @@ -116,6 +116,8 @@ public class DebuggerTests break; } + req.Disable (); + Assert.IsInstanceOfType (typeof (BreakpointEvent), e); Assert.AreEqual (m.Name, (e as BreakpointEvent).Method.Name); @@ -375,15 +377,19 @@ public class DebuggerTests Assert.AreEqual (method, (e as StepEvent).Method.Name); } + StepEventRequest create_step (Event e) { + var req = vm.CreateStepRequest (e.Thread); + step_req = req; + return req; + } + [Test] public void SingleStepping () { Event e = run_until ("single_stepping"); - var req = vm.CreateStepRequest (e.Thread); + var req = create_step (e); req.Enable (); - step_req = req; - // Step over 'bool b = true' e = step_once (); assert_location (e, "single_stepping"); @@ -402,49 +408,24 @@ public class DebuggerTests e = step_once (); assert_location (e, "single_stepping"); - // Change to step over - req.Disable (); - req.Depth = StepDepth.Over; - req.Enable (); - // Step over ss2 - e = step_once (); + e = step_over (); assert_location (e, "single_stepping"); - // Change to step into - req.Disable (); - req.Depth = StepDepth.Into; - req.Enable (); - // Step into ss3 - e = step_once (); + e = step_into (); assert_location (e, "ss3"); - // Change to step out - req.Disable (); - req.Depth = StepDepth.Out; - req.Enable (); - // Step back into single_stepping - e = step_once (); + e = step_out (); assert_location (e, "single_stepping"); - // Change to step into - req.Disable (); - req.Depth = StepDepth.Into; - req.Enable (); - // Step into ss3_2 () - e = step_once (); + e = step_into (); assert_location (e, "ss3_2"); - // Change to step over - req.Disable (); - req.Depth = StepDepth.Over; - req.Enable (); - // Step over ss3_2_2 () - e = step_once (); + e = step_over (); assert_location (e, "ss3_2"); // Recreate the request @@ -458,13 +439,8 @@ public class DebuggerTests e = step_once (); assert_location (e, "single_stepping"); - // Change to step into - req.Disable (); - req.Depth = StepDepth.Into; - req.Enable (); - // Step into ss4 () - e = step_once (); + e = step_into (); assert_location (e, "ss4"); // Skip nop @@ -504,13 +480,12 @@ public class DebuggerTests assert_location (e, "is_even"); // FIXME: Check that single stepping works with lock (obj) - req.Disable (); // Run until ss6 e = run_until ("ss6"); - req = vm.CreateStepRequest (e.Thread); + req = create_step (e); req.Depth = StepDepth.Over; req.Enable (); @@ -522,18 +497,62 @@ public class DebuggerTests // Check that a step over stops at an EH clause e = run_until ("ss7_2"); - req = vm.CreateStepRequest (e.Thread); + req = create_step (e); req.Depth = StepDepth.Out; req.Enable (); e = step_once (); assert_location (e, "ss7"); req.Disable (); - req = vm.CreateStepRequest (e.Thread); + req = create_step (e); req.Depth = StepDepth.Over; req.Enable (); e = step_once (); assert_location (e, "ss7"); req.Disable (); + + // Check that stepping stops between nested calls + e = run_until ("ss_nested_2"); + e = step_out (); + assert_location (e, "ss_nested"); + e = step_into (); + assert_location (e, "ss_nested_1"); + e = step_out (); + assert_location (e, "ss_nested"); + // Check that step over steps over nested calls + e = step_over (); + assert_location (e, "ss_nested"); + e = step_into (); + assert_location (e, "ss_nested_3"); + req.Disable (); + + // Check DebuggerStepThrough support + e = run_until ("ss_step_through"); + req = create_step (e); + req.Filter = StepFilter.DebuggerStepThrough; + e = step_into (); + // Step through step_through_1 () + e = step_into (); + assert_location (e, "ss_step_through"); + // Step through StepThroughClass.step_through_2 () + e = step_into (); + assert_location (e, "ss_step_through"); + req.Disable (); + req.Filter = StepFilter.None; + e = step_into (); + assert_location (e, "step_through_3"); + req.Disable (); + + // Check that step-over doesn't stop at inner frames with recursive functions + e = run_until ("ss_recursive"); + req = create_step (e); + e = step_over (); + e = step_over (); + e = step_over (); + var f = e.Thread.GetFrames () [0]; + assert_location (e, "ss_recursive"); + AssertValue (1, f.GetValue (f.Method.GetLocal ("n"))); + + req.Disable (); } [Test] @@ -1113,7 +1132,7 @@ public class DebuggerTests t = frame.Method.GetParameters ()[8].ParameterType; Assert.AreEqual ("Tests2", t.Name); var attrs = t.GetCustomAttributes (true); - Assert.AreEqual (3, attrs.Length); + Assert.AreEqual (5, attrs.Length); foreach (var attr in attrs) { if (attr.Constructor.DeclaringType.Name == "DebuggerDisplayAttribute") { Assert.AreEqual (1, attr.ConstructorArguments.Count); @@ -1132,6 +1151,12 @@ public class DebuggerTests Assert.AreEqual (2, attr.NamedArguments.Count); Assert.AreEqual ("afield", attr.NamedArguments [0].Field.Name); Assert.AreEqual ("bfield", attr.NamedArguments [1].Field.Name); + } else if (attr.Constructor.DeclaringType.Name == "ClassInterfaceAttribute") { + // inherited from System.Object + //} else if (attr.Constructor.DeclaringType.Name == "Serializable") { + // inherited from System.Object + } else if (attr.Constructor.DeclaringType.Name == "ComVisibleAttribute") { + // inherited from System.Object } else { Assert.Fail (attr.Constructor.DeclaringType.Name); } @@ -1335,6 +1360,10 @@ public class DebuggerTests Assert.AreEqual ("AStruct", s.Type.Name); AssertValue (42, s ["i"]); + // Check decoding of nested structs (#14942) + obj = o.GetValue (o.Type.GetField ("nested_struct")); + o.SetValue (o.Type.GetField ("nested_struct"), obj); + // Check round tripping of boxed struct fields (#12354) obj = o.GetValue (o.Type.GetField ("boxed_struct_field")); o.SetValue (o.Type.GetField ("boxed_struct_field"), obj); @@ -1438,8 +1467,8 @@ public class DebuggerTests StackFrame frame = e.Thread.GetFrames () [0]; var locals = frame.Method.GetLocals (); - Assert.AreEqual (7, locals.Length); - for (int i = 0; i < 7; ++i) { + Assert.AreEqual (8, locals.Length); + for (int i = 0; i < 8; ++i) { if (locals [i].Name == "args") { Assert.IsTrue (locals [i].IsArg); Assert.AreEqual ("String[]", locals [i].Type.Name); @@ -1462,6 +1491,7 @@ public class DebuggerTests } else if (locals [i].Name == "rs") { Assert.IsTrue (locals [i].IsArg); Assert.AreEqual ("String", locals [i].Type.Name); + } else if (locals [i].Name == "astruct") { } else { Assert.Fail (); } @@ -1475,6 +1505,27 @@ public class DebuggerTests return e; } + Event step_into () { + step_req.Disable (); + step_req.Depth = StepDepth.Into; + step_req.Enable (); + return step_once (); + } + + Event step_over () { + step_req.Disable (); + step_req.Depth = StepDepth.Over; + step_req.Enable (); + return step_once (); + } + + Event step_out () { + step_req.Disable (); + step_req.Depth = StepDepth.Out; + step_req.Enable (); + return step_once (); + } + [Test] public void Locals () { var be = run_until ("locals1"); @@ -1496,9 +1547,8 @@ public class DebuggerTests object val = frame.GetValue (frame.Method.GetLocal ("i")); AssertValue (0, val); - var req = vm.CreateStepRequest (be.Thread); + var req = create_step (be); req.Enable (); - step_req = req; // Skip nop step_once (); @@ -1580,9 +1630,8 @@ public class DebuggerTests // gsharedvt be = run_until ("locals7"); - req = vm.CreateStepRequest (be.Thread); + req = create_step (be); req.Enable (); - step_req = req; // Skip nop e = step_once (); @@ -1653,6 +1702,8 @@ public class DebuggerTests var e = GetNextEvent (); Assert.IsInstanceOfType (typeof (VMDeathEvent), e); + Assert.AreEqual (5, (e as VMDeathEvent).ExitCode); + var p = vm.Process; /* Could be a remote vm with no process */ if (p != null) { @@ -1698,7 +1749,7 @@ public class DebuggerTests // FIXME: Merge this with LineNumbers () when its fixed - step_req = vm.CreateStepRequest (e.Thread); + step_req = create_step (e); step_req.Depth = StepDepth.Into; step_req.Enable (); @@ -1734,7 +1785,7 @@ public class DebuggerTests public void LineNumbers () { Event e = run_until ("line_numbers"); - step_req = vm.CreateStepRequest (e.Thread); + step_req = create_step (e); step_req.Depth = StepDepth.Into; step_req.Enable (); @@ -2035,6 +2086,18 @@ public class DebuggerTests v = this_obj.InvokeMethod (e.Thread, m, null); AssertValue (42, v); +#if NET_4_5 + // instance + m = t.GetMethod ("invoke_pass_ref"); + var task = this_obj.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") }); + AssertValue ("ABC", task.Result); + + // static + m = t.GetMethod ("invoke_static_pass_ref"); + task = t.InvokeMethodAsync (e.Thread, m, new Value [] { vm.RootDomain.CreateString ("ABC") }); + AssertValue ("ABC", task.Result); +#endif + // Argument checking // null thread @@ -2258,8 +2321,13 @@ public class DebuggerTests while (invoke_results.Count < 2) { Thread.Sleep (100); } - AssertValue ("ABC", invoke_results [0]); - AssertValue (42, invoke_results [1]); + if (invoke_results [0] is PrimitiveValue) { + AssertValue ("ABC", invoke_results [1]); + AssertValue (42, invoke_results [0]); + } else { + AssertValue ("ABC", invoke_results [0]); + AssertValue (42, invoke_results [1]); + } } void invoke_multiple_cb (IAsyncResult ar) { @@ -2337,6 +2405,14 @@ public class DebuggerTests frame.SetValue (p, vm.RootDomain.CreateString ("DEF2")); AssertValue ("DEF2", frame.GetValue (p)); + // byref struct + p = frame.Method.GetParameters ()[4]; + var v = frame.GetValue (p) as StructMirror; + v ["i"] = vm.CreateValue (43); + frame.SetValue (p, v); + v = frame.GetValue (p) as StructMirror; + AssertValue (43, v ["i"]); + // argument checking // variable null @@ -2426,13 +2502,11 @@ public class DebuggerTests Assert.IsNull (v); // Try a single step after the invoke - var req = vm.CreateStepRequest (e.Thread); + var req = create_step (e); req.Depth = StepDepth.Into; req.Size = StepSize.Line; req.Enable (); - step_req = req; - // Skip nop step_once (); @@ -2487,6 +2561,17 @@ public class DebuggerTests Assert.AreEqual ("OverflowException", (e as ExceptionEvent).Exception.Type.Name); req.Disable (); + // no subclasses + req.IncludeSubclasses = false; + req.Enable (); + + vm.Resume (); + + e = GetNextEvent (); + Assert.IsInstanceOfType (typeof (ExceptionEvent), e); + Assert.AreEqual ("Exception", (e as ExceptionEvent).Exception.Type.Name); + req.Disable (); + // Implicit exceptions req = vm.CreateExceptionRequest (null); req.Enable (); @@ -2511,7 +2596,7 @@ public class DebuggerTests Assert.AreEqual ("exceptions2", frames [0].Method.Name); req.Disable (); - var sreq = vm.CreateStepRequest (e.Thread); + var sreq = create_step (e); sreq.Depth = StepDepth.Over; sreq.Size = StepSize.Line; sreq.Enable (); @@ -2915,7 +3000,7 @@ public class DebuggerTests e = GetNextEvent (); Assert.IsTrue (e is BreakpointEvent); - var req = vm.CreateStepRequest (e.Thread); + var req = create_step (e); req.Depth = StepDepth.Over; req.Size = StepSize.Line; req.Enable (); |