Skip to content

Commit ecef34c

Browse files
committed
Add PointerValue.Value to dereference and access pointer value.
1 parent bc0ff2f commit ecef34c

File tree

7 files changed

+178
-17
lines changed

7 files changed

+178
-17
lines changed

mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ public abstract class Connection
420420
* with newer runtimes, and vice versa.
421421
*/
422422
internal const int MAJOR_VERSION = 2;
423-
internal const int MINOR_VERSION = 45;
423+
internal const int MINOR_VERSION = 46;
424424

425425
enum WPSuspendPolicy {
426426
NONE = 0,
@@ -442,7 +442,8 @@ enum CommandSet {
442442
TYPE = 23,
443443
MODULE = 24,
444444
FIELD = 25,
445-
EVENT = 64
445+
EVENT = 64,
446+
POINTER = 65
446447
}
447448

448449
enum EventKind {
@@ -574,7 +575,8 @@ enum CmdType {
574575
GET_INTERFACES = 16,
575576
GET_INTERFACE_MAP = 17,
576577
IS_INITIALIZED = 18,
577-
CREATE_INSTANCE = 19
578+
CREATE_INSTANCE = 19,
579+
GET_VALUE_SIZE = 20
578580
}
579581

580582
enum CmdField {
@@ -606,6 +608,10 @@ enum CmdStringRef {
606608
GET_CHARS = 3
607609
}
608610

611+
enum CmdPointer {
612+
GET_VALUE = 1
613+
}
614+
609615
enum CmdObjectRef {
610616
GET_TYPE = 1,
611617
GET_VALUES = 2,
@@ -730,10 +736,12 @@ internal static byte[] EncodePacket (int id, int commandSet, int command, byte[]
730736
}
731737

732738
class PacketReader {
739+
Connection connection;
733740
byte[] packet;
734741
int offset;
735742

736-
public PacketReader (byte[] packet) {
743+
public PacketReader (Connection connection, byte[] packet) {
744+
this.connection = connection;
737745
this.packet = packet;
738746

739747
// For event packets
@@ -845,9 +853,16 @@ public ValueImpl ReadValue () {
845853
return new ValueImpl { Type = etype, Value = ReadDouble () };
846854
case ElementType.I:
847855
case ElementType.U:
848-
case ElementType.Ptr:
849856
// FIXME: The client and the debuggee might have different word sizes
850857
return new ValueImpl { Type = etype, Value = ReadLong () };
858+
case ElementType.Ptr:
859+
long value = ReadLong ();
860+
if (connection.Version.AtLeast (2, 46)) {
861+
long pointerClass = ReadId ();
862+
return new ValueImpl { Type = etype, Klass = pointerClass, Value = value };
863+
} else {
864+
return new ValueImpl { Type = etype, Value = value };
865+
}
851866
case ElementType.String:
852867
case ElementType.SzArray:
853868
case ElementType.Class:
@@ -1283,7 +1298,7 @@ bool ReceivePacket () {
12831298
if (cb != null)
12841299
cb.Invoke (id, packet);
12851300
} else {
1286-
PacketReader r = new PacketReader (packet);
1301+
PacketReader r = new PacketReader (this, packet);
12871302

12881303
if (r.CommandSet == CommandSet.EVENT && r.Command == (int)CmdEvent.COMPOSITE) {
12891304
int spolicy = r.ReadByte ();
@@ -1502,7 +1517,7 @@ int Send (CommandSet command_set, int command, PacketWriter packet, Action<Packe
15021517
if (EnableConnectionLogging)
15031518
LogPacket (packet_id, encoded_packet, p, command_set, command, watch);
15041519
/* Run the callback on a tp thread to avoid blocking the receive thread */
1505-
PacketReader r = new PacketReader (p);
1520+
PacketReader r = new PacketReader (this, p);
15061521
cb.BeginInvoke (r, null, null);
15071522
};
15081523
reply_cb_counts [id] = count;
@@ -1549,7 +1564,7 @@ PacketReader SendReceive (CommandSet command_set, int command, PacketWriter pack
15491564
if (reply_packets.ContainsKey (packetId)) {
15501565
byte[] reply = reply_packets [packetId];
15511566
reply_packets.Remove (packetId);
1552-
PacketReader r = new PacketReader (reply);
1567+
PacketReader r = new PacketReader (this, reply);
15531568

15541569
if (EnableConnectionLogging)
15551570
LogPacket (packetId, encoded_packet, reply, command_set, command, watch);
@@ -2297,6 +2312,11 @@ internal long Type_CreateInstance (long id) {
22972312
return r.ReadId ();
22982313
}
22992314

2315+
internal int Type_GetValueSize (long id) {
2316+
PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUE_SIZE, new PacketWriter ().WriteId (id));
2317+
return r.ReadInt ();
2318+
}
2319+
23002320
/*
23012321
* FIELD
23022322
*/
@@ -2475,7 +2495,16 @@ internal char[] String_GetChars (long id, int index, int length) {
24752495
for (int i = 0; i < length; ++i)
24762496
res [i] = (char)r.ReadShort ();
24772497
return res;
2478-
}
2498+
}
2499+
2500+
/*
2501+
* POINTERS
2502+
*/
2503+
2504+
internal ValueImpl Pointer_GetValue (long address, TypeMirror type)
2505+
{
2506+
return SendReceive (CommandSet.POINTER, (int)CmdPointer.GET_VALUE, new PacketWriter ().WriteLong (address).WriteId (type.Id)).ReadValue ();
2507+
}
24792508

24802509
/*
24812510
* OBJECTS

mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ public TypeMirror Type {
4848
get { return type; }
4949
}
5050

51+
// Since protocol version 2.46
52+
public Value Value {
53+
get {
54+
if (Address == 0)
55+
return null;
56+
57+
return vm.DecodeValue (vm.conn.Pointer_GetValue (Address, Type));
58+
}
59+
}
60+
5161
public override bool Equals (object obj) {
5262
if (obj != null && obj is PointerValue)
5363
return addr == (obj as PointerValue).addr;

mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,11 @@ public Value NewInstance () {
842842
return vm.GetObject (vm.conn.Type_CreateInstance (id));
843843
}
844844

845+
// Since protocol version 2.46
846+
public int GetValueSize () {
847+
return vm.conn.Type_GetValueSize (id);
848+
}
849+
845850
// Since protocol version 2.11
846851
public TypeMirror[] GetInterfaces () {
847852
if (ifaces == null)

mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/VirtualMachine.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,8 +616,11 @@ internal Value DecodeValue (ValueImpl v) {
616616
}
617617

618618
internal Value DecodeValue (ValueImpl v, Dictionary<int, Value> parent_vtypes) {
619-
if (v.Value != null)
619+
if (v.Value != null) {
620+
if (Version.AtLeast (2, 46) && v.Type == ElementType.Ptr)
621+
return new PointerValue(this, GetType(v.Klass), (long)v.Value);
620622
return new PrimitiveValue (this, v.Value);
623+
}
621624

622625
switch (v.Type) {
623626
case ElementType.Void:
@@ -682,8 +685,11 @@ internal ValueImpl EncodeValue (Value v, List<Value> duplicates = null) {
682685
duplicates.Add (v);
683686

684687
return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeValues ((v as StructMirror).Fields, duplicates) };
688+
} else if (v is PointerValue) {
689+
PointerValue val = (PointerValue)v;
690+
return new ValueImpl { Type = ElementType.Ptr, Klass = val.Type.Id, Value = val.Address };
685691
} else {
686-
throw new NotSupportedException ();
692+
throw new NotSupportedException ("Value of type " + v.GetType());
687693
}
688694
}
689695

mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,12 @@ public override string ToString () {
145145
}
146146
}
147147

148+
149+
public struct BlittableStruct {
150+
public int i;
151+
public double d;
152+
}
153+
148154
public class GClass<T> {
149155
public T field;
150156
public static T static_field;
@@ -343,6 +349,7 @@ public static int Main (String[] args) {
343349
gc_suspend ();
344350
set_ip ();
345351
step_filters ();
352+
pointers ();
346353
if (args.Length > 0 && args [0] == "local-reflect")
347354
local_reflect ();
348355
if (args.Length > 0 && args [0] == "domain-test")
@@ -1720,6 +1727,18 @@ public void attach () {
17201727
attach_break ();
17211728
}
17221729
}
1730+
1731+
public static unsafe void pointer_arguments (int* a, BlittableStruct* s) {
1732+
*a = 0;
1733+
}
1734+
1735+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
1736+
public static unsafe void pointers () {
1737+
int[] a = new [] {1,2,3};
1738+
BlittableStruct s = new BlittableStruct () { i = 2, d = 3.0 };
1739+
fixed (int* pa = a)
1740+
pointer_arguments (pa, &s);
1741+
}
17231742
}
17241743

17251744
public class SentinelClass : MarshalByRefObject {

mcs/class/Mono.Debugger.Soft/Test/dtest.cs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ void AssertValue (object expected, object val) {
324324
Assert.AreEqual (expected, (val as StringMirror).Value);
325325
} else if (val is StructMirror && (val as StructMirror).Type.Name == "IntPtr") {
326326
AssertValue (expected, (val as StructMirror).Fields [0]);
327+
} else if (val is PointerValue) {
328+
Assert.AreEqual (expected, (val as PointerValue).Address);
327329
} else {
328330
Assert.IsTrue (val is PrimitiveValue);
329331
Assert.AreEqual (expected, (val as PrimitiveValue).Value);
@@ -4361,6 +4363,38 @@ public void Hash ()
43614363
}
43624364
}
43634365

4364-
}
4366+
[Test]
4367+
public void Pointer_GetValue () {
4368+
var e = run_until ("pointer_arguments");
4369+
var frame = e.Thread.GetFrames () [0];
4370+
4371+
var param = frame.Method.GetParameters()[0];
4372+
Assert.AreEqual("Int32*", param.ParameterType.Name);
4373+
4374+
var pointerValue = frame.GetValue(param) as PointerValue;
4375+
Assert.AreEqual("Int32*", pointerValue.Type.Name);
4376+
4377+
AssertValue(1, pointerValue.Value);
4378+
4379+
var pointerValue2 = new PointerValue (pointerValue.VirtualMachine, pointerValue.Type, pointerValue.Address + pointerValue.Type.GetElementType().GetValueSize());
4380+
4381+
AssertValue(2, pointerValue2.Value);
43654382

4366-
}
4383+
4384+
param = frame.Method.GetParameters()[1];
4385+
Assert.AreEqual("BlittableStruct*", param.ParameterType.Name);
4386+
4387+
pointerValue = frame.GetValue(param) as PointerValue;
4388+
Assert.AreEqual("BlittableStruct*", pointerValue.Type.Name);
4389+
4390+
var structValue = pointerValue.Value as StructMirror;
4391+
Assert.AreEqual("BlittableStruct", structValue.Type.Name);
4392+
4393+
object f = structValue.Fields[0];
4394+
AssertValue (2, f);
4395+
f = structValue.Fields[1];
4396+
AssertValue (3.0, f);
4397+
4398+
}
4399+
} // class DebuggerTests
4400+
} // namespace

0 commit comments

Comments
 (0)