X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Ficall.c;h=beb055f8978e11d3cdff3198a189093c23c7f623;hb=ad43d7bd734184dcb61fc26834674a1ed64fb83b;hp=12f85e374508960e7676d0f2a9243368cdb2dcec;hpb=47dcb9768779171e168c0fe626bdc58206dbfa43;p=mono.git diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 12f85e37450..beb055f8978 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -67,6 +67,8 @@ #include #include #include +#include +#include #include #include #include @@ -74,6 +76,8 @@ #include #include #include +#include +#include #if defined (HOST_WIN32) #include @@ -81,60 +85,26 @@ #endif #include "decimal.h" +extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL; + static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void); static MonoArray* type_array_from_modifiers (MonoImage *image, MonoType *type, int optional); -/* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes. - * It works by allocating an initial small array on stack and only going to malloc'd memory if needed. - */ -typedef struct { - void **data; - int size; - int capacity; -} MonoPtrArray; - -#define MONO_PTR_ARRAY_MAX_ON_STACK (16) - -#define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\ - (ARRAY).size = 0; \ - (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \ - (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \ -} while (0) - -#define mono_ptr_array_destroy(ARRAY) do {\ - if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \ - mono_gc_free_fixed ((ARRAY).data); \ -} while (0) - -#define mono_ptr_array_append(ARRAY, VALUE) do { \ - if ((ARRAY).size >= (ARRAY).capacity) {\ - void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \ - memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \ - if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \ - mono_gc_free_fixed ((ARRAY).data); \ - (ARRAY).data = __tmp; \ - (ARRAY).capacity *= 2;\ - }\ - ((ARRAY).data [(ARRAY).size++] = VALUE); \ -} while (0) - -#define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \ - ((ARRAY).data [(IDX)] = VALUE); \ -} while (0) - -#define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)]) - -#define mono_ptr_array_size(ARRAY) ((ARRAY).size) - - static inline MonoBoolean is_generic_parameter (MonoType *type) { return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR); } +static void +mono_class_init_or_throw (MonoClass *klass) +{ + if (!mono_class_init (klass)) + mono_raise_exception (mono_class_get_exception_for_failure (klass)); +} + /* * We expect a pointer to a char, not a string */ @@ -151,14 +121,10 @@ mono_double_ParseImpl (char *ptr, double *result) *result = strtod (ptr, &endptr); #else if (*ptr){ -#ifdef _EGLIB_MAJOR - /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */ + /* mono_strtod () is not thread-safe */ EnterCriticalSection (&mono_strtod_mutex); *result = mono_strtod (ptr, &endptr); LeaveCriticalSection (&mono_strtod_mutex); -#else - *result = mono_strtod (ptr, &endptr); -#endif } #endif @@ -259,6 +225,11 @@ ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 ea = (gpointer*)((char*)this->vector + (pos * esize)); va = (gpointer*)((char*)value + sizeof (MonoObject)); + if (mono_class_is_nullable (ec)) { + mono_nullable_init ((guint8*)ea, value, ec); + return; + } + if (!value) { memset (ea, 0, esize); return; @@ -275,7 +246,8 @@ ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 "value", "not a widening conversion")); \ }G_STMT_END -#define INVALID_CAST G_STMT_START{\ +#define INVALID_CAST G_STMT_START{ \ + mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \ mono_raise_exception (mono_get_exception_invalid_cast ()); \ }G_STMT_END @@ -549,9 +521,9 @@ ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value, static MonoArray * ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds) { - MonoClass *aklass; + MonoClass *aklass, *klass; MonoArray *array; - mono_array_size_t *sizes, i; + uintptr_t *sizes, i; gboolean bounded = FALSE; MONO_ARCH_SAVE_REGS; @@ -567,15 +539,18 @@ ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray * if (mono_array_get (lengths, gint32, i) < 0) mono_raise_exception (mono_get_exception_argument_out_of_range (NULL)); + klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); + if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0)) /* vectors are not the same as one dimensional arrays with no-zero bounds */ bounded = TRUE; else bounded = FALSE; - aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded); + aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded); - sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2); + sizes = alloca (aklass->rank * sizeof(intptr_t) * 2); for (i = 0; i < aklass->rank; ++i) { sizes [i] = mono_array_get (lengths, guint32, i); if (bounds) @@ -584,7 +559,7 @@ ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray * sizes [i + aklass->rank] = 0; } - array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank); + array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank); return array; } @@ -592,9 +567,9 @@ ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray * static MonoArray * ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds) { - MonoClass *aklass; + MonoClass *aklass, *klass; MonoArray *array; - mono_array_size_t *sizes, i; + uintptr_t *sizes, i; gboolean bounded = FALSE; MONO_ARCH_SAVE_REGS; @@ -611,15 +586,18 @@ ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) mono_raise_exception (mono_get_exception_argument_out_of_range (NULL)); + klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); + if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0)) /* vectors are not the same as one dimensional arrays with no-zero bounds */ bounded = TRUE; else bounded = FALSE; - aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded); + aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded); - sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2); + sizes = alloca (aklass->rank * sizeof(intptr_t) * 2); for (i = 0; i < aklass->rank; ++i) { sizes [i] = mono_array_get (lengths, guint64, i); if (bounds) @@ -628,7 +606,7 @@ ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray sizes [i + aklass->rank] = 0; } - array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank); + array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank); return array; } @@ -645,7 +623,7 @@ static gint32 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension) { gint32 rank = ((MonoObject *)this)->vtable->klass->rank; - mono_array_size_t length; + uintptr_t length; MONO_ARCH_SAVE_REGS; @@ -711,7 +689,6 @@ ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* d void * source_addr; MonoClass *src_class; MonoClass *dest_class; - int i; MONO_ARCH_SAVE_REGS; @@ -735,6 +712,10 @@ ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* d /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */ if (src_class == mono_defaults.object_class && dest_class->valuetype) { + // FIXME: This is racy + return FALSE; + /* + int i; int has_refs = dest_class->has_references; for (i = source_idx; i < source_idx + length; ++i) { MonoObject *elem = mono_array_get (source, MonoObject*, i); @@ -755,6 +736,7 @@ ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* d memcpy (addr, (char *)elem + sizeof (MonoObject), element_size); } return TRUE; + */ } /* Check if we're copying a char[] <==> (u)short[] */ @@ -765,13 +747,18 @@ ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* d if (mono_class_is_subclass_of (src_class, dest_class, FALSE)) ; /* Case2: object[] -> reftype[] (ArrayList::ToArray) */ - else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) + else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) { + // FIXME: This is racy + return FALSE; + /* + int i; for (i = source_idx; i < source_idx + length; ++i) { MonoObject *elem = mono_array_get (source, MonoObject*, i); if (elem && !mono_object_isinst (elem, dest_class)) return FALSE; } - else + */ + } else return FALSE; } @@ -849,12 +836,9 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoAr int align; const char *field_data; - if (MONO_TYPE_IS_REFERENCE (type) || - (type->type == MONO_TYPE_VALUETYPE && - (!mono_type_get_class (type) || - mono_type_get_class (type)->has_references))) { + if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) { MonoException *exc = mono_get_exception_argument("array", - "Cannot initialize array containing references"); + "Cannot initialize array of non-primitive type."); mono_raise_exception (exc); } @@ -972,6 +956,29 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (M } } +static MonoBoolean +ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void) +{ + guint8 *stack_addr; + guint8 *current; + size_t stack_size; + /* later make this configurable and per-arch */ + int min_size = 4096 * 4 * sizeof (void*); + mono_thread_get_stack_bounds (&stack_addr, &stack_size); + /* if we have no info we are optimistic and assume there is enough room */ + if (!stack_addr) + return TRUE; + current = (guint8 *)&stack_addr; + if (current > stack_addr) { + if ((current - stack_addr) < min_size) + return FALSE; + } else { + if (current - (stack_addr - stack_size) < min_size) + return FALSE; + } + return TRUE; +} + static MonoObject * ves_icall_System_Object_MemberwiseClone (MonoObject *this) { @@ -1173,13 +1180,13 @@ mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj) } static gint32 -ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj) +ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance) { MONO_ARCH_SAVE_REGS; MONO_CHECK_ARG_NULL (obj); - return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE); + return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE); } static gint32 @@ -1319,19 +1326,27 @@ type_from_name (const char *str, MonoBoolean ignoreCase) * Dec 10, 2005 - Martin. */ - if (dest) + if (dest) { assembly = dest->klass->image->assembly; - else { + type_resolve = TRUE; + } else { g_warning (G_STRLOC); } } - if (assembly) + if (assembly) { + /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */ type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve); - + } + if (!info.assembly.name && !type) /* try mscorlib */ type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve); + if (assembly && !type && type_resolve) { + type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */ + type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve); + } + mono_reflection_free_type_info (&info); g_free (temp_str); @@ -1382,11 +1397,9 @@ static MonoReflectionType* ves_icall_type_from_handle (MonoType *handle) { MonoDomain *domain = mono_domain_get (); - MonoClass *klass = mono_class_from_mono_type (handle); MONO_ARCH_SAVE_REGS; - mono_class_init (klass); return mono_type_get_object (domain, handle); } @@ -1465,20 +1478,22 @@ handle_enum: return TYPECODE_SINGLE; case MONO_TYPE_R8: return TYPECODE_DOUBLE; - case MONO_TYPE_VALUETYPE: - if (type->type->data.klass->enumtype) { - t = mono_class_enum_basetype (type->type->data.klass)->type; + case MONO_TYPE_VALUETYPE: { + MonoClass *klass = type->type->data.klass; + + if (klass->enumtype) { + t = mono_class_enum_basetype (klass)->type; goto handle_enum; - } else { - MonoClass *k = type->type->data.klass; - if (strcmp (k->name_space, "System") == 0) { - if (strcmp (k->name, "Decimal") == 0) + } else if (mono_is_corlib_image (klass->image)) { + if (strcmp (klass->name_space, "System") == 0) { + if (strcmp (klass->name, "Decimal") == 0) return TYPECODE_DECIMAL; - else if (strcmp (k->name, "DateTime") == 0) + else if (strcmp (klass->name, "DateTime") == 0) return TYPECODE_DATETIME; } } return TYPECODE_OBJECT; + } case MONO_TYPE_STRING: return TYPECODE_STRING; case MONO_TYPE_SZARRAY: @@ -1490,9 +1505,9 @@ handle_enum: return TYPECODE_OBJECT; case MONO_TYPE_CLASS: { - MonoClass *k = type->type->data.klass; - if (strcmp (k->name_space, "System") == 0) { - if (strcmp (k->name, "DBNull") == 0) + MonoClass *klass = type->type->data.klass; + if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) { + if (strcmp (klass->name, "DBNull") == 0) return TYPECODE_DBNULL; } } @@ -1524,12 +1539,42 @@ ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, M klass = mono_class_from_mono_type (type->type); klassc = mono_class_from_mono_type (c->type); + /* Interface check requires a more complex setup so we + * only do for them. Otherwise we simply avoid mono_class_init. + */ + if (check_interfaces) { + mono_class_init_or_throw (klass); + mono_class_init_or_throw (klassc); + } else if (!klass->supertypes || !klassc->supertypes) { + mono_loader_lock (); + mono_class_setup_supertypes (klass); + mono_class_setup_supertypes (klassc); + mono_loader_unlock (); + } + if (type->type->byref) return klassc == mono_defaults.object_class; return mono_class_is_subclass_of (klass, klassc, check_interfaces); } +static gboolean +mono_type_is_primitive (MonoType *type) +{ + return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) || + type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U; +} + +static MonoType* +mono_type_get_underlying_type_ignore_byref (MonoType *type) +{ + if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) + return mono_class_enum_basetype (type->data.klass); + if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype) + return mono_class_enum_basetype (type->data.generic_class->container_class); + return type; +} + static guint32 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c) { @@ -1546,9 +1591,34 @@ ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType klass = mono_class_from_mono_type (type->type); klassc = mono_class_from_mono_type (c->type); - if (type->type->byref && !c->type->byref) + mono_class_init_or_throw (klass); + mono_class_init_or_throw (klassc); + + if (type->type->byref ^ c->type->byref) return FALSE; + if (type->type->byref) { + MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type); + MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type); + + klass = mono_class_from_mono_type (t); + klassc = mono_class_from_mono_type (ot); + + if (mono_type_is_primitive (t)) { + return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size; + } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) { + return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num; + } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) { + return t->type == ot->type; + } else { + if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR) + return FALSE; + + if (klass->valuetype) + return klass == klassc; + return klass->valuetype == klassc->valuetype; + } + } return mono_class_is_assignable_from (klass, klassc); } @@ -1556,6 +1626,7 @@ static guint32 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj) { MonoClass *klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); return mono_object_isinst (obj, klass) != NULL; } @@ -1563,9 +1634,6 @@ static guint32 ves_icall_get_attributes (MonoReflectionType *type) { MonoClass *klass = mono_class_from_mono_type (type->type); - - MONO_ARCH_SAVE_REGS; - return klass->flags; } @@ -1627,23 +1695,32 @@ ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField static MonoArray* ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional) { - MonoType *type = field->field->type; + MonoError error; + MonoType *type = mono_field_get_type_checked (field->field, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); return type_array_from_modifiers (field->field->parent->image, type, optional); } +static int +vell_icall_get_method_attributes (MonoMethod *method) +{ + return method->flags; +} + static void ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info) { + MonoError error; MonoDomain *domain = mono_domain_get (); MonoMethodSignature* sig; MONO_ARCH_SAVE_REGS; - sig = mono_method_signature (method); - if (!sig) { - g_assert (mono_loader_get_last_error ()); - mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); - } + sig = mono_method_signature_checked (method, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg)); MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret)); @@ -1693,6 +1770,10 @@ ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method) static gint32 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field) { + MonoClass *parent = field->field->parent; + if (!parent->size_inited) + mono_class_init (parent); + return field->field->offset - sizeof (MonoObject); } @@ -1710,135 +1791,26 @@ ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean decla static MonoObject * ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj) { - MonoObject *o; + MonoClass *fklass = field->klass; MonoClassField *cf = field->field; - MonoClass *klass; - MonoVTable *vtable; - MonoType *t; - MonoDomain *domain = mono_object_domain (field); - gchar *v; - gboolean is_static = FALSE; - gboolean is_ref = FALSE; - - MONO_ARCH_SAVE_REGS; + MonoDomain *domain = mono_object_domain (field); - if (field->klass->image->assembly->ref_only) + if (fklass->image->assembly->ref_only) mono_raise_exception (mono_get_exception_invalid_operation ( "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods.")); - + if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) mono_security_core_clr_ensure_reflection_access_field (cf); - mono_class_init (field->klass); - - if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) - is_static = TRUE; - - if (obj && !is_static) { - /* Check that the field belongs to the object */ - gboolean found = FALSE; - MonoClass *k; - - for (k = obj->vtable->klass; k; k = k->parent) { - if (k == cf->parent) { - found = TRUE; - break; - } - } - - if (!found) { - char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name); - MonoException *ex = mono_get_exception_argument (NULL, msg); - g_free (msg); - mono_raise_exception (ex); - } - } - - t = mono_type_get_underlying_type (cf->type); - switch (t->type) { - case MONO_TYPE_STRING: - case MONO_TYPE_OBJECT: - case MONO_TYPE_CLASS: - case MONO_TYPE_ARRAY: - case MONO_TYPE_SZARRAY: - is_ref = TRUE; - break; - case MONO_TYPE_U1: - case MONO_TYPE_I1: - case MONO_TYPE_BOOLEAN: - case MONO_TYPE_U2: - case MONO_TYPE_I2: - case MONO_TYPE_CHAR: - case MONO_TYPE_U: - case MONO_TYPE_I: - case MONO_TYPE_U4: - case MONO_TYPE_I4: - case MONO_TYPE_R4: - case MONO_TYPE_U8: - case MONO_TYPE_I8: - case MONO_TYPE_R8: - case MONO_TYPE_VALUETYPE: - is_ref = t->byref; - break; - case MONO_TYPE_GENERICINST: - if (mono_type_generic_inst_is_valuetype (t)) { - is_ref = t->byref; - } else { - is_ref = TRUE; - } - break; - default: - g_error ("type 0x%x not handled in " - "ves_icall_Monofield_GetValue", t->type); - return NULL; - } - - vtable = NULL; - if (is_static) { - vtable = mono_class_vtable_full (domain, cf->parent, TRUE); - if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL)) - mono_runtime_class_init (vtable); - } - - if (is_ref) { - if (is_static) { - mono_field_static_get_value (vtable, cf, &o); - } else { - mono_field_get_value (obj, cf, &o); - } - return o; - } - - if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) { - MonoClass *nklass = mono_class_from_mono_type (cf->type); - guint8 *buf; - - /* Convert the Nullable structure into a boxed vtype */ - if (is_static) - buf = (guint8*)vtable->data + cf->offset; - else - buf = (guint8*)obj + cf->offset; - - return mono_nullable_box (buf, nklass); - } - - /* boxed value type */ - klass = mono_class_from_mono_type (cf->type); - o = mono_object_new (domain, klass); - v = ((gchar *) o) + sizeof (MonoObject); - if (is_static) { - mono_field_static_get_value (vtable, cf, v); - } else { - mono_field_get_value (obj, cf, v); - } - - return o; + return mono_field_get_value_object (domain, cf, obj); } static void ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value) { + MonoError error; MonoClassField *cf = field->field; + MonoType *type; gchar *v; MONO_ARCH_SAVE_REGS; @@ -1850,9 +1822,13 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) mono_security_core_clr_ensure_reflection_access_field (cf); + type = mono_field_get_type_checked (cf, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + v = (gchar *) value; - if (!cf->type->byref) { - switch (cf->type->type) { + if (!type->byref) { + switch (type->type) { case MONO_TYPE_U1: case MONO_TYPE_I1: case MONO_TYPE_BOOLEAN: @@ -1868,6 +1844,7 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob case MONO_TYPE_I8: case MONO_TYPE_R8: case MONO_TYPE_VALUETYPE: + case MONO_TYPE_PTR: if (v != NULL) v += sizeof (MonoObject); break; @@ -1879,11 +1856,11 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob /* Do nothing */ break; case MONO_TYPE_GENERICINST: { - MonoGenericClass *gclass = cf->type->data.generic_class; + MonoGenericClass *gclass = type->data.generic_class; g_assert (!gclass->context.class_inst->is_open); - if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) { - MonoClass *nklass = mono_class_from_mono_type (cf->type); + if (mono_class_is_nullable (mono_class_from_mono_type (type))) { + MonoClass *nklass = mono_class_from_mono_type (type); MonoObject *nullable; /* @@ -1904,12 +1881,12 @@ ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *ob } default: g_error ("type 0x%x not handled in " - "ves_icall_FieldInfo_SetValueInternal", cf->type->type); + "ves_icall_FieldInfo_SetValueInternal", type->type); return; } } - if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) { + if (type->attrs & FIELD_ATTRIBUTE_STATIC) { MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE); if (!vtable->initialized) mono_runtime_class_init (vtable); @@ -1944,6 +1921,7 @@ ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this) def_value = mono_class_get_field_default_value (field, &def_type); + /*FIXME unify this with reflection.c:mono_get_object_from_blob*/ switch (def_type) { case MONO_TYPE_U1: case MONO_TYPE_I1: @@ -1982,6 +1960,17 @@ ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this) return o; } +static MonoReflectionType* +ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field) +{ + MonoError error; + MonoClassField *field = ref_field->field; + MonoType *type = mono_field_get_type_checked (field, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); + return mono_type_get_object (mono_object_domain (ref_field), type); +} + static MonoReflectionType* ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod) { @@ -2009,8 +1998,8 @@ ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo if ((req_info & PInfo_ReflectedType) != 0) MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg)); - else if ((req_info & PInfo_DeclaringType) != 0) - MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg)); + if ((req_info & PInfo_DeclaringType) != 0) + MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg)); if ((req_info & PInfo_Name) != 0) MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name)); @@ -2047,6 +2036,7 @@ ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info) MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL); MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL); +#ifndef MONO_SMALL_CONFIG if (event->event->other) { int i, n = 0; while (event->event->other [n]) @@ -2056,72 +2046,107 @@ ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info) for (i = 0; i < n; i++) mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL)); } +#endif +} + +static void +collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error) +{ + int i; + MonoClass *ic; + + mono_class_setup_interfaces (klass, error); + if (!mono_error_ok (error)) + return; + + for (i = 0; i < klass->interface_count; i++) { + ic = klass->interfaces [i]; + g_hash_table_insert (ifaces, ic, ic); + + collect_interfaces (ic, ifaces, error); + if (!mono_error_ok (error)) + return; + } +} + +typedef struct { + MonoArray *iface_array; + MonoGenericContext *context; + MonoError *error; + MonoDomain *domain; + int next_idx; +} FillIfaceArrayData; + +static void +fill_iface_array (gpointer key, gpointer value, gpointer user_data) +{ + FillIfaceArrayData *data = user_data; + MonoClass *ic = key; + MonoType *ret = &ic->byval_arg, *inflated = NULL; + + if (!mono_error_ok (data->error)) + return; + + if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) { + inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error); + if (!mono_error_ok (data->error)) + return; + } + + mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret)); + + if (inflated) + mono_metadata_free_type (inflated); } static MonoArray* ves_icall_Type_GetInterfaces (MonoReflectionType* type) { MonoError error; - MonoDomain *domain = mono_object_domain (type); - MonoArray *intf; - GPtrArray *ifaces = NULL; - int i; MonoClass *class = mono_class_from_mono_type (type->type); MonoClass *parent; - MonoBitSet *slots; - MonoGenericContext *context = NULL; + FillIfaceArrayData data = { 0 }; + int len; - MONO_ARCH_SAVE_REGS; + GHashTable *iface_hash = g_hash_table_new (NULL, NULL); if (class->generic_class && class->generic_class->context.class_inst->is_open) { - context = mono_class_get_context (class); + data.context = mono_class_get_context (class); class = class->generic_class->container_class; } - mono_class_setup_vtable (class); - - slots = mono_bitset_new (class->max_interface_id + 1, 0); - for (parent = class; parent; parent = parent->parent) { - GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error); - if (!mono_error_ok (&error)) { - mono_bitset_free (slots); - mono_error_raise_exception (&error); - return NULL; - } else if (tmp_ifaces) { - for (i = 0; i < tmp_ifaces->len; ++i) { - MonoClass *ic = g_ptr_array_index (tmp_ifaces, i); + mono_class_setup_interfaces (parent, &error); + if (!mono_error_ok (&error)) + goto fail; + collect_interfaces (parent, iface_hash, &error); + if (!mono_error_ok (&error)) + goto fail; + } - if (mono_bitset_test (slots, ic->interface_id)) - continue; + data.error = &error; + data.domain = mono_object_domain (type); - mono_bitset_set (slots, ic->interface_id); - if (ifaces == NULL) - ifaces = g_ptr_array_new (); - g_ptr_array_add (ifaces, ic); - } - g_ptr_array_free (tmp_ifaces, TRUE); - } + len = g_hash_table_size (iface_hash); + if (len == 0) { + g_hash_table_destroy (iface_hash); + if (!data.domain->empty_types) + data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0); + return data.domain->empty_types; } - mono_bitset_free (slots); - if (!ifaces) - return mono_array_new_cached (domain, mono_defaults.monotype_class, 0); - - intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len); - for (i = 0; i < ifaces->len; ++i) { - MonoClass *ic = g_ptr_array_index (ifaces, i); - MonoType *ret = &ic->byval_arg, *inflated = NULL; - if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open) - inflated = ret = mono_class_inflate_generic_type (ret, context); - - mono_array_setref (intf, i, mono_type_get_object (domain, ret)); - if (inflated) - mono_metadata_free_type (inflated); - } - g_ptr_array_free (ifaces, TRUE); + data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len); + g_hash_table_foreach (iface_hash, fill_iface_array, &data); + if (!mono_error_ok (&error)) + goto fail; - return intf; + g_hash_table_destroy (iface_hash); + return data.iface_array; + +fail: + g_hash_table_destroy (iface_hash); + mono_error_raise_exception (&error); + return NULL; } static void @@ -2137,6 +2162,8 @@ ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType MonoDomain *domain; MONO_ARCH_SAVE_REGS; + mono_class_init_or_throw (class); + mono_class_init_or_throw (iclass); mono_class_setup_vtable (class); @@ -2163,6 +2190,7 @@ static void ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size) { MonoClass *klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); if (klass->image->dynamic) { MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type; @@ -2184,6 +2212,7 @@ ves_icall_MonoType_GetElementType (MonoReflectionType *type) return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg); class = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (class); // GetElementType should only return a type for: // Array Pointer PassedByRef @@ -2201,9 +2230,6 @@ static MonoReflectionType* ves_icall_get_type_parent (MonoReflectionType *type) { MonoClass *class = mono_class_from_mono_type (type->type); - - MONO_ARCH_SAVE_REGS; - return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL; } @@ -2235,7 +2261,7 @@ static MonoBoolean ves_icall_type_iscomobject (MonoReflectionType *type) { MonoClass *klass = mono_class_from_mono_type (type->type); - MONO_ARCH_SAVE_REGS; + mono_class_init_or_throw (klass); return (klass && klass->is_com_object); } @@ -2244,9 +2270,6 @@ static MonoReflectionModule* ves_icall_MonoType_get_Module (MonoReflectionType *type) { MonoClass *class = mono_class_from_mono_type (type->type); - - MONO_ARCH_SAVE_REGS; - return mono_module_get_object (mono_object_domain (type), class->image); } @@ -2255,9 +2278,6 @@ ves_icall_MonoType_get_Assembly (MonoReflectionType *type) { MonoDomain *domain = mono_domain_get (); MonoClass *class = mono_class_from_mono_type (type->type); - - MONO_ARCH_SAVE_REGS; - return mono_assembly_get_object (domain, class->image->assembly); } @@ -2281,30 +2301,12 @@ ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type) return class ? mono_type_get_object (domain, &class->byval_arg) : NULL; } -static MonoReflectionType* -ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type) -{ - MonoDomain *domain = mono_domain_get (); - MonoClass *class = mono_class_from_mono_type (type->type); - - MONO_ARCH_SAVE_REGS; - - if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */ - return mono_type_get_object (domain, mono_class_enum_basetype (class)); - else if (class->element_class) - return mono_type_get_object (domain, &class->element_class->byval_arg); - else - return NULL; -} - static MonoString* ves_icall_MonoType_get_Name (MonoReflectionType *type) { MonoDomain *domain = mono_domain_get (); MonoClass *class = mono_class_from_mono_type (type->type); - MONO_ARCH_SAVE_REGS; - if (type->type->byref) { char *n = g_strdup_printf ("%s&", class->name); MonoString *res = mono_string_new (domain, n); @@ -2323,8 +2325,6 @@ ves_icall_MonoType_get_Namespace (MonoReflectionType *type) MonoDomain *domain = mono_domain_get (); MonoClass *class = mono_class_from_mono_type (type->type); - MONO_ARCH_SAVE_REGS; - while (class->nested_in) class = class->nested_in; @@ -2343,6 +2343,7 @@ ves_icall_MonoType_GetArrayRank (MonoReflectionType *type) mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type")); class = mono_class_from_mono_type (type->type); + return class->rank; } @@ -2389,7 +2390,6 @@ ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type) return FALSE; klass = mono_class_from_mono_type (type->type); - return klass->generic_container != NULL; } @@ -2403,14 +2403,18 @@ ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type) return NULL; klass = mono_class_from_mono_type (type->type); + if (klass->generic_container) { return type; /* check this one */ } if (klass->generic_class) { MonoClass *generic_class = klass->generic_class->container_class; + gpointer tb; + + tb = mono_class_get_ref_info (generic_class); - if (generic_class->wastypebuilder && generic_class->reflection_info) - return generic_class->reflection_info; + if (generic_class->wastypebuilder && tb) + return tb; else return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg); } @@ -2420,10 +2424,12 @@ ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type) static MonoReflectionType* ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array) { + MonoClass *class; MonoType *geninst, **types; int i, count; - MONO_ARCH_SAVE_REGS; + g_assert (IS_MONOTYPE (type)); + mono_class_init_or_throw (mono_class_from_mono_type (type->type)); count = mono_array_length (type_array); types = g_new0 (MonoType *, count); @@ -2438,6 +2444,12 @@ ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array) if (!geninst) return NULL; + class = mono_class_from_mono_type (geninst); + + /*we might inflate to the GTD*/ + if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class)) + mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments")); + return mono_type_get_object (mono_object_domain (type), geninst); } @@ -2451,6 +2463,7 @@ ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type) return FALSE; klass = mono_class_from_mono_type (type->type); + return klass->generic_class != NULL; } @@ -2554,6 +2567,7 @@ ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type, domain = ((MonoObject *)type)->vtable->domain; klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); iter = NULL; while ((method = mono_class_get_methods (klass, &iter))) { @@ -2776,6 +2790,11 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoAr mono_security_core_clr_ensure_reflection_access_method (m); if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) { + if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) { + mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass)); + return NULL; + } + if (this) { if (!mono_object_isinst (this, m->klass)) { mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.")); @@ -2809,12 +2828,13 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoAr if (m->klass->rank && !strcmp (m->name, ".ctor")) { int i; - mono_array_size_t *lengths; - mono_array_size_t *lower_bounds; + uintptr_t *lengths; + intptr_t *lower_bounds; pcount = mono_array_length (params); - lengths = alloca (sizeof (mono_array_size_t) * pcount); + lengths = alloca (sizeof (uintptr_t) * pcount); + /* Note: the synthetized array .ctors have int32 as argument type */ for (i = 0; i < pcount; ++i) - lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject)); + lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject)); if (m->klass->rank == pcount) { /* Only lengths provided. */ @@ -2822,7 +2842,7 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoAr } else { g_assert (pcount == (m->klass->rank * 2)); /* lower bounds are first. */ - lower_bounds = lengths; + lower_bounds = (intptr_t*)lengths; lengths += m->klass->rank; } @@ -3025,6 +3045,7 @@ ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value) MonoDomain *domain; MonoClass *enumc, *objc; MonoObject *res; + MonoType *etype; guint64 val; MONO_ARCH_SAVE_REGS; @@ -3034,6 +3055,9 @@ ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value) domain = mono_object_domain (enumType); enumc = mono_class_from_mono_type (enumType->type); + + mono_class_init_or_throw (enumc); + objc = value->vtable->klass; if (!enumc->enumtype) @@ -3041,9 +3065,14 @@ ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value) if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8))) mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32.")); + etype = mono_class_enum_basetype (enumc); + if (!etype) + /* MS throws this for typebuilders */ + mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType")); + res = mono_object_new (domain, enumc); val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type); - write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val); + write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val); return res; } @@ -3078,9 +3107,20 @@ ves_icall_System_Enum_get_value (MonoObject *this) static MonoReflectionType * ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type) { + MonoType *etype; + MonoClass *klass; + MONO_ARCH_SAVE_REGS; - return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type))); + klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); + + etype = mono_class_enum_basetype (klass); + if (!etype) + /* MS throws this for typebuilders */ + mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType")); + + return mono_type_get_object (mono_object_domain (type), etype); } static int @@ -3177,6 +3217,8 @@ ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info) MONO_ARCH_SAVE_REGS; + mono_class_init_or_throw (enumc); + MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc))); nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0; MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues)); @@ -3189,6 +3231,8 @@ ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info) int len; MonoTypeEnum def_type; + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + continue; if (strcmp ("value__", mono_field_get_name (field)) == 0) continue; if (mono_field_is_deleted (field)) @@ -3254,8 +3298,6 @@ ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bfl domain = ((MonoObject *)type)->vtable->domain; klass = startklass = mono_class_from_mono_type (type->type); - MONO_ARCH_SAVE_REGS; - if (!name) mono_raise_exception (mono_get_exception_argument_null ("name")); if (type->type->byref) @@ -3268,17 +3310,16 @@ handle_parent: mono_raise_exception (mono_class_get_exception_for_failure (klass)); iter = NULL; - while ((field = mono_class_get_fields (klass, &iter))) { + while ((field = mono_class_get_fields_lazy (klass, &iter))) { + guint32 flags = mono_field_get_flags (field); match = 0; - if (field->type == NULL) - continue; - if (mono_field_is_deleted (field)) + if (mono_field_is_deleted_with_flags (field, flags)) continue; - if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) { + if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) { if (bflags & BFLAGS_Public) match++; - } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) { + } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) { if (bflags & BFLAGS_NonPublic) { match++; } @@ -3286,7 +3327,7 @@ handle_parent: if (!match) continue; match = 0; - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { + if (flags & FIELD_ATTRIBUTE_STATIC) { if (bflags & BFLAGS_Static) if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass)) match++; @@ -3337,18 +3378,21 @@ ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, Mon mono_ptr_array_init (tmp_array, 2); handle_parent: - if (klass->exception_type != MONO_EXCEPTION_NONE) + if (klass->exception_type != MONO_EXCEPTION_NONE) { + mono_ptr_array_destroy (tmp_array); mono_raise_exception (mono_class_get_exception_for_failure (klass)); + } iter = NULL; - while ((field = mono_class_get_fields (klass, &iter))) { + while ((field = mono_class_get_fields_lazy (klass, &iter))) { + guint32 flags = mono_field_get_flags (field); match = 0; - if (mono_field_is_deleted (field)) + if (mono_field_is_deleted_with_flags (field, flags)) continue; - if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) { + if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) { if (bflags & BFLAGS_Public) match++; - } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) { + } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) { if (bflags & BFLAGS_NonPublic) { match++; } @@ -3356,7 +3400,7 @@ handle_parent: if (!match) continue; match = 0; - if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) { + if (flags & FIELD_ATTRIBUTE_STATIC) { if (bflags & BFLAGS_Static) if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass)) match++; @@ -3418,8 +3462,6 @@ ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, gui MonoException *ex; MonoPtrArray tmp_array; - MONO_ARCH_SAVE_REGS; - mono_ptr_array_init (tmp_array, 4); if (!MethodInfo_array) { @@ -3434,6 +3476,7 @@ ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, gui return mono_array_new_specific (array_vtable, 0); klass = startklass = mono_class_from_mono_type (type->type); refklass = mono_class_from_mono_type (reftype->type); + len = 0; if (name != NULL) { mname = mono_string_to_utf8 (name); @@ -3571,9 +3614,6 @@ ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflag klass = startklass = mono_class_from_mono_type (type->type); refklass = mono_class_from_mono_type (reftype->type); - if (klass->exception_type != MONO_EXCEPTION_NONE) - mono_raise_exception (mono_class_get_exception_for_failure (klass)); - if (!System_Reflection_ConstructorInfo) System_Reflection_ConstructorInfo = mono_class_from_name ( mono_defaults.corlib, "System.Reflection", "ConstructorInfo"); @@ -3653,6 +3693,7 @@ property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass) static MonoArray* ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype) { + MonoException *ex; MonoDomain *domain; static MonoClass *System_Reflection_PropertyInfo; MonoClass *startklass, *klass; @@ -3664,7 +3705,7 @@ ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, gchar *propname = NULL; int (*compare_func) (const char *s1, const char *s2) = NULL; gpointer iter; - GHashTable *properties; + GHashTable *properties = NULL; MonoPtrArray tmp_array; MONO_ARCH_SAVE_REGS; @@ -3679,22 +3720,17 @@ ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, if (type->type->byref) return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0); klass = startklass = mono_class_from_mono_type (type->type); + if (name != NULL) { propname = mono_string_to_utf8 (name); compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp; } - mono_class_setup_vtable (klass); - properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal); handle_parent: mono_class_setup_vtable (klass); - if (klass->exception_type != MONO_EXCEPTION_NONE) { - g_hash_table_destroy (properties); - if (name != NULL) - g_free (propname); - mono_raise_exception (mono_class_get_exception_for_failure (klass)); - } + if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ()) + goto loader_error; iter = NULL; while ((prop = mono_class_get_properties (klass, &iter))) { @@ -3757,6 +3793,22 @@ handle_parent: mono_ptr_array_destroy (tmp_array); return res; + +loader_error: + if (properties) + g_hash_table_destroy (properties); + if (name) + g_free (propname); + mono_ptr_array_destroy (tmp_array); + + if (klass->exception_type != MONO_EXCEPTION_NONE) { + ex = mono_class_get_exception_for_failure (klass); + } else { + ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ()); + mono_loader_clear_error (); + } + mono_raise_exception (ex); + return NULL; } static MonoReflectionEvent * @@ -3768,6 +3820,7 @@ ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 MonoEvent *event; MonoMethod *method; gchar *event_name; + int (*compare_func) (const char *s1, const char *s2); MONO_ARCH_SAVE_REGS; @@ -3777,13 +3830,16 @@ ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 klass = startklass = mono_class_from_mono_type (type->type); domain = mono_object_domain (type); + mono_class_init_or_throw (klass); + + compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp; handle_parent: if (klass->exception_type != MONO_EXCEPTION_NONE) mono_raise_exception (mono_class_get_exception_for_failure (klass)); iter = NULL; while ((event = mono_class_get_events (klass, &iter))) { - if (strcmp (event->name, event_name)) + if (compare_func (event->name, event_name)) continue; method = event->add; @@ -3829,6 +3885,7 @@ handle_parent: static MonoArray* ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype) { + MonoException *ex; MonoDomain *domain; static MonoClass *System_Reflection_EventInfo; MonoClass *startklass, *klass; @@ -3853,9 +3910,10 @@ ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, Mon return mono_array_new_cached (domain, System_Reflection_EventInfo, 0); klass = startklass = mono_class_from_mono_type (type->type); -handle_parent: - if (klass->exception_type != MONO_EXCEPTION_NONE) - mono_raise_exception (mono_class_get_exception_for_failure (klass)); +handle_parent: + mono_class_setup_vtable (klass); + if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ()) + goto loader_error; iter = NULL; while ((event = mono_class_get_events (klass, &iter))) { @@ -3908,6 +3966,17 @@ handle_parent: mono_ptr_array_destroy (tmp_array); return res; + +loader_error: + mono_ptr_array_destroy (tmp_array); + if (klass->exception_type != MONO_EXCEPTION_NONE) { + ex = mono_class_get_exception_for_failure (klass); + } else { + ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ()); + mono_loader_clear_error (); + } + mono_raise_exception (ex); + return NULL; } static MonoReflectionType * @@ -3928,6 +3997,7 @@ ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint3 if (type->type->byref) return NULL; klass = mono_class_from_mono_type (type->type); + str = mono_string_to_utf8 (name); handle_parent: @@ -3987,8 +4057,6 @@ ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags) if (type->type->byref) return mono_array_new (domain, mono_defaults.monotype_class, 0); klass = mono_class_from_mono_type (type->type); - if (klass->exception_type != MONO_EXCEPTION_NONE) - mono_raise_exception (mono_class_get_exception_for_failure (klass)); /* * If a nested type is generic, return its generic type definition. @@ -4115,6 +4183,10 @@ ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *as mono_raise_exception (e); return NULL; + } else if (mono_loader_get_last_error ()) { + if (throwOnError) + mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); + mono_loader_clear_error (); } if (type->type == MONO_TYPE_CLASS) { @@ -4831,7 +4903,6 @@ ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full MonoString *res; gchar *name; - MONO_ARCH_SAVE_REGS; if (full_name) format = assembly_qualified ? MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : @@ -4854,6 +4925,14 @@ ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full return res; } +static int +vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this) +{ + MonoClass *klass = mono_class_from_mono_type (this->type); + mono_class_init_or_throw (klass); + return mono_security_core_clr_class_level (klass); +} + static void fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token) { @@ -4874,6 +4953,7 @@ fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *a aname->revision = name->revision; aname->hashalg = name->hash_alg; aname->versioncompat = 1; /* SameMachine (default) */ + aname->processor_architecture = name->arch; if (by_default_version) MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision)); @@ -4960,14 +5040,7 @@ ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assem MonoString *res; gchar *name; - name = g_strdup_printf ( - "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", - mass->aname.name, - mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision, - mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral", - mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null", - (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : ""); - + name = mono_stringify_assembly_name (&mass->aname); res = mono_string_new (domain, name); g_free (name); @@ -4985,14 +5058,14 @@ ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, if (g_path_is_absolute (mass->image->name)) { fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, - TRUE, mono_framework_version () >= 2); + TRUE, TRUE); return; } absolute = g_build_filename (mass->basedir, mass->image->name, NULL); fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, - mono_framework_version () >= 2); + TRUE); g_free (absolute); } @@ -5036,8 +5109,7 @@ ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, } fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, - TRUE, mono_framework_version () == 1, - mono_framework_version () >= 2); + TRUE, FALSE, TRUE); g_free (filename); mono_image_close (image); @@ -5346,14 +5418,23 @@ ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *modul } static gboolean -mono_metadata_memberref_is_method (MonoImage *image, guint32 token) -{ - guint32 cols [MONO_MEMBERREF_SIZE]; - const char *sig; - mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE); - sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]); - mono_metadata_decode_blob_size (sig, &sig); - return (*sig != 0x6); +mono_memberref_is_method (MonoImage *image, guint32 token) +{ + if (!image->dynamic) { + guint32 cols [MONO_MEMBERREF_SIZE]; + const char *sig; + mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE); + sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]); + mono_metadata_decode_blob_size (sig, &sig); + return (*sig != 0x6); + } else { + MonoClass *handle_class; + + if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL)) + return FALSE; + + return mono_defaults.methodhandle_class == handle_class; + } } static void @@ -5389,12 +5470,14 @@ ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 t } if (image->dynamic) { - if (type_args || method_args) - mono_raise_exception (mono_get_exception_not_implemented (NULL)); - klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); - if (!klass) - return NULL; - return &klass->byval_arg; + if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) { + klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); + return klass ? &klass->byval_arg : NULL; + } + + init_generic_context_from_args (&context, type_args, method_args); + klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context); + return klass ? &klass->byval_arg : NULL; } if ((index <= 0) || (index > image->tables [table].rows)) { @@ -5432,17 +5515,23 @@ ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 } if (image->dynamic) { - if (type_args || method_args) - mono_raise_exception (mono_get_exception_not_implemented (NULL)); - /* FIXME: validate memberref token type */ - return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); + if (table == MONO_TABLE_METHOD) + return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); + + if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) { + *error = ResolveTokenError_BadTable; + return NULL; + } + + init_generic_context_from_args (&context, type_args, method_args); + return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context); } if ((index <= 0) || (index > image->tables [table].rows)) { *error = ResolveTokenError_OutOfRange; return NULL; } - if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) { + if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) { *error = ResolveTokenError_BadTable; return NULL; } @@ -5500,17 +5589,23 @@ ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 } if (image->dynamic) { - if (type_args || method_args) - mono_raise_exception (mono_get_exception_not_implemented (NULL)); - /* FIXME: validate memberref token type */ - return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); + if (table == MONO_TABLE_FIELD) + return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL); + + if (mono_memberref_is_method (image, token)) { + *error = ResolveTokenError_BadTable; + return NULL; + } + + init_generic_context_from_args (&context, type_args, method_args); + return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context); } if ((index <= 0) || (index > image->tables [table].rows)) { *error = ResolveTokenError_OutOfRange; return NULL; } - if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) { + if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) { *error = ResolveTokenError_BadTable; return NULL; } @@ -5558,7 +5653,7 @@ ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 return NULL; } case MONO_TABLE_MEMBERREF: - if (mono_metadata_memberref_is_method (image, token)) { + if (mono_memberref_is_method (image, token)) { MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error); if (m) return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass); @@ -5687,6 +5782,20 @@ ves_icall_Type_IsArrayImpl (MonoReflectionType *t) return res; } +static void +check_for_invalid_type (MonoClass *klass) +{ + char *name; + MonoString *str; + if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF) + return; + + name = mono_type_get_full_name (klass); + str = mono_string_new (mono_domain_get (), name); + g_free (name); + mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL)); + +} static MonoReflectionType * ves_icall_Type_make_array_type (MonoReflectionType *type, int rank) { @@ -5695,6 +5804,8 @@ ves_icall_Type_make_array_type (MonoReflectionType *type, int rank) MONO_ARCH_SAVE_REGS; klass = mono_class_from_mono_type (type->type); + check_for_invalid_type (klass); + if (rank == 0) //single dimentional array aklass = mono_array_class_get (klass, 1); else @@ -5711,6 +5822,8 @@ ves_icall_Type_make_byref_type (MonoReflectionType *type) MONO_ARCH_SAVE_REGS; klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); + check_for_invalid_type (klass); return mono_type_get_object (mono_object_domain (type), &klass->this_arg); } @@ -5718,9 +5831,11 @@ ves_icall_Type_make_byref_type (MonoReflectionType *type) static MonoReflectionType * ves_icall_Type_MakePointerType (MonoReflectionType *type) { - MonoClass *pklass; + MonoClass *klass, *pklass; - MONO_ARCH_SAVE_REGS; + klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); + check_for_invalid_type (klass); pklass = mono_ptr_class_get (type->type); @@ -5738,6 +5853,8 @@ ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, Mon MONO_ARCH_SAVE_REGS; + mono_class_init_or_throw (delegate_class); + mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class); if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) { @@ -5751,6 +5868,8 @@ ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, Mon /* Creating a trampoline would leak memory */ func = mono_compile_method (method); } else { + if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target)) + method = mono_object_get_virtual_method (target, method); func = mono_create_ftnptr (mono_domain_get (), mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE)); } @@ -6189,20 +6308,16 @@ ves_icall_System_Environment_get_Platform (void) return 2; #elif defined(__MACH__) /* OSX */ - if (mono_framework_version () < 2) - return 128; - // - // For compatibility with our client code, this will be 4 for a while. - // We will eventually move to 6 to match .NET, but it requires all client - // code to be updated and the documentation everywhere to be updated - // first. + // Notice that the value is hidden from user code, and only exposed + // to mscorlib. This is due to Mono's Unix/MacOS code predating the + // define and making assumptions based on Unix/128/4 values before there + // was a MacOS define. Lots of code would assume that not-Unix meant + // Windows, but in this case, it would be OSX. // - return 4; + return 6; #else /* Unix */ - if (mono_framework_version () < 2) - return 128; return 4; #endif } @@ -6246,7 +6361,7 @@ ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name) */ #ifndef _MSC_VER #ifndef __MINGW32_VERSION -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined (__arm__) /* Apple defines this in crt_externs.h but doesn't provide that header for * arm-apple-darwin9. We'll manually define the symbol on Apple as it does * in fact exist on all implementations (so far) @@ -6409,6 +6524,9 @@ ves_icall_System_Environment_Exit (int result) mono_runtime_set_shutting_down (); + /* This will kill the tp threads which cannot be suspended */ + mono_thread_pool_cleanup (); + /* Suspend all managed threads since the runtime is going away */ mono_thread_suspend_all_other_threads (); @@ -6449,7 +6567,7 @@ ves_icall_System_Environment_GetWindowsFolderPath (int folder) static MonoArray * ves_icall_System_Environment_GetLogicalDrives (void) { - gunichar2 buf [128], *ptr, *dname; + gunichar2 buf [256], *ptr, *dname; gunichar2 *u16; guint initial_size = 127, size = 128; gint ndrives; @@ -6643,6 +6761,7 @@ ves_icall_Remoting_RemotingServices_GetVirtualMethod ( method = rmethod->method; klass = mono_class_from_mono_type (rtype->type); + mono_class_init_or_throw (klass); if (MONO_CLASS_IS_INTERFACE (klass)) return NULL; @@ -6705,6 +6824,7 @@ ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClas domain = mono_object_domain (type); klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); if (klass->rank >= 1) { g_assert (klass->rank == 1); @@ -6796,6 +6916,45 @@ ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void) return mcpath; } +static MonoString * +get_bundled_app_config (void) +{ + const gchar *app_config; + MonoDomain *domain; + MonoString *file; + gchar *config_file_name, *config_file_path; + gsize len; + gchar *module; + + MONO_ARCH_SAVE_REGS; + + domain = mono_domain_get (); + file = domain->setup->configuration_file; + if (!file) + return NULL; + + // Retrieve config file and remove the extension + config_file_name = mono_string_to_utf8 (file); + config_file_path = mono_portability_find_file (config_file_name, TRUE); + if (!config_file_path) + config_file_path = config_file_name; + len = strlen (config_file_path) - strlen (".config"); + module = g_malloc0 (len + 1); + memcpy (module, config_file_path, len); + // Get the config file from the module name + app_config = mono_config_string_for_assembly_file (module); + // Clean-up + g_free (module); + if (config_file_name != config_file_path) + g_free (config_file_name); + g_free (config_file_path); + + if (!app_config) + return NULL; + + return mono_string_new (mono_domain_get (), app_config); +} + static MonoString * get_bundled_machine_config (void) { @@ -6891,6 +7050,7 @@ ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type) domain = mono_object_domain (type); klass = mono_class_from_mono_type (type->type); + mono_class_init_or_throw (klass); if (mono_class_is_nullable (klass)) /* No arguments -> null */ @@ -6905,6 +7065,7 @@ ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definiti MonoClass *klass, *parent; MonoMethod *method = m->method; MonoMethod *result = NULL; + int slot; MONO_ARCH_SAVE_REGS; @@ -6916,6 +7077,10 @@ ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definiti method->flags & METHOD_ATTRIBUTE_NEW_SLOT) return m; + slot = mono_method_get_vtable_slot (method); + if (slot == -1) + return m; + klass = method->klass; if (klass->generic_class) klass = klass->generic_class->container_class; @@ -6924,7 +7089,7 @@ ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definiti /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */ for (parent = klass->parent; parent != NULL; parent = parent->parent) { mono_class_setup_vtable (parent); - if (parent->vtable_size <= method->slot) + if (parent->vtable_size <= slot) break; klass = parent; } @@ -6937,12 +7102,20 @@ ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definiti if (klass == method->klass) return m; - result = klass->vtable [method->slot]; + /*This is possible if definition == FALSE. + * Do it here to be really sure we don't read invalid memory. + */ + if (slot >= klass->vtable_size) + return m; + + mono_class_setup_vtable (klass); + + result = klass->vtable [slot]; if (result == NULL) { /* It is an abstract method */ gpointer iter = NULL; while ((result = mono_class_get_methods (klass, &iter))) - if (result->slot == method->slot) + if (result->slot == slot) break; } @@ -7115,6 +7288,8 @@ ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType gpointer iter = NULL; MONO_ARCH_SAVE_REGS; + mono_class_init_or_throw (klass); + while ((m = mono_class_get_methods (klass, &iter))) prelink_method (m); } @@ -7192,10 +7367,32 @@ static MonoArray* param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional) { MonoType *type = param->ClassImpl->type; - MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl; - MonoImage *image = method->method->klass->image; - int pos = param->PositionImpl; - MonoMethodSignature *sig = mono_method_signature (method->method); + MonoClass *member_class = mono_object_class (param->MemberImpl); + MonoMethod *method = NULL; + MonoImage *image; + int pos; + MonoMethodSignature *sig; + + if (mono_class_is_reflection_method_or_constructor (member_class)) { + MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl; + method = rmethod->method; + } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) { + MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl; + if (!(method = prop->property->get)) + method = prop->property->set; + g_assert (method); + } else { + char *type_name = mono_type_get_full_name (member_class); + char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name); + MonoException *ex = mono_get_exception_not_supported (msg); + g_free (type_name); + g_free (msg); + mono_raise_exception (ex); + } + + image = method->klass->image; + pos = param->PositionImpl; + sig = mono_method_signature (method); if (pos == -1) type = sig->ret; else @@ -7229,16 +7426,65 @@ property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean return type_array_from_modifiers (image, type, optional); } +/* + *Construct a MonoType suited to be used to decode a constant blob object. + * + * @type is the target type which will be constructed + * @blob_type is the blob type, for example, that comes from the constant table + * @real_type is the expected constructed type. + */ +static void +mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type) +{ + type->type = blob_type; + type->data.klass = NULL; + if (blob_type == MONO_TYPE_CLASS) + type->data.klass = mono_defaults.object_class; + else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) { + /* For enums, we need to use the base type */ + type->type = MONO_TYPE_VALUETYPE; + type->data.klass = mono_class_from_mono_type (real_type); + } else + type->data.klass = mono_class_from_mono_type (real_type); +} + +static MonoObject* +property_info_get_default_value (MonoReflectionProperty *property) +{ + MonoType blob_type; + MonoProperty *prop = property->property; + MonoType *type = get_property_type (prop); + MonoDomain *domain = mono_object_domain (property); + MonoTypeEnum def_type; + const char *def_value; + MonoObject *o; + + mono_class_init (prop->parent); + + if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) + mono_raise_exception (mono_get_exception_invalid_operation (NULL)); + + def_value = mono_class_get_property_default_value (prop, &def_type); + + mono_type_from_blob_type (&blob_type, def_type, type); + o = mono_get_object_from_blob (domain, &blob_type, def_value); + + return o; +} + static MonoBoolean custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type) { + MonoClass *attr_class = mono_class_from_mono_type (attr_type->type); MonoCustomAttrInfo *cinfo; gboolean found; + mono_class_init_or_throw (attr_class); + cinfo = mono_reflection_get_custom_attrs_info (obj); if (!cinfo) return FALSE; - found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type)); + found = mono_custom_attrs_has_attr (cinfo, attr_class); if (!cinfo->cached) mono_custom_attrs_free (cinfo); return found; @@ -7247,8 +7493,16 @@ custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type) static MonoArray* custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type) { - MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL); + MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL; + MonoArray *res; + MonoError error; + + if (attr_class) + mono_class_init_or_throw (attr_class); + res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error); + if (!mono_error_ok (&error)) + mono_error_raise_exception (&error); if (mono_loader_get_last_error ()) { mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ())); g_assert_not_reached ();