diff options
author | Jonathan Chambers <joncham@gmail.com> | 2018-02-25 09:14:11 +0300 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2018-02-25 09:14:11 +0300 |
commit | 67c1708677af8c5a3a8955937775a61de9e36e0f (patch) | |
tree | 76f2996f3cd0ac42485bcafc254787390b56b8d4 /mcs/class | |
parent | 9bbe5e5e5f807884ea66aa762dae3f8c240652e2 (diff) |
Add PointerValue.Value to dereference and access pointer value. (#6840)
Diffstat (limited to 'mcs/class')
6 files changed, 116 insertions, 11 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 |