diff options
7 files changed, 178 insertions, 15 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 602c827091d..e480555252e 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs @@ -420,7 +420,7 @@ namespace Mono.Debugger.Soft * with newer runtimes, and vice versa. */ internal const int MAJOR_VERSION = 2; - internal const int MINOR_VERSION = 45; + internal const int MINOR_VERSION = 46; enum WPSuspendPolicy { NONE = 0, @@ -442,7 +442,8 @@ namespace Mono.Debugger.Soft TYPE = 23, MODULE = 24, FIELD = 25, - EVENT = 64 + EVENT = 64, + POINTER = 65 } enum EventKind { @@ -574,7 +575,8 @@ namespace Mono.Debugger.Soft GET_INTERFACES = 16, GET_INTERFACE_MAP = 17, IS_INITIALIZED = 18, - CREATE_INSTANCE = 19 + CREATE_INSTANCE = 19, + GET_VALUE_SIZE = 20 } enum CmdField { @@ -606,6 +608,10 @@ namespace Mono.Debugger.Soft GET_CHARS = 3 } + enum CmdPointer { + GET_VALUE = 1 + } + enum CmdObjectRef { GET_TYPE = 1, GET_VALUES = 2, @@ -730,10 +736,12 @@ namespace Mono.Debugger.Soft } class PacketReader { + Connection connection; byte[] packet; int offset; - public PacketReader (byte[] packet) { + public PacketReader (Connection connection, byte[] packet) { + this.connection = connection; this.packet = packet; // For event packets @@ -845,9 +853,16 @@ namespace Mono.Debugger.Soft return new ValueImpl { Type = etype, Value = ReadDouble () }; case ElementType.I: case ElementType.U: - case ElementType.Ptr: // FIXME: The client and the debuggee might have different word sizes return new ValueImpl { Type = etype, Value = ReadLong () }; + case ElementType.Ptr: + long value = ReadLong (); + if (connection.Version.AtLeast (2, 46)) { + long pointerClass = ReadId (); + return new ValueImpl { Type = etype, Klass = pointerClass, Value = value }; + } else { + return new ValueImpl { Type = etype, Value = value }; + } case ElementType.String: case ElementType.SzArray: case ElementType.Class: @@ -1283,7 +1298,7 @@ namespace Mono.Debugger.Soft if (cb != null) cb.Invoke (id, packet); } else { - PacketReader r = new PacketReader (packet); + PacketReader r = new PacketReader (this, packet); if (r.CommandSet == CommandSet.EVENT && r.Command == (int)CmdEvent.COMPOSITE) { int spolicy = r.ReadByte (); @@ -1502,7 +1517,7 @@ namespace Mono.Debugger.Soft if (EnableConnectionLogging) LogPacket (packet_id, encoded_packet, p, command_set, command, watch); /* Run the callback on a tp thread to avoid blocking the receive thread */ - PacketReader r = new PacketReader (p); + PacketReader r = new PacketReader (this, p); cb.BeginInvoke (r, null, null); }; reply_cb_counts [id] = count; @@ -1549,7 +1564,7 @@ namespace Mono.Debugger.Soft if (reply_packets.ContainsKey (packetId)) { byte[] reply = reply_packets [packetId]; reply_packets.Remove (packetId); - PacketReader r = new PacketReader (reply); + PacketReader r = new PacketReader (this, reply); if (EnableConnectionLogging) LogPacket (packetId, encoded_packet, reply, command_set, command, watch); @@ -2297,6 +2312,11 @@ namespace Mono.Debugger.Soft return r.ReadId (); } + internal int Type_GetValueSize (long id) { + PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUE_SIZE, new PacketWriter ().WriteId (id)); + return r.ReadInt (); + } + /* * FIELD */ @@ -2475,7 +2495,16 @@ namespace Mono.Debugger.Soft for (int i = 0; i < length; ++i) res [i] = (char)r.ReadShort (); return res; - } + } + + /* + * POINTERS + */ + + internal ValueImpl Pointer_GetValue (long address, TypeMirror type) + { + return SendReceive (CommandSet.POINTER, (int)CmdPointer.GET_VALUE, new PacketWriter ().WriteLong (address).WriteId (type.Id)).ReadValue (); + } /* * OBJECTS diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs index 3fa359fcb5d..2cf9dfa418b 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs @@ -48,6 +48,16 @@ namespace Mono.Debugger.Soft get { return type; } } + // Since protocol version 2.46 + public Value Value { + get { + if (Address == 0) + return null; + + return vm.DecodeValue (vm.conn.Pointer_GetValue (Address, Type)); + } + } + public override bool Equals (object obj) { if (obj != null && obj is PointerValue) return addr == (obj as PointerValue).addr; 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 f92dca03932..78c11a8d9af 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs @@ -842,6 +842,11 @@ namespace Mono.Debugger.Soft return vm.GetObject (vm.conn.Type_CreateInstance (id)); } + // Since protocol version 2.46 + public int GetValueSize () { + return vm.conn.Type_GetValueSize (id); + } + // Since protocol version 2.11 public TypeMirror[] GetInterfaces () { if (ifaces == null) 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 1eaaac8ec9d..9d60855a31a 100644 --- a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs +++ b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs @@ -616,8 +616,11 @@ namespace Mono.Debugger.Soft } internal Value DecodeValue (ValueImpl v, Dictionary<int, Value> parent_vtypes) { - if (v.Value != null) + if (v.Value != null) { + if (Version.AtLeast (2, 46) && v.Type == ElementType.Ptr) + return new PointerValue(this, GetType(v.Klass), (long)v.Value); return new PrimitiveValue (this, v.Value); + } switch (v.Type) { case ElementType.Void: @@ -682,8 +685,11 @@ namespace Mono.Debugger.Soft duplicates.Add (v); return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeValues ((v as StructMirror).Fields, duplicates) }; + } else if (v is PointerValue) { + PointerValue val = (PointerValue)v; + return new ValueImpl { Type = ElementType.Ptr, Klass = val.Type.Id, Value = val.Address }; } else { - throw new NotSupportedException (); + throw new NotSupportedException ("Value of type " + v.GetType()); } } diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index 97202372c77..33ef36b6d5c 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -145,6 +145,12 @@ public struct AStruct : ITest2 { } } + +public struct BlittableStruct { + public int i; + public double d; +} + public class GClass<T> { public T field; public static T static_field; @@ -349,6 +355,7 @@ public class Tests : TestsBase, ITest2 gc_suspend (); set_ip (); step_filters (); + pointers (); if (args.Length > 0 && args [0] == "local-reflect") local_reflect (); if (args.Length > 0 && args [0] == "domain-test") @@ -1761,6 +1768,18 @@ public class Tests : TestsBase, ITest2 static void step_out_void_async_2 () { } + + public static unsafe void pointer_arguments (int* a, BlittableStruct* s) { + *a = 0; + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static unsafe void pointers () { + int[] a = new [] {1,2,3}; + BlittableStruct s = new BlittableStruct () { i = 2, d = 3.0 }; + fixed (int* pa = a) + pointer_arguments (pa, &s); + } } public class SentinelClass : MarshalByRefObject { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs index 75fdd8f6d07..4633ce2ae58 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs @@ -325,6 +325,8 @@ public class DebuggerTests Assert.AreEqual (expected, (val as StringMirror).Value); } else if (val is StructMirror && (val as StructMirror).Type.Name == "IntPtr") { AssertValue (expected, (val as StructMirror).Fields [0]); + } else if (val is PointerValue) { + Assert.AreEqual (expected, (val as PointerValue).Address); } else { Assert.IsTrue (val is PrimitiveValue); Assert.AreEqual (expected, (val as PrimitiveValue).Value); @@ -4433,5 +4435,39 @@ public class DebuggerTests // DummyCall assert_location (e, "Call"); } + + [Test] + public void Pointer_GetValue () { + var e = run_until ("pointer_arguments"); + var frame = e.Thread.GetFrames () [0]; + + var param = frame.Method.GetParameters()[0]; + Assert.AreEqual("Int32*", param.ParameterType.Name); + + var pointerValue = frame.GetValue(param) as PointerValue; + Assert.AreEqual("Int32*", pointerValue.Type.Name); + + AssertValue(1, pointerValue.Value); + + var pointerValue2 = new PointerValue (pointerValue.VirtualMachine, pointerValue.Type, pointerValue.Address + pointerValue.Type.GetElementType().GetValueSize()); + + AssertValue(2, pointerValue2.Value); + + + param = frame.Method.GetParameters()[1]; + Assert.AreEqual("BlittableStruct*", param.ParameterType.Name); + + pointerValue = frame.GetValue(param) as PointerValue; + Assert.AreEqual("BlittableStruct*", pointerValue.Type.Name); + + var structValue = pointerValue.Value as StructMirror; + Assert.AreEqual("BlittableStruct", structValue.Type.Name); + + object f = structValue.Fields[0]; + AssertValue (2, f); + f = structValue.Fields[1]; + AssertValue (3.0, f); + + } } // class DebuggerTests } // namespace diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 0113fbcde38..c3c32c98558 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -275,7 +275,7 @@ typedef struct { #define HEADER_LENGTH 11 #define MAJOR_VERSION 2 -#define MINOR_VERSION 45 +#define MINOR_VERSION 46 typedef enum { CMD_SET_VM = 1, @@ -291,7 +291,8 @@ typedef enum { CMD_SET_TYPE = 23, CMD_SET_MODULE = 24, CMD_SET_FIELD = 25, - CMD_SET_EVENT = 64 + CMD_SET_EVENT = 64, + CMD_SET_POINTER = 65 } CommandSet; typedef enum { @@ -496,7 +497,8 @@ typedef enum { CMD_TYPE_GET_INTERFACES = 16, CMD_TYPE_GET_INTERFACE_MAP = 17, CMD_TYPE_IS_INITIALIZED = 18, - CMD_TYPE_CREATE_INSTANCE = 19 + CMD_TYPE_CREATE_INSTANCE = 19, + CMD_TYPE_GET_VALUE_SIZE = 20 } CmdType; typedef enum { @@ -520,6 +522,10 @@ typedef enum { } CmdString; typedef enum { + CMD_POINTER_GET_VALUE = 1 +} CmdPointer; + +typedef enum { CMD_OBJECT_REF_GET_TYPE = 1, CMD_OBJECT_REF_GET_VALUES = 2, CMD_OBJECT_REF_IS_COLLECTED = 3, @@ -6333,6 +6339,8 @@ buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain, buffer_add_byte (buf, t->type); buffer_add_long (buf, val); + if (CHECK_PROTOCOL_VERSION(2, 46)) + buffer_add_typeid (buf, domain, mono_class_from_mono_type (t)); break; } handle_ref: @@ -9003,6 +9011,13 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint buffer_add_objid (buf, obj); break; } + case CMD_TYPE_GET_VALUE_SIZE: { + int32_t value_size; + + value_size = mono_class_value_size (klass, NULL); + buffer_add_int (buf, value_size); + break; + } default: return ERR_NOT_IMPLEMENTED; } @@ -9999,6 +10014,34 @@ string_commands (int command, guint8 *p, guint8 *end, Buffer *buf) } static ErrorCode +pointer_commands (int command, guint8 *p, guint8 *end, Buffer *buf) +{ + ErrorCode err; + gint64 addr; + MonoClass* klass; + MonoDomain* domain = NULL; + + switch (command) { + case CMD_POINTER_GET_VALUE: + addr = decode_long (p, &p, end); + klass = decode_typeid (p, &p, end, &domain, &err); + if (err != ERR_NONE) + return err; + + if (klass->byval_arg.type != MONO_TYPE_PTR) + return ERR_INVALID_ARGUMENT; + + buffer_add_value (buf, &klass->element_class->byval_arg, (gpointer)addr, domain); + + break; + default: + return ERR_NOT_IMPLEMENTED; + } + + return ERR_NONE; +} + +static ErrorCode object_commands (int command, guint8 *p, guint8 *end, Buffer *buf) { ERROR_DECL (error); @@ -10199,6 +10242,8 @@ command_set_to_string (CommandSet command_set) return "FIELD"; case CMD_SET_EVENT: return "EVENT"; + case CMD_SET_POINTER: + return "POINTER"; default: return ""; } @@ -10295,7 +10340,9 @@ static const char* type_cmds_str[] = { "GET_METHODS_BY_NAME_FLAGS", "GET_INTERFACES", "GET_INTERFACE_MAP", - "IS_INITIALIZED" + "IS_INITIALIZED", + "CREATE_INSTANCE", + "GET_VALUE_SIZE" }; static const char* stack_frame_cmds_str[] = { @@ -10318,6 +10365,10 @@ static const char* string_cmds_str[] = { "GET_CHARS" }; +static const char* pointer_cmds_str[] = { + "GET_VALUE" +}; + static const char* object_cmds_str[] = { "GET_TYPE", "GET_VALUES", @@ -10391,6 +10442,10 @@ cmd_to_string (CommandSet set, int command) cmds = event_cmds_str; cmds_len = G_N_ELEMENTS (event_cmds_str); break; + case CMD_SET_POINTER: + cmds = pointer_cmds_str; + cmds_len = G_N_ELEMENTS (pointer_cmds_str); + break; default: return NULL; } @@ -10568,6 +10623,9 @@ debugger_thread (void *arg) case CMD_SET_STRING_REF: err = string_commands (command, p, end, &buf); break; + case CMD_SET_POINTER: + err = pointer_commands (command, p, end, &buf); + break; case CMD_SET_OBJECT_REF: err = object_commands (command, p, end, &buf); break; |