[threading] Use a RT signal for abort when possible.
[mono.git] / mono / metadata / metadata.c
index 03cac47ce37bacdeb29dff3658ccc2a284b64610..138cb114b002d6625d832cc4e30c017104c84f67 100644 (file)
@@ -1761,6 +1761,8 @@ mono_metadata_get_param_attrs (MonoImage *m, int def, int param_count)
 MonoMethodSignature*
 mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *generic_container, guint32 token)
 {
+       MonoError error;
+       MonoMethodSignature *ret;
        MonoTableInfo *tables = image->tables;
        guint32 idx = mono_metadata_token_index (token);
        guint32 sig;
@@ -1776,7 +1778,12 @@ mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContainer *gene
        ptr = mono_metadata_blob_heap (image, sig);
        mono_metadata_decode_blob_size (ptr, &ptr);
 
-       return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL); 
+       ret = mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL, &error);
+       if (!ret) {
+               mono_loader_set_error_from_mono_error (&error);
+               mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
+       }
+       return ret;
 }
 
 /*
@@ -1893,7 +1900,7 @@ mono_metadata_signature_size (MonoMethodSignature *sig)
  */
 MonoMethodSignature *
 mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *container,
-                                          int def, const char *ptr, const char **rptr)
+                                          int def, const char *ptr, const char **rptr, MonoError *error)
 {
        MonoMethodSignature *method;
        int i, *pattrs = NULL;
@@ -1901,6 +1908,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
        guint32 gen_param_count = 0;
        gboolean is_open = FALSE;
 
+       mono_error_init (error);
+
        if (*ptr & 0x10)
                gen_param_count = 1;
        if (*ptr & 0x20)
@@ -1927,6 +1936,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
                if (!method->ret) {
                        mono_metadata_free_method_signature (method);
                        g_free (pattrs);
+                       if (mono_loader_get_last_error ())
+                               mono_error_set_from_loader_error (error);
+                       else
+                               mono_error_set_bad_image (error, m, "Could not parse return type signature");
                        return NULL;
                }
                is_open = mono_class_is_open_constructed_type (method->ret);
@@ -1935,12 +1948,14 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
        for (i = 0; i < method->param_count; ++i) {
                if (*ptr == MONO_TYPE_SENTINEL) {
                        if (method->call_convention != MONO_CALL_VARARG || def) {
-                               g_warning ("found sentinel for methoddef or no vararg method 0x%08x on image %s", def, m->name);
+                               g_assert (!mono_loader_get_last_error ());
+                               mono_error_set_bad_image (error, m, "Found sentinel for methoddef or no vararg");
                                g_free (pattrs);
                                return NULL;
                        }
                        if (method->sentinelpos >= 0) {
-                               g_warning ("found sentinel twice in the same signature for method 0x%08x on image %s", def, m->name);
+                               g_assert (!mono_loader_get_last_error ());
+                               mono_error_set_bad_image (error, m, "Found sentinel twice in the same signature.");
                                g_free (pattrs);
                                return NULL;
                        }
@@ -1949,6 +1964,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
                }
                method->params [i] = mono_metadata_parse_type_full (m, container, MONO_PARSE_PARAM, pattrs ? pattrs [i+1] : 0, ptr, &ptr);
                if (!method->params [i]) {
+                       if (mono_loader_get_last_error ())
+                               mono_error_set_from_loader_error (error);
+                       else
+                               mono_error_set_bad_image (error, m, "Could not parse type argument %d on method signature", i);
                        mono_metadata_free_method_signature (method);
                        g_free (pattrs);
                        return NULL;
@@ -1974,6 +1993,7 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
         * Add signature to a cache and increase ref count...
         */
 
+       g_assert (!mono_loader_get_last_error ());
        return method;
 }
 
@@ -1994,7 +2014,14 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
 MonoMethodSignature *
 mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
 {
-       return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
+       MonoError error;
+       MonoMethodSignature *ret;
+       ret = mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr, &error);
+       if (!ret) {
+               mono_loader_set_error_from_mono_error (&error);
+               mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
+       }
+       return ret;
 }
 
 /*
@@ -2735,9 +2762,6 @@ free_inflated_signature (MonoInflatedMethodSignature *sig)
        g_free (sig);
 }
 
-/*
- * LOCKING: assumes the loader lock is held.
- */
 MonoMethodInflated*
 mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
 {
@@ -2753,19 +2777,15 @@ mono_method_inflated_lookup (MonoMethodInflated* method, gboolean cache)
 
        collect_data_free (&data);
 
-       if (cache) {
-               mono_image_set_lock (set);
+       mono_image_set_lock (set);
+       res = g_hash_table_lookup (set->gmethod_cache, method);
+       if (!res && cache) {
                g_hash_table_insert (set->gmethod_cache, method, method);
-               mono_image_set_unlock (set);
-
-               return method;
-       } else {
-               mono_image_set_lock (set);
-               res = g_hash_table_lookup (set->gmethod_cache, method);
-               mono_image_set_unlock (set);
-
-               return res;
+               res = method;
        }
+
+       mono_image_set_unlock (set);
+       return res;
 }
 
 /*
@@ -3126,6 +3146,8 @@ mono_metadata_get_shared_type (MonoType *type)
                if (type == &type->data.klass->this_arg)
                        return type;
                break;
+       default:
+               break;
        }
 
        return NULL;
@@ -3143,9 +3165,32 @@ compare_type_literals (int class_type, int type_type)
        /* NET 1.1 assemblies might encode string and object in a denormalized way.
         * See #675464.
         */
-       if (type_type == MONO_TYPE_CLASS && (class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT))
+       if (class_type == type_type)
+               return TRUE;
+
+       if (type_type == MONO_TYPE_CLASS)
+               return class_type == MONO_TYPE_STRING || class_type == MONO_TYPE_OBJECT;
+
+       g_assert (type_type == MONO_TYPE_VALUETYPE);
+       switch (class_type) {
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_CHAR:
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_R4:
+       case MONO_TYPE_R8:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
                return TRUE;
-       return class_type == type_type;
+       default:
+               return FALSE;
+       }
 }
 
 /* 
@@ -3200,11 +3245,15 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
        case MONO_TYPE_CLASS: {
                guint32 token;
                MonoClass *class;
+               MonoError error;
                token = mono_metadata_parse_typedef_or_ref (m, ptr, &ptr);
-               class = mono_class_get (m, token);
+               class = mono_class_get_checked (m, token, &error);
                type->data.klass = class;
-               if (!class)
+               if (!class) {
+                       mono_loader_set_error_from_mono_error (&error);
+                       mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
                        return FALSE;
+               }
                if (!compare_type_literals (class->byval_arg.type, type->type))
                        return FALSE;
                break;
@@ -3223,11 +3272,16 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                if (!type->data.type)
                        return FALSE;
                break;
-       case MONO_TYPE_FNPTR:
-               type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr);
-               if (!type->data.method)
+       case MONO_TYPE_FNPTR: {
+               MonoError error;
+               type->data.method = mono_metadata_parse_method_signature_full (m, container, 0, ptr, &ptr, &error);
+               if (!type->data.method) {
+                       mono_loader_set_error_from_mono_error (&error);
+                       mono_error_cleanup (&error); /*FIXME don't swallow the error message*/
                        return FALSE;
+               }
                break;
+       }
        case MONO_TYPE_ARRAY:
                type->data.array = mono_metadata_parse_array_internal (m, container, transient, ptr, &ptr);
                if (!type->data.array)
@@ -3286,6 +3340,8 @@ mono_metadata_free_type (MonoType *type)
        case MONO_TYPE_ARRAY:
                mono_metadata_free_array (type->data.array);
                break;
+       default:
+               break;
        }
 
        g_free (type);
@@ -3321,14 +3377,13 @@ static MonoExceptionClause*
 parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
 {
        unsigned char sect_data_flags;
-       const unsigned char *sptr;
        int is_fat;
        guint32 sect_data_len;
        MonoExceptionClause* clauses = NULL;
        
        while (1) {
                /* align on 32-bit boundary */
-               sptr = ptr = dword_align (ptr); 
+               ptr = dword_align (ptr); 
                sect_data_flags = *ptr;
                ptr++;
                
@@ -3340,14 +3395,7 @@ parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
                        sect_data_len = ptr [0];
                        ++ptr;
                }
-               /*
-               g_print ("flags: %02x, len: %d\n", sect_data_flags, sect_data_len);
-               hex_dump (sptr, 0, sect_data_len+8);
-               g_print ("\nheader: ");
-               hex_dump (sptr-4, 0, 4);
-               g_print ("\n");
-               */
-               
+
                if (sect_data_flags & METHOD_HEADER_SECTION_EHTABLE) {
                        const unsigned char *p = dword_align (ptr);
                        int i;
@@ -3377,7 +3425,16 @@ parse_section_data (MonoImage *m, int *num_clauses, const unsigned char *ptr)
                                if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                        ec->data.filter_offset = tof_value;
                                } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
-                                       ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
+                                       ec->data.catch_class = NULL;
+                                       if (tof_value) {
+                                               MonoError error;
+                                               ec->data.catch_class = mono_class_get_checked (m, tof_value, &error);
+                                               if (!mono_error_ok (&error)) {
+                                                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                                                       g_free (clauses);
+                                                       return NULL;
+                                               }
+                                       }
                                } else {
                                        ec->data.catch_class = NULL;
                                }
@@ -3480,14 +3537,14 @@ mono_method_get_header_summary (MonoMethod *method, MonoMethodHeaderSummary *sum
 MonoMethodHeader *
 mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
 {
-       MonoMethodHeader *mh;
+       MonoMethodHeader *mh = NULL;
        unsigned char flags = *(const unsigned char *) ptr;
        unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
        guint16 fat_flags;
        guint32 local_var_sig_tok, max_stack, code_size, init_locals;
        const unsigned char *code;
        MonoExceptionClause* clauses = NULL;
-       int hsize, num_clauses = 0;
+       int num_clauses = 0;
        MonoTableInfo *t = &m->tables [MONO_TABLE_STANDALONESIG];
        guint32 cols [MONO_STAND_ALONE_SIGNATURE_SIZE];
 
@@ -3506,7 +3563,6 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        case METHOD_HEADER_FAT_FORMAT:
                fat_flags = read16 (ptr);
                ptr += 2;
-               hsize = (fat_flags >> 12) & 0xf;
                max_stack = read16 (ptr);
                ptr += 2;
                code_size = read32 (ptr);
@@ -3536,20 +3592,20 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        if (local_var_sig_tok) {
                int idx = (local_var_sig_tok & 0xffffff)-1;
                if (idx >= t->rows || idx < 0)
-                       return NULL;
+                       goto fail;
                mono_metadata_decode_row (t, idx, cols, 1);
 
                if (!mono_verifier_verify_standalone_signature (m, cols [MONO_STAND_ALONE_SIGNATURE], NULL))
-                       return NULL;
+                       goto fail;
        }
        if (fat_flags & METHOD_HEADER_MORE_SECTS)
                clauses = parse_section_data (m, &num_clauses, (const unsigned char*)ptr);
        if (local_var_sig_tok) {
                const char *locals_ptr;
-               int len=0, i, bsize;
+               int len=0, i;
 
                locals_ptr = mono_metadata_blob_heap (m, cols [MONO_STAND_ALONE_SIGNATURE]);
-               bsize = mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
+               mono_metadata_decode_blob_size (locals_ptr, &locals_ptr);
                if (*locals_ptr != 0x07)
                        g_warning ("wrong signature for locals blob");
                locals_ptr++;
@@ -3559,11 +3615,8 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                for (i = 0; i < len; ++i) {
                        mh->locals [i] = mono_metadata_parse_type_internal (m, container,
                                                                                                                                MONO_PARSE_LOCAL, 0, TRUE, locals_ptr, &locals_ptr);
-                       if (!mh->locals [i]) {
-                               g_free (clauses);
-                               g_free (mh);
-                               return NULL;
-                       }
+                       if (!mh->locals [i])
+                               goto fail;
                }
        } else {
                mh = g_malloc0 (MONO_SIZEOF_METHOD_HEADER + num_clauses * sizeof (MonoExceptionClause));
@@ -3581,6 +3634,11 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                mh->num_clauses = num_clauses;
        }
        return mh;
+fail:
+       g_free (clauses);
+       g_free (mh);
+       return NULL;
+
 }
 
 /*
@@ -3996,7 +4054,7 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
  * Returns: TRUE on success, FALSE on failure.
  */
 gboolean
-mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context)
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, MonoClass ***interfaces, guint *count, gboolean heap_alloc_result, MonoGenericContext *context, MonoError *error)
 {
        MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
        locator_t loc;
@@ -4007,6 +4065,8 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
        *interfaces = NULL;
        *count = 0;
 
+       mono_error_init (error);
+
        if (!tdef->base)
                return TRUE;
 
@@ -4047,8 +4107,8 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
                mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
                if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
                        break;
-               iface = mono_class_get_full (
-                       meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
+               iface = mono_class_get_and_inflate_typespec_checked (
+                       meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context, error);
                if (iface == NULL)
                        return FALSE;
                result [pos - start] = iface;
@@ -4076,10 +4136,12 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
 MonoClass**
 mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
 {
-       MonoClass **interfaces;
+       MonoError error;
+       MonoClass **interfaces = NULL;
        gboolean rv;
 
-       rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL);
+       rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, TRUE, NULL, &error);
+       g_assert (mono_error_ok (&error)); /* FIXME dont swallow the error */
        if (rv)
                return interfaces;
        else
@@ -4301,6 +4363,8 @@ mono_type_set_alignment (MonoTypeEnum type, int align)
 int
 mono_type_size (MonoType *t, int *align)
 {
+       MonoTypeEnum simple_type;
+
        if (!t) {
                *align = 1;
                return 0;
@@ -4310,7 +4374,9 @@ mono_type_size (MonoType *t, int *align)
                return sizeof (gpointer);
        }
 
-       switch (t->type){
+       simple_type = t->type;
+ again:
+       switch (simple_type) {
        case MONO_TYPE_VOID:
                *align = 1;
                return 0;
@@ -4383,9 +4449,14 @@ mono_type_size (MonoType *t, int *align)
        }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
-               /* FIXME: Martin, this is wrong. */
-               *align = MONO_ABI_ALIGNOF (gpointer);
-               return sizeof (gpointer);
+               if (t->data.generic_param->gshared_constraint == 0 || t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE) {
+                       *align = MONO_ABI_ALIGNOF (gpointer);
+                       return sizeof (gpointer);
+               } else {
+                       /* The gparam can only match types given by gshared_constraint */
+                       simple_type = t->data.generic_param->gshared_constraint;
+                       goto again;
+               }
        default:
                g_error ("mono_type_size: type 0x%02x unknown", t->type);
        }
@@ -4409,6 +4480,7 @@ int
 mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
 {
        int tmp;
+       MonoTypeEnum simple_type;
 #if SIZEOF_VOID_P == SIZEOF_REGISTER
        int stack_slot_size = sizeof (gpointer);
        int stack_slot_align = MONO_ABI_ALIGNOF (gpointer);
@@ -4427,7 +4499,9 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
                return stack_slot_size;
        }
 
-       switch (t->type){
+       simple_type = t->type;
+ again:
+       switch (simple_type) {
        case MONO_TYPE_BOOLEAN:
        case MONO_TYPE_CHAR:
        case MONO_TYPE_I1:
@@ -4450,8 +4524,14 @@ mono_type_stack_size_internal (MonoType *t, int *align, gboolean allow_open)
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                g_assert (allow_open);
-               *align = stack_slot_align;
-               return stack_slot_size;
+               if (t->data.generic_param->gshared_constraint == 0 || t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE) {
+                       *align = stack_slot_align;
+                       return stack_slot_size;
+               } else {
+                       /* The gparam can only match types given by gshared_constraint */
+                       simple_type = t->data.generic_param->gshared_constraint;
+                       goto again;
+               }
        case MONO_TYPE_TYPEDBYREF:
                *align = stack_slot_align;
                return stack_slot_size * 3;
@@ -4634,8 +4714,9 @@ mono_metadata_type_hash (MonoType *t1)
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                return ((hash << 5) - hash) ^ mono_metadata_generic_param_hash (t1->data.generic_param);
+       default:
+               return hash;
        }
-       return hash;
 }
 
 static guint
@@ -4644,7 +4725,7 @@ mono_metadata_generic_param_hash (MonoGenericParam *p)
        guint hash;
        MonoGenericParamInfo *info;
 
-       hash = (mono_generic_param_num (p) << 2) | p->serial;
+       hash = (mono_generic_param_num (p) << 2) | p->gshared_constraint;
        info = mono_generic_param_info (p);
        /* Can't hash on the owner klass/method, since those might not be set when this is called */
        if (info)
@@ -4659,7 +4740,7 @@ mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, g
                return TRUE;
        if (mono_generic_param_num (p1) != mono_generic_param_num (p2))
                return FALSE;
-       if (p1->serial != p2->serial)
+       if (p1->gshared_constraint != p2->gshared_constraint)
                return FALSE;
 
        /*
@@ -5279,20 +5360,33 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
 /**
  * @image: context where the image is created
  * @type_spec:  typespec token
+ * @deprecated use mono_type_create_from_typespec_checked that has proper error handling
  *
  * Creates a MonoType representing the TypeSpec indexed by the @type_spec
  * token.
  */
 MonoType *
 mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+       MonoError error;
+       MonoType *type = mono_type_create_from_typespec_checked (image, type_spec, &error);
+       if (!type)
+                g_error ("Could not create typespec %x due to %s", type_spec, mono_error_get_message (&error));
+       return type;
+}
+
+MonoType *
+mono_type_create_from_typespec_checked (MonoImage *image, guint32 type_spec, MonoError *error)
+
 {
        guint32 idx = mono_metadata_token_index (type_spec);
        MonoTableInfo *t;
        guint32 cols [MONO_TYPESPEC_SIZE];
        const char *ptr;
-       guint32 len;
        MonoType *type, *type2;
 
+       mono_error_init (error);
+
        mono_image_lock (image);
        type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec));
        mono_image_unlock (image);
@@ -5304,14 +5398,21 @@ mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
        mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
        ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
 
-       if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL))
+       if (!mono_verifier_verify_typespec_signature (image, cols [MONO_TYPESPEC_SIGNATURE], type_spec, NULL)) {
+               mono_error_set_bad_image (error, image, "Could not verify type spec %08x.", type_spec);
                return NULL;
+       }
 
-       len = mono_metadata_decode_value (ptr, &ptr);
+       mono_metadata_decode_value (ptr, &ptr);
 
        type = mono_metadata_parse_type_internal (image, NULL, MONO_PARSE_TYPE, 0, TRUE, ptr, &ptr);
-       if (!type)
+       if (!type) {
+               if (mono_loader_get_last_error ())
+                       mono_error_set_from_loader_error (error);
+               else
+                       mono_error_set_bad_image (error, image, "Could not parse type spec %08x.", type_spec);
                return NULL;
+       }
 
        type2 = mono_metadata_type_dup (image, type);
        mono_metadata_free_type (type);
@@ -5659,18 +5760,25 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 }
 
 MonoMethod*
-method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
+method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context, MonoError *error)
 {
+       MonoMethod *result = NULL;
        guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
 
+       mono_error_init (error);
+
        switch (tok & MONO_METHODDEFORREF_MASK) {
        case MONO_METHODDEFORREF_METHODDEF:
-               return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
+               result = mono_get_method_checked (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context, error);
+               break;
        case MONO_METHODDEFORREF_METHODREF:
-               return mono_get_method_full (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context);
+               result = mono_get_method_checked (m, MONO_TOKEN_MEMBER_REF | idx, NULL, context, error);
+               break;
+       default:
+               mono_error_set_bad_image (error, m, "Invalid MethodDefOfRef token %x", tok);
        }
-       g_assert_not_reached ();
-       return NULL;
+
+       return result;
 }
 
 /*
@@ -5731,21 +5839,25 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
                MonoMethod *method;
 
                if (!mono_verifier_verify_methodimpl_row (image, start + i, &error)) {
-                       mono_error_cleanup (&error);
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        ok = FALSE;
                        break;
                }
 
                mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
                method = method_from_method_def_or_ref (
-                       image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
-               if (method == NULL)
+                       image, cols [MONO_METHODIMPL_DECLARATION], generic_context, &error);
+               if (method == NULL) {
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        ok = FALSE;
+               }
                result [i * 2] = method;
                method = method_from_method_def_or_ref (
-                       image, cols [MONO_METHODIMPL_BODY], generic_context);
-               if (method == NULL)
+                       image, cols [MONO_METHODIMPL_BODY], generic_context, &error);
+               if (method == NULL) {
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
                        ok = FALSE;
+               }
                result [i * 2 + 1] = method;
        }
 
@@ -5772,7 +5884,7 @@ mono_guid_to_string (const guint8 *guid)
 }
 
 static gboolean
-get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container)
+get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGenericContainer *container, MonoError *error)
 {
        MonoTableInfo *tdef  = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
        guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
@@ -5781,13 +5893,15 @@ get_constraints (MonoImage *image, int owner, MonoClass ***constraints, MonoGene
        GSList *cons = NULL, *tmp;
        MonoGenericContext *context = &container->context;
 
+       mono_error_init (error);
+
        *constraints = NULL;
        found = 0;
        for (i = 0; i < tdef->rows; ++i) {
                mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
                if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
                        token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
-                       klass = mono_class_get_full (image, token, context);
+                       klass = mono_class_get_and_inflate_typespec_checked (image, token, context, error);
                        if (!klass) {
                                g_slist_free (cons);
                                return FALSE;
@@ -5866,40 +5980,24 @@ mono_metadata_has_generic_params (MonoImage *image, guint32 token)
  * Memory is allocated from IMAGE's mempool.
  */
 gboolean
-mono_metadata_load_generic_param_constraints_full (MonoImage *image, guint32 token,
-                                             MonoGenericContainer *container)
+mono_metadata_load_generic_param_constraints_checked (MonoImage *image, guint32 token,
+                                             MonoGenericContainer *container, MonoError *error)
 {
 
        guint32 start_row, i, owner;
+       mono_error_init (error);
+
        if (! (start_row = mono_metadata_get_generic_param_row (image, token, &owner)))
                return TRUE;
        for (i = 0; i < container->type_argc; i++) {
-               if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container))
+               if (!get_constraints (image, start_row + i, &mono_generic_container_get_param_info (container, i)->constraints, container, error)) {
+                       g_assert (!mono_loader_get_last_error ());
                        return FALSE;
+               }
        }
        return TRUE;
 }
 
-/*
- * mono_metadata_load_generic_param_constraints:
- *
- * @image: metadata context
- * @token: metadata token to load the contraints, can be methodef or typedef.
- * @container: generic container to load into.
- *
- * Load the generic parameter constraints for the newly created generic type or method
- * represented by @token and @container.  The @container is the new container which has
- * been returned by a call to mono_metadata_load_generic_params() with this @token.
- * Memory is allocated from IMAGE's mempool.
- */
-void
-mono_metadata_load_generic_param_constraints (MonoImage *image, guint32 token,
-                                             MonoGenericContainer *container)
-{
-       mono_metadata_load_generic_param_constraints_full (image, token, container);
-       /*FIXME this function can potentially exit with a pending loader error and cause all sort of havok */
-}
-
 /*
  * mono_metadata_load_generic_params:
  *