Add support for accessing ThreadStatic fields in sdb. Fixes #645217.
authorZoltan Varga <vargaz@gmail.com>
Sun, 19 Dec 2010 22:12:04 +0000 (23:12 +0100)
committerZoltan Varga <vargaz@gmail.com>
Sun, 19 Dec 2010 22:13:04 +0000 (23:13 +0100)
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/TypeMirror.cs
mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mono/mini/debugger-agent.c

index 78028f2637be375c856969acb02312cb3a03eb05..8bd711f315c3a273504b3ee037fe319c9853457a 100644 (file)
@@ -437,7 +437,9 @@ namespace Mono.Debugger.Soft
                        GET_FIELD_CATTRS = 11,
                        GET_PROPERTY_CATTRS = 12,
                        /* FIXME: Merge into GET_SOURCE_FILES when the major protocol version is increased */
-                       GET_SOURCE_FILES_2 = 13
+                       GET_SOURCE_FILES_2 = 13,
+                       /* FIXME: Merge into GET_VALUES when the major protocol version is increased */
+                       GET_VALUES_2 = 14
                }
 
                enum CmdStackFrame {
@@ -1672,9 +1674,13 @@ namespace Mono.Debugger.Soft
                        return SendReceive (CommandSet.TYPE, (int)CmdType.GET_OBJECT, new PacketWriter ().WriteId (id)).ReadId ();
                }
 
-               public ValueImpl[] Type_GetValues (long id, long[] fields) {
+               public ValueImpl[] Type_GetValues (long id, long[] fields, long thread_id) {
                        int len = fields.Length;
-                       PacketReader r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
+                       PacketReader r;
+                       if (thread_id != 0)
+                               r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES_2, new PacketWriter ().WriteId (id).WriteId (thread_id).WriteInt (len).WriteIds (fields));
+                       else
+                               r = SendReceive (CommandSet.TYPE, (int)CmdType.GET_VALUES, new PacketWriter ().WriteId (id).WriteInt (len).WriteIds (fields));
 
                        ValueImpl[] res = new ValueImpl [len];
                        for (int i = 0; i < len; ++i)
index 51ec6eb1c92eec0626ebe6214c17abe1b58509d1..d17fac5dd8d1d8d9c4668b4bcc00af8f68d345e9 100644 (file)
@@ -442,7 +442,7 @@ namespace Mono.Debugger.Soft
                        return GetValues (new FieldInfoMirror [] { field }) [0];
                }
 
-               public Value[] GetValues (IList<FieldInfoMirror> fields) {
+               public Value[] GetValues (IList<FieldInfoMirror> fields, ThreadMirror thread) {
                        if (fields == null)
                                throw new ArgumentNullException ("fields");
                        foreach (FieldInfoMirror f in fields) {
@@ -454,7 +454,7 @@ namespace Mono.Debugger.Soft
                        for (int i = 0; i < fields.Count; ++i)
                                ids [i] = fields [i].Id;
                        try {
-                               return vm.DecodeValues (vm.conn.Type_GetValues (id, ids));
+                               return vm.DecodeValues (vm.conn.Type_GetValues (id, ids, thread !=  null ? thread.Id : 0));
                        } catch (CommandException ex) {
                                if (ex.ErrorCode == ErrorCode.INVALID_FIELDID)
                                        throw new ArgumentException ("One of the fields is not valid for this type.", "fields");
@@ -463,6 +463,20 @@ namespace Mono.Debugger.Soft
                        }
                }
 
+               public Value[] GetValues (IList<FieldInfoMirror> fields) {
+                       return GetValues (fields, null);
+               }
+
+               /*
+                * Return the value of the [ThreadStatic] field FIELD on the thread THREAD.
+                */
+               public Value GetValue (FieldInfoMirror field, ThreadMirror thread) {
+                       if (thread == null)
+                               throw new ArgumentNullException ("thread");
+                       CheckMirror (thread);
+                       return GetValues (new FieldInfoMirror [] { field }, thread) [0];
+               }
+
                public void SetValues (IList<FieldInfoMirror> fields, Value[] values) {
                        if (fields == null)
                                throw new ArgumentNullException ("fields");
index 55b6092e84b640c353f96bba26071bfd12d3ef01..3e445c3ed667ddad340d8af4de7a1f2cf5dccbfe 100644 (file)
@@ -156,6 +156,8 @@ public class Tests : TestsBase
        }
 
        public static int Main (String[] args) {
+               tls_i = 42;
+
                if (args.Length > 0 && args [0] == "suspend-test")
                        /* This contains an infinite loop, so execute it conditionally */
                        suspend ();
index fcf774d470577abacd37cff9180a18b1e68bd3df..86a953d8216eb2df97d682ee76ded6fd69b9d4e8 100644 (file)
@@ -1086,6 +1086,7 @@ public class DebuggerTests
        }
 
        [Test]
+       [Category ("only5")]
        public void Type_GetValue () {
                Event e = run_until ("o1");
                StackFrame frame = e.Thread.GetFrames () [0];
@@ -1118,6 +1119,10 @@ public class DebuggerTests
                f = t.GetValue (parent.GetField ("base_static_s"));
                AssertValue ("C", f);
 
+               // thread static field
+               f = t.GetValue (t.GetField ("tls_i"), e.Thread);
+               AssertValue (42, f);
+
                // Argument checking
                AssertThrows<ArgumentNullException> (delegate () {
                        t.GetValue (null);
index db390ba7c67972d2ccf960a0330747484a9e2f7d..24ca62837034cd7599c48987b0deb0328e8c5def 100644 (file)
@@ -426,6 +426,7 @@ typedef enum {
        CMD_TYPE_GET_FIELD_CATTRS = 11,
        CMD_TYPE_GET_PROPERTY_CATTRS = 12,
        CMD_TYPE_GET_SOURCE_FILES_2 = 13,
+       CMD_TYPE_GET_VALUES_2 = 14
 } CmdType;
 
 typedef enum {
@@ -6042,13 +6043,28 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
                buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
                break;
        }
-       case CMD_TYPE_GET_VALUES: {
+       case CMD_TYPE_GET_VALUES:
+       case CMD_TYPE_GET_VALUES_2: {
                guint8 *val;
                MonoClassField *f;
                MonoVTable *vtable;
                MonoClass *k;
                int len, i;
                gboolean found;
+               MonoThread *thread_obj;
+               MonoInternalThread *thread = NULL;
+               guint32 special_static_type;
+
+               if (command == CMD_TYPE_GET_VALUES_2) {
+                       int objid = decode_objid (p, &p, end);
+                       int err;
+
+                       err = get_object (objid, (MonoObject**)&thread_obj);
+                       if (err)
+                               return err;
+
+                       thread = THREAD_TO_INTERNAL (thread_obj);
+               }
 
                len = decode_int (p, &p, end);
                for (i = 0; i < len; ++i) {
@@ -6058,8 +6074,11 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
 
                        if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
                                return ERR_INVALID_FIELDID;
-                       if (mono_class_field_is_special_static (f))
-                               return ERR_INVALID_FIELDID;
+                       special_static_type = mono_class_field_get_special_static_type (f);
+                       if (special_static_type != SPECIAL_STATIC_NONE) {
+                               if (!(thread && special_static_type == SPECIAL_STATIC_THREAD))
+                                       return ERR_INVALID_FIELDID;
+                       }
 
                        /* Check that the field belongs to the object */
                        found = FALSE;
@@ -6074,7 +6093,7 @@ type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint
 
                        vtable = mono_class_vtable (domain, f->parent);
                        val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
-                       mono_field_static_get_value (vtable, f, val);
+                       mono_field_static_get_value_for_thread (thread ? thread : mono_thread_internal_current (), vtable, f, val);
                        buffer_add_value (buf, f->type, val, domain);
                        g_free (val);
                }