Apply patch from Paolo:
[mono.git] / mono / metadata / metadata.c
index 0005ad3cd35e918dcfcdcdf5d326111a8f4ecb7b..094ea0c314dcfd9f4a370283b557ac8c79ec9b08 100644 (file)
@@ -27,6 +27,7 @@ static gboolean do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoG
 
 static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
 static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
 static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
                                                    gboolean signature_only);
 
@@ -174,7 +175,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_TABLE_IDX,  /* "EventType" }, TypeDef or TypeRef  */
        MONO_MT_END,
 
-#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Event" }, */
+       MONO_MT_END,
+
+#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT32,     /* "Flags" }, */
        MONO_MT_TABLE_IDX,  /* "TypeDefId" }, */
        MONO_MT_STRING_IDX, /* "TypeName" }, */
@@ -203,7 +208,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_TABLE_IDX,  /* "Field:Field" }, */
        MONO_MT_END,
 
-#define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+       MONO_MT_TABLE_IDX,  /* "Field" }, */
+       MONO_MT_END,
+
+#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT32,     /* "Flags" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_BLOB_IDX,   /* "Value" },  */
@@ -255,7 +264,11 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_HS_IDX,     /* "Association" }, */
        MONO_MT_END,
 
-#define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Method" }, */
+       MONO_MT_END,
+
+#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT16,     /* "Generation" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_GUID_IDX,   /* "MVID" }, */
@@ -278,13 +291,21 @@ const static unsigned char TableSchemas [] = {
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_END,
 
-#define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+#define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX,  /* "Param" }, */
+       MONO_MT_END,
+
+#define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_UINT16,     /* "Flags" }, */
        MONO_MT_STRING_IDX, /* "Name" }, */
        MONO_MT_BLOB_IDX,   /* "Type" }, */
        MONO_MT_END,
 
-#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+       MONO_MT_TABLE_IDX, /* "Property" }, */
+       MONO_MT_END,
+
+#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
        MONO_MT_TABLE_IDX,  /* "Parent:TypeDef" }, */
        MONO_MT_TABLE_IDX,  /* "PropertyList:Property" }, */
        MONO_MT_END,
@@ -339,11 +360,11 @@ table_description [] = {
        MODULE_SCHEMA_OFFSET,
        TYPEREF_SCHEMA_OFFSET,
        TYPEDEF_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       FIELD_POINTER_SCHEMA_OFFSET,
        FIELD_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       METHOD_POINTER_SCHEMA_OFFSET,
        METHOD_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       PARAM_POINTER_SCHEMA_OFFSET,
        PARAM_SCHEMA_OFFSET,
        IFACEMAP_SCHEMA_OFFSET,
        MEMBERREF_SCHEMA_OFFSET, /* 0xa */
@@ -355,10 +376,10 @@ table_description [] = {
        FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
        STDALON_SIG_SCHEMA_OFFSET,
        EVENTMAP_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       EVENT_POINTER_SCHEMA_OFFSET,
        EVENT_SCHEMA_OFFSET,
        PROPERTY_MAP_SCHEMA_OFFSET,
-       NULL_SCHEMA_OFFSET,
+       PROPERTY_POINTER_SCHEMA_OFFSET,
        PROPERTY_SCHEMA_OFFSET,
        METHOD_SEMA_SCHEMA_OFFSET,
        METHOD_IMPL_SCHEMA_OFFSET,
@@ -511,6 +532,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                                field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
                                field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
                                break;
+                       case MONO_TABLE_EVENT_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_EVENT); break;
                        case MONO_TABLE_EXPORTEDTYPE:
                                g_assert (i == 1);
                                /* the index is in another metadata file, so it must be 4 */
@@ -521,6 +545,9 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_FIELDRVA:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_FIELD); break;
+                       case MONO_TABLE_FIELD_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_FIELD); break;
                        case MONO_TABLE_IMPLMAP:
                                g_assert (i == 3);
                                field_size = idx_size (MONO_TABLE_MODULEREF); break;
@@ -536,14 +563,23 @@ mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bit
                        case MONO_TABLE_METHODSEMANTICS:
                                g_assert (i == 1);
                                field_size = idx_size (MONO_TABLE_METHOD); break;
+                       case MONO_TABLE_METHOD_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_METHOD); break;
                        case MONO_TABLE_NESTEDCLASS:
                                g_assert (i == 0 || i == 1);
                                field_size = idx_size (MONO_TABLE_TYPEDEF); break;
+                       case MONO_TABLE_PARAM_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_PARAM); break;
                        case MONO_TABLE_PROPERTYMAP:
                                g_assert (i == 0 || i == 1);
                                field_size = i ? idx_size (MONO_TABLE_PROPERTY):
                                        idx_size(MONO_TABLE_TYPEDEF); 
                                break;
+                       case MONO_TABLE_PROPERTY_POINTER:
+                               g_assert (i == 0);
+                               field_size = idx_size (MONO_TABLE_PROPERTY); break;
                        case MONO_TABLE_TYPEDEF:
                                g_assert (i == 4 || i == 5);
                                field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
@@ -966,6 +1002,7 @@ mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
        }
        return 0;
 }
+
 /**
  * mono_metadata_decode_blob_size:
  * @ptr: pointer to a blob object
@@ -1067,6 +1104,82 @@ mono_metadata_decode_signed_value (const char *ptr, const char **rptr)
        return ival - 0x20000000;
 }
 
+/* 
+ * Translates the given 1-based index into the Method, Field, Event, or Param tables
+ * using the *Ptr tables in uncompressed metadata, if they are available.
+ *
+ * FIXME: The caller is not forced to call this function, which is error-prone, since 
+ * forgetting to call it would only show up as a bug on uncompressed metadata.
+ */
+guint32
+mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
+{
+       if (!image->uncompressed_metadata)
+               return idx;
+
+       switch (table) {
+       case MONO_TABLE_METHOD:
+               if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
+               else
+                       return idx;
+       case MONO_TABLE_FIELD:
+               if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
+               else
+                       return idx;
+       case MONO_TABLE_EVENT:
+               if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
+               else
+                       return idx;
+       case MONO_TABLE_PROPERTY:
+               if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
+               else
+                       return idx;
+       case MONO_TABLE_PARAM:
+               if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
+                       return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
+               else
+                       return idx;
+       default:
+               return idx;
+       }
+}
+
+/**
+ * mono_metadata_decode_table_row:
+ *
+ *   Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables when the access is made from metadata, i.e.
+ * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
+ */
+void
+mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
+{
+       if (image->uncompressed_metadata)
+               idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+       mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
+}
+
+/**
+ * mono_metadata_decode_table_row_col:
+ *
+ *   Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables.
+ */
+guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
+{
+       if (image->uncompressed_metadata)
+               idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+       return mono_metadata_decode_row_col (&image->tables [table], idx, col);
+}
+
 /*
  * mono_metadata_parse_typedef_or_ref:
  * @m: a metadata context.
@@ -1377,6 +1490,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        int count = 0;
        gboolean found;
 
+       mono_loader_lock ();
        /*
         * According to the spec, custom modifiers should come before the byref
         * flag, but the IL produced by ilasm from the following signature:
@@ -1448,6 +1562,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
        if (!do_mono_metadata_parse_type (type, m, container, ptr, &ptr)) {
                if (type != &stype)
                        g_free (type);
+               mono_loader_unlock ();
                return NULL;
        }
 
@@ -1477,12 +1592,16 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
                           LOCKING: even though we don't explicitly hold a lock, in the problematic case 'ret' is a field
                                    of a MonoClass which currently holds the loader lock.  'type' is local.
                        */
-                       if (ret->data.klass == type->data.klass)
+                       if (ret->data.klass == type->data.klass) {
+                               mono_loader_unlock ();
                                return ret;
+                       }
                }
                /* No need to use locking since nobody is modifying the hash table */
-               if ((cached = g_hash_table_lookup (type_cache, type)))
+               if ((cached = g_hash_table_lookup (type_cache, type))) {
+                       mono_loader_unlock ();
                        return cached;
+               }
        }
        
        /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
@@ -1491,6 +1610,7 @@ mono_metadata_parse_type_full (MonoImage *m, MonoGenericContainer *container, Mo
                type = mono_mempool_alloc (m->mempool, sizeof (MonoType));
                memcpy (type, &stype, sizeof (MonoType));
        }
+       mono_loader_unlock ();
        return type;
 }
 
@@ -1517,16 +1637,16 @@ mono_metadata_get_param_attrs (MonoImage *m, int def)
        MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
        MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
        guint32 cols [MONO_PARAM_SIZE];
-       guint lastp, i, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
+       guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST);
        int *pattrs = NULL;
 
        if (def < methodt->rows)
-               lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
+               lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST);
        else
                lastp = paramt->rows + 1;
 
        for (i = param_index; i < lastp; ++i) {
-               mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
+               mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE);
                if (cols [MONO_PARAM_FLAGS]) {
                        if (!pattrs)
                                pattrs = g_new0 (int, 1 + (lastp - param_index));
@@ -1603,9 +1723,11 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
 {
        MonoMethodSignature *sig;
 
+       mono_loader_lock ();
        sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
        sig->param_count = nparams;
        sig->sentinelpos = -1;
+       mono_loader_unlock ();
 
        return sig;
 }
@@ -1687,6 +1809,8 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
                if (*ptr == MONO_TYPE_SENTINEL) {
                        if (method->call_convention != MONO_CALL_VARARG || def)
                                g_error ("found sentinel for methoddef or no vararg method");
+                       if (method->sentinelpos >= 0)
+                               g_error ("found sentinel twice in the same signature");
                        method->sentinelpos = i;
                        ptr++;
                }
@@ -1700,6 +1824,10 @@ mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContainer *c
                        is_open = mono_class_is_open_constructed_type (method->params [i]);
        }
 
+       /* The sentinel could be missing if the caller does not pass any additional arguments */
+       if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
+               method->sentinelpos = method->param_count;
+
        method->has_type_parameters = is_open;
 
        if (def && (method->call_convention == MONO_CALL_VARARG))
@@ -1880,7 +2008,7 @@ mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContainer *container,
        return mono_metadata_lookup_generic_inst (ginst);
 }
 
-static void
+static gboolean
 do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
                                      const char *ptr, const char **rptr)
 {
@@ -1907,6 +2035,8 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
        igclass->klass = g_new0 (MonoClass, 1);
 
        gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+       if (gtype == NULL)
+               return FALSE;
        gclass->container_class = gklass = mono_class_from_mono_type (gtype);
 
        g_assert (gklass->generic_container);
@@ -1919,6 +2049,10 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
        if (rptr)
                *rptr = ptr;
 
+       /* If we failed to parse, return, the error has been flagged. */
+       if (gclass->inst == NULL)
+               return FALSE;
+       
        /*
         * We may be called multiple times on different metadata to create the same
         * instantiated type.  This happens for instance if we're part of a method or
@@ -1939,7 +2073,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
                g_free (gclass);
 
                type->data.generic_class = cached;
-               return;
+               return TRUE;
        } else {
                g_hash_table_insert (generic_class_cache, gclass, gclass);
 
@@ -1948,6 +2082,7 @@ do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericC
                        sizeof (MonoGenericContext) +
                        gclass->inst->type_argc * sizeof (MonoType);
        }
+       return TRUE;
 }
 
 /*
@@ -1965,17 +2100,14 @@ select_container (MonoGenericContainer *gc, MonoTypeEnum type)
 
        g_assert (is_var || type == MONO_TYPE_MVAR);
 
-       if (is_var && gc->parent)
-               /*
-                * The current MonoGenericContainer is a generic method -> its `parent'
-                * points to the containing class'es container.
-                */
-               gc = gc->parent;
-
-       /*
-        * Ensure that we have the correct type of GenericContainer.
-        */
-       g_assert (is_var == !gc->is_method);
+       if (is_var) {
+               if (gc->is_method || gc->parent)
+                       /*
+                        * The current MonoGenericContainer is a generic method -> its `parent'
+                        * points to the containing class'es container.
+                        */
+                       return gc->parent;
+       }
 
        return gc;
 }
@@ -2032,6 +2164,7 @@ static gboolean
 do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
                             const char *ptr, const char **rptr)
 {
+       gboolean ok = TRUE;
        type->type = mono_metadata_decode_value (ptr, &ptr);
        
        switch (type->type){
@@ -2087,7 +2220,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
                type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
                break;
        case MONO_TYPE_GENERICINST:
-               do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
+               ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
                break;
        default:
                g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
@@ -2095,7 +2228,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer
        
        if (rptr)
                *rptr = ptr;
-       return TRUE;
+       return ok;
 }
 
 /*
@@ -2265,6 +2398,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        
        g_return_val_if_fail (ptr != NULL, NULL);
 
+       mono_loader_lock ();
        switch (format) {
        case METHOD_HEADER_TINY_FORMAT:
                mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
@@ -2273,6 +2407,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                local_var_sig_tok = 0;
                mh->code_size = flags >> 2;
                mh->code = ptr;
+               mono_loader_unlock ();
                return mh;
        case METHOD_HEADER_TINY_FORMAT1:
                mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
@@ -2286,6 +2421,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                 */
                mh->code_size = flags >> 2;
                mh->code = ptr;
+               mono_loader_unlock ();
                return mh;
        case METHOD_HEADER_FAT_FORMAT:
                fat_flags = read16 (ptr);
@@ -2314,6 +2450,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                ptr = code + code_size;
                break;
        default:
+               mono_loader_unlock ();
                return NULL;
        }
                       
@@ -2336,7 +2473,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
                        mh->locals [i] = mono_metadata_parse_type_full (
                                m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
                        if (!mh->locals [i]) {
-                               g_free (mh);
+                               mono_loader_unlock ();
                                return NULL;
                        }
                }
@@ -2349,6 +2486,7 @@ mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, cons
        mh->init_locals = init_locals;
        if (fat_flags & METHOD_HEADER_MORE_SECTS)
                parse_section_data (m, mh, (const unsigned char*)ptr);
+       mono_loader_unlock ();
        return mh;
 }
 
@@ -2663,6 +2801,30 @@ declsec_locator (const void *a, const void *b)
                return 1;
 }
 
+/**
+ * search_ptr_table:
+ *
+ *  Return the 1-based row index in TABLE, which must be one of the *Ptr tables, 
+ * which contains IDX.
+ */
+static guint32
+search_ptr_table (MonoImage *image, int table, int idx)
+{
+       MonoTableInfo *ptrdef = &image->tables [table];
+       int i;
+
+       /* Use a linear search to find our index in the table */
+       for (i = 0; i < ptrdef->rows; i ++)
+               /* All the Ptr tables have the same structure */
+               if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
+                       break;
+
+       if (i < ptrdef->rows)
+               return i + 1;
+       else
+               return idx;
+}
+
 /**
  * mono_metadata_typedef_from_field:
  * @meta: metadata context
@@ -2684,6 +2846,9 @@ mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
        loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
        loc.t = tdef;
 
+       if (meta->uncompressed_metadata)
+               loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
                g_assert_not_reached ();
 
@@ -2712,6 +2877,9 @@ mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
        loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
        loc.t = tdef;
 
+       if (meta->uncompressed_metadata)
+               loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
+
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
                g_assert_not_reached ();
 
@@ -2771,15 +2939,22 @@ mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, Mono
                ++pos;
        }
 
+       mono_loader_lock ();
        result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start));
+       mono_loader_unlock ();
 
        pos = start;
        while (pos < tdef->rows) {
+               MonoClass *iface;
+               
                mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
                if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
                        break;
-               result [pos - start] = mono_class_get_full (
+               iface = mono_class_get_full (
                        meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
+               if (iface == NULL)
+                       return FALSE;
+               result [pos - start] = iface;
                ++pos;
        }
        *count = pos - start;
@@ -2923,6 +3098,8 @@ mono_metadata_custom_attrs_from_index (MonoImage *meta, guint32 index)
        loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
        loc.t = tdef;
 
+       /* FIXME: Index translation */
+
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return 0;
 
@@ -2993,10 +3170,9 @@ mono_backtrace (int limit)
  *
  * Returns: the number of bytes required to hold an instance of this
  * type in memory
- * FIXME: This should really use 'guint32*' for the align parameter.
  */
 int
-mono_type_size (MonoType *t, gint *align)
+mono_type_size (MonoType *t, int *align)
 {
        if (!t) {
                *align = 1;
@@ -3099,12 +3275,11 @@ mono_type_size (MonoType *t, gint *align)
  *
  * Returns: the number of bytes required to hold an instance of this
  * type on the runtime stack
- * FIXME: This should really use 'guint32*' for the align parameter.
  */
 int
-mono_type_stack_size (MonoType *t, gint *align)
+mono_type_stack_size (MonoType *t, int *align)
 {
-       int tmp;
+       guint32 tmp;
 
        g_assert (t != NULL);
 
@@ -3311,6 +3486,37 @@ mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only
        return FALSE;
 }
 
+static gboolean
+mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
+{
+       gpointer iter1 = 0, iter2 = 0;
+
+       if (s1 == s2)
+               return TRUE;
+       if (s1->call_convention != s2->call_convention)
+               return FALSE;
+       if (s1->sentinelpos != s2->sentinelpos)
+               return FALSE;
+       if (s1->hasthis != s2->hasthis)
+               return FALSE;
+       if (s1->explicit_this != s2->explicit_this)
+               return FALSE;
+       if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
+               return FALSE;
+       if (s1->param_count != s2->param_count)
+               return FALSE;
+
+       while (TRUE) {
+               MonoType *t1 = mono_signature_get_params (s1, &iter1);
+               MonoType *t2 = mono_signature_get_params (s2, &iter2);
+
+               if (t1 == NULL || t2 == NULL)
+                       return (t1 == t2);
+               if (! do_mono_metadata_type_equal (t1, t2, signature_only))
+                       return FALSE;
+       }
+}
+
 /*
  * mono_metadata_type_equal:
  * @t1: a type
@@ -3364,6 +3570,8 @@ do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only
        case MONO_TYPE_MVAR:
                return mono_metadata_generic_param_equal (
                        t1->data.generic_param, t2->data.generic_param, signature_only);
+       case MONO_TYPE_FNPTR:
+               return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
        default:
                g_error ("implement type compare for %0x!", t1->type);
                return FALSE;
@@ -3420,6 +3628,31 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
        return TRUE;
 }
 
+/**
+ * mono_metadata_type_dup_mp:
+ * @image: image type is defined in
+ * @original: type to duplicate
+ *
+ * Returns: copy of type allocated from mempool.
+ */
+MonoType *
+mono_metadata_type_dup_mp (MonoImage *image, const MonoType *original)
+{
+       MonoType *r = NULL;
+       mono_loader_lock ();
+       r = mono_mempool_alloc0 (image->mempool, sizeof(MonoType));
+       mono_loader_unlock ();
+       *r = *original;
+       /* FIXME: we don't handle these yet because they need to duplicate memory
+        * but the current routines used are not using the mempools
+        */
+       if (original->type == MONO_TYPE_PTR || 
+               original->type == MONO_TYPE_ARRAY || 
+               original->type == MONO_TYPE_FNPTR)
+               g_assert_not_reached ();
+       return r;
+}
+
 guint
 mono_signature_hash (MonoMethodSignature *sig)
 {
@@ -3487,6 +3720,9 @@ mono_metadata_field_info (MonoImage *meta, guint32 index, guint32 *offset, guint
        locator_t loc;
 
        loc.idx = index + 1;
+       if (meta->uncompressed_metadata)
+               loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
        if (offset) {
                tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
 
@@ -3561,6 +3797,8 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
        loc.col_idx = MONO_CONSTANT_PARENT;
        loc.t = tdef;
 
+       /* FIXME: Index translation */
+
        if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
                return hint;
 
@@ -3630,6 +3868,9 @@ mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_i
        if (!msemt->base)
                return 0;
 
+       if (meta->uncompressed_metadata)
+           index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
+
        loc.t = msemt;
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
        loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
@@ -3718,6 +3959,9 @@ mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *en
        if (!msemt->base)
                return 0;
 
+       if (meta->uncompressed_metadata)
+           index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
+
        loc.t = msemt;
        loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
        loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
@@ -3755,6 +3999,8 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
        if (!tdef->base)
                return 0;
 
+       /* No index translation seems to be needed */
+
        loc.t = tdef;
        loc.col_idx = MONO_IMPLMAP_MEMBER;
        loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
@@ -4076,6 +4322,8 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
        loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
        loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
 
+       /* FIXME: Index translation */
+
        if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
                return NULL;
 
@@ -4086,6 +4334,7 @@ static MonoMethod*
 method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
 {
        guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
+
        switch (tok & MONO_METHODDEFORREF_MASK) {
        case MONO_METHODDEFORREF_METHODDEF:
                return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
@@ -4114,7 +4363,8 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
        gint32 i, num;
        guint32 cols [MONO_METHODIMPL_SIZE];
        MonoMethod **result;
-
+       gint32 ok = TRUE;
+       
        *overrides = NULL;
        if (num_overrides)
                *num_overrides = 0;
@@ -4149,17 +4399,25 @@ mono_class_get_overrides_full (MonoImage *image, guint32 type_token, MonoMethod
        num = end - start;
        result = g_new (MonoMethod*, num * 2);
        for (i = 0; i < num; ++i) {
+               MonoMethod *method;
+
                mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
-               result [i * 2] = method_from_method_def_or_ref (
+               method = method_from_method_def_or_ref (
                        image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
-               result [i * 2 + 1] = method_from_method_def_or_ref (
+               if (method == NULL)
+                       ok = FALSE;
+               result [i * 2] = method;
+               method = method_from_method_def_or_ref (
                        image, cols [MONO_METHODIMPL_BODY], generic_context);
+               if (method == NULL)
+                       ok = FALSE;
+               result [i * 2 + 1] = method;
        }
 
        *overrides = result;
        if (num_overrides)
                *num_overrides = num;
-       return TRUE;
+       return ok;
 }
 
 /**
@@ -4372,6 +4630,13 @@ mono_type_get_array_type (MonoType *type)
        return type->data.array;
 }
 
+/* For MONO_TYPE_PTR */
+MonoType*
+mono_type_get_ptr_type (MonoType *type)
+{
+       return type->data.type;
+}
+
 MonoClass*
 mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
 {