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 {
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)
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) {
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");
}
}
+ 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");
}
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 ();
}
[Test]
+ [Category ("only5")]
public void Type_GetValue () {
Event e = run_until ("o1");
StackFrame frame = e.Thread.GetFrames () [0];
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);
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 {
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) {
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;
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);
}