#include "interp/interp.h"
#include "debugger-engine.h"
#include "mono/metadata/debug-mono-ppdb.h"
+#include "mono/metadata/custom-attrs-internals.h"
/*
* On iOS we can't use System.Environment.Exit () as it will do the wrong
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 52
+#define MINOR_VERSION 53
typedef enum {
CMD_SET_VM = 1,
typedef enum {
VALUE_TYPE_ID_NULL = 0xf0,
VALUE_TYPE_ID_TYPE = 0xf1,
- VALUE_TYPE_ID_PARENT_VTYPE = 0xf2
+ VALUE_TYPE_ID_PARENT_VTYPE = 0xf2,
+ VALUE_TYPE_ID_FIXED_ARRAY = 0xf3
} ValueTypeId;
typedef enum {
static int ss_create_init_args (SingleStepReq *ss_req, SingleStepArgs *args);
static void ss_args_destroy (SingleStepArgs *ss_args);
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (fixed_buffer, "System.Runtime.CompilerServices", "FixedBufferAttribute")
+
#ifndef DISABLE_SOCKET_TRANSPORT
static void
register_socket_transport (void);
return FALSE;
}
+static gint32 isFixedSizeArray (MonoClassField *f)
+{
+ ERROR_DECL (error);
+ if (!CHECK_PROTOCOL_VERSION (2, 53) || f->type->type != MONO_TYPE_VALUETYPE) {
+ return 1;
+ }
+ MonoCustomAttrInfo *cinfo;
+ MonoCustomAttrEntry *attr;
+ int aindex;
+ gint32 ret = 1;
+ cinfo = mono_custom_attrs_from_field_checked (f->parent, f, error);
+ if (!is_ok (error))
+ return ret;
+ attr = NULL;
+ if (cinfo) {
+ for (aindex = 0; aindex < cinfo->num_attrs; ++aindex) {
+ MonoClass *ctor_class = cinfo->attrs [aindex].ctor->klass;
+ MonoClass *fixed_size_class = mono_class_try_get_fixed_buffer_class ();
+ if (fixed_size_class != NULL && mono_class_has_parent (ctor_class, fixed_size_class)) {
+ attr = &cinfo->attrs [aindex];
+ gpointer *typed_args, *named_args;
+ CattrNamedArg *arginfo;
+ int num_named_args;
+
+ mono_reflection_create_custom_attr_data_args_noalloc (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size,
+ &typed_args, &named_args, &num_named_args, &arginfo, error);
+ if (!is_ok (error))
+ return FALSE;
+ ret = *(gint32*)typed_args [1];
+ g_free (typed_args);
+ g_free (named_args);
+ g_free (arginfo);
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
static gboolean
process_filter_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
{
tls->filter_state.valid = FALSE;
}
+static void
+buffer_add_fixed_array (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
+ gboolean as_vtype, GHashTable *parent_vtypes, gint32 len_fixed_array)
+{
+ buffer_add_byte (buf, VALUE_TYPE_ID_FIXED_ARRAY);
+ buffer_add_byte (buf, t->type);
+ buffer_add_int (buf, len_fixed_array );
+ for (int i = 0; i < len_fixed_array; i++) {
+ switch (t->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ buffer_add_int (buf, ((gint8*)addr)[i]);
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ buffer_add_int (buf, ((gint16*)addr)[i]);
+ break;
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_R4:
+ buffer_add_int (buf, ((gint32*)addr)[i]);
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_R8:
+ buffer_add_long (buf, ((gint64*)addr)[i]);
+ break;
+ case MONO_TYPE_PTR: {
+ gssize val = *(gssize*)addr;
+
+ 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_internal (t));
+ break;
+ }
+ }
+ }
+}
/*
* buffer_add_value_full:
*
*/
static void
buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
- gboolean as_vtype, GHashTable *parent_vtypes)
+ gboolean as_vtype, GHashTable *parent_vtypes, gint32 len_fixed_array)
{
MonoObject *obj;
gboolean boxed_vtype = FALSE;
break;
}
}
-
+
+ if (len_fixed_array > 1 && t->type != MONO_TYPE_VALUETYPE && CHECK_PROTOCOL_VERSION (2, 53))
+ {
+ buffer_add_fixed_array(buf, t, addr, domain, as_vtype, parent_vtypes, len_fixed_array);
+ return;
+ }
switch (t->type) {
case MONO_TYPE_VOID:
buffer_add_byte (buf, t->type);
if (boxed_vtype) {
/*
- * Handle boxed vtypes recursively referencing themselves using fields.
- */
+ * Handle boxed vtypes recursively referencing themselves using fields.
+ */
if (!parent_vtypes)
parent_vtypes = g_hash_table_new (NULL, NULL);
vtype_index = GPOINTER_TO_INT (g_hash_table_lookup (parent_vtypes, addr));
continue;
if (mono_field_is_deleted (f))
continue;
- buffer_add_value_full (buf, f->type, mono_vtype_get_field_addr (addr, f), domain, FALSE, parent_vtypes);
+ buffer_add_value_full (buf, f->type, mono_vtype_get_field_addr (addr, f), domain, FALSE, parent_vtypes, len_fixed_array != 1 ? len_fixed_array : isFixedSizeArray(f));
}
if (boxed_vtype) {
static void
buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain)
{
- buffer_add_value_full (buf, t, addr, domain, FALSE, NULL);
+ buffer_add_value_full (buf, t, addr, domain, FALSE, NULL, 1);
}
static gboolean
return ERR_NONE;
}
-
+static ErrorCode decode_fixed_size_array_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit, gboolean check_field_datatype)
+{
+ ErrorCode err = ERR_NONE;
+ int fixedSizeLen = 1;
+ int newType = MONO_TYPE_END;
+ if (CHECK_PROTOCOL_VERSION (2, 53)) {
+ newType = decode_byte (buf, &buf, limit);
+ fixedSizeLen = decode_int (buf, &buf, limit);
+ //t->type = newType;
+ }
+ for (int i = 0 ; i < fixedSizeLen; i++) {
+ switch (newType) {
+ case MONO_TYPE_BOOLEAN:
+ ((guint8*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_CHAR:
+ ((gunichar2*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_I1:
+ ((gint8*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_U1:
+ ((guint8*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_I2:
+ ((gint16*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_U2:
+ ((guint16*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_I4:
+ ((gint32*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_U4:
+ ((guint32*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_I8:
+ ((gint64*)addr)[i] = decode_long (buf, &buf, limit);
+ break;
+ case MONO_TYPE_U8:
+ ((guint64*)addr)[i] = decode_long (buf, &buf, limit);
+ break;
+ case MONO_TYPE_R4:
+ ((guint32*)addr)[i] = decode_int (buf, &buf, limit);
+ break;
+ case MONO_TYPE_R8:
+ ((guint64*)addr)[i] = decode_long (buf, &buf, limit);
+ break;
+ }
+ }
+ *endbuf = buf;
+ return err;
+}
static ErrorCode
decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit, gboolean check_field_datatype)
{
ErrorCode err;
-
if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
!(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
+ !(type == VALUE_TYPE_ID_FIXED_ARRAY) &&
!(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) &&
!(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) &&
!(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE) &&
g_free (name);
return ERR_INVALID_ARGUMENT;
}
+ if (type == VALUE_TYPE_ID_FIXED_ARRAY && t->type != MONO_TYPE_VALUETYPE) {
+ decode_fixed_size_array_internal (t, type, domain, addr, buf, endbuf, limit, check_field_datatype);
+ return ERR_NONE;
+ }
switch (t->type) {
case MONO_TYPE_BOOLEAN:
/* This can happen when round-tripping boxed vtypes */
/*
- * Obtain vtype class.
- * Same as the beginning of the handle_vtype case above.
- */
+ * Obtain vtype class.
+ * Same as the beginning of the handle_vtype case above.
+ */
buf2 = buf;
is_enum = decode_byte (buf, &buf, limit);
if (is_enum)
break;
}
+
*endbuf = buf;
return ERR_NONE;
case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
reg_val = mono_arch_context_get_int_reg (ctx, reg);
- buffer_add_value_full (buf, t, ®_val, domain, as_vtype, NULL);
+ buffer_add_value_full (buf, t, ®_val, domain, as_vtype, NULL, 1);
break;
case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
addr = (guint8 *)mono_arch_context_get_int_reg (ctx, reg);
//printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
- buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL);
+ buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL, 1);
break;
case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
NOT_IMPLEMENTED;
gaddr = (guint8 *)*(gpointer*)addr;
g_assert (gaddr);
- buffer_add_value_full (buf, t, gaddr, domain, as_vtype, NULL);
+ buffer_add_value_full (buf, t, gaddr, domain, as_vtype, NULL, 1);
break;
case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL: {
MonoDebugVarInfo *info_var = jit->gsharedvt_info_var;
addr = locals + GPOINTER_TO_INT (info->entries [idx]);
- buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL);
+ buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL, 1);
break;
}
addr = (guint8*)mini_get_interp_callbacks ()->frame_get_arg (frame->interp_frame, pos);
- buffer_add_value_full (buf, sig->params [pos], addr, frame->de.domain, FALSE, NULL);
+ buffer_add_value_full (buf, sig->params [pos], addr, frame->de.domain, FALSE, NULL, 1);
} else {
g_assert (pos >= 0 && pos < jit->num_params);
addr = (guint8*)mini_get_interp_callbacks ()->frame_get_local (frame->interp_frame, pos);
- buffer_add_value_full (buf, header->locals [pos], addr, frame->de.domain, FALSE, NULL);
+ buffer_add_value_full (buf, header->locals [pos], addr, frame->de.domain, FALSE, NULL, 1);
} else {
g_assert (pos >= 0 && pos < jit->num_locals);
addr = (guint8*)mini_get_interp_callbacks ()->frame_get_this (frame->interp_frame);
- buffer_add_value_full (buf, m_class_get_this_arg (frame->actual_method->klass), addr, frame->de.domain, FALSE, NULL);
+ buffer_add_value_full (buf, m_class_get_this_arg (frame->actual_method->klass), addr, frame->de.domain, FALSE, NULL, 1);
} else {
add_var (buf, jit, m_class_get_this_arg (frame->actual_method->klass), jit->this_var, &frame->ctx, frame->de.domain, TRUE);
}
addr = (guint8*)mini_get_interp_callbacks ()->frame_get_this (frame->interp_frame);
- buffer_add_value_full (buf, m_class_get_byval_arg (frame->api_method->klass), addr, frame->de.domain, FALSE, NULL);
+ buffer_add_value_full (buf, m_class_get_byval_arg (frame->api_method->klass), addr, frame->de.domain, FALSE, NULL, 1);
} else {
add_var (buf, jit, m_class_get_byval_arg (frame->api_method->klass), jit->this_var, &frame->ctx, frame->de.domain, TRUE);
}