* locales.c
[mono.git] / mono / metadata / image.c
index bfde34cfc3fcfef14733a7a5077fd47603891b67..0c8ca5f9043e6a8c51652c3a35ae2442b0d2576a 100644 (file)
@@ -278,6 +278,9 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
        char *ptr;
        
        offset = mono_cli_rva_image_map (iinfo, iinfo->cli_cli_header.ch_metadata.rva);
+       if (offset == INVALID_ADDRESS)
+               return FALSE;
+
        size = iinfo->cli_cli_header.ch_metadata.size;
 
        if (!image->f) {
@@ -338,7 +341,7 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
                        return FALSE;
                } else {
                        g_message ("Unknown heap type: %s\n", ptr + 8);
-                       ptr += 8 + strlen (ptr) + 1;
+                       ptr += 8 + strlen (ptr + 8) + 1;
                }
                pad = ptr - image->raw_metadata;
                if (pad % 4)
@@ -492,6 +495,29 @@ load_class_names (MonoImage *image)
                g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
        }
 
+       /* Load type names from EXPORTEDTYPES table */
+       {
+               MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
+               guint32 cols [MONO_EXP_TYPE_SIZE];
+               int i;
+
+               for (i = 0; i < t->rows; ++i) {
+                       mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
+                       name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
+                       nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
+
+                       nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
+                       nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
+                       if (!nspace_table) {
+                               nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
+                               g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
+                               g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
+                                                                        nspace_table);
+                       }
+                       g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
+               }
+       }
+
        g_hash_table_destroy (name_cache2);
 }
 
@@ -535,8 +561,11 @@ mono_image_init (MonoImage *image)
        image->remoting_invoke_cache = g_hash_table_new (NULL, NULL);
        image->synchronized_cache = g_hash_table_new (NULL, NULL);
 
-       image->generics_cache = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GEqualFunc)mono_metadata_type_equal);
        image->typespec_cache = g_hash_table_new (NULL, NULL);
+
+       image->generic_inst_cache =
+               g_hash_table_new ((GHashFunc)mono_metadata_generic_inst_hash,
+                                 (GCompareFunc)mono_metadata_generic_inst_equal);
 }
 
 static MonoImage *
@@ -733,10 +762,17 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status)
        image = g_new0 (MonoImage, 1);
        image->ref_count = 1;
        image->f = filed;
-       image->name = g_strdup (fname);
        iinfo = g_new0 (MonoCLIImageInfo, 1);
        image->image_info = iinfo;
 
+       if (g_path_is_absolute (fname))
+               image->name = g_strdup (fname);
+       else {
+               gchar *path = g_get_current_dir ();
+               image->name = g_build_filename (path, fname, NULL);
+               g_free (path);
+       }
+
        return do_mono_image_load (image, status);
 }
 
@@ -745,9 +781,6 @@ mono_image_loaded (const char *name)
 {
        MonoImage *res;
         
-       if (strcmp (name, "corlib") == 0)
-               name = "mscorlib";
-
        EnterCriticalSection (&images_mutex);
        res = g_hash_table_lookup (loaded_images_hash, name);
        LeaveCriticalSection (&images_mutex);
@@ -859,6 +892,18 @@ free_hash_table (gpointer key, gpointer val, gpointer user_data)
        g_hash_table_destroy ((GHashTable*)val);
 }
 
+/**
+ * mono_image_close:
+ * @image: The image file we wish to add a reference to
+ *
+ *  Increases the reference count of an image.
+ */
+void
+mono_image_addref (MonoImage *image)
+{
+       InterlockedIncrement (&image->ref_count);
+}      
+
 /**
  * mono_image_close:
  * @image: The image file we wish to close
@@ -896,6 +941,7 @@ mono_image_close (MonoImage *image)
                g_free (image->raw_data);
 
        g_free (image->name);
+       g_free (image->files);
 
        g_hash_table_destroy (image->method_cache);
        g_hash_table_destroy (image->class_cache);
@@ -910,6 +956,8 @@ mono_image_close (MonoImage *image)
        g_hash_table_destroy (image->delegate_invoke_cache);
        g_hash_table_destroy (image->remoting_invoke_cache);
        g_hash_table_destroy (image->runtime_invoke_cache);
+       g_hash_table_destroy (image->typespec_cache);
+       g_hash_table_destroy (image->generic_inst_cache);
        
        if (image->raw_metadata != NULL)
                mono_raw_buffer_free (image->raw_metadata);
@@ -929,7 +977,7 @@ mono_image_close (MonoImage *image)
                        g_free (ii->cli_sections);
                g_free (image->image_info);
        }
-       
+
        g_free (image);
 }
 
@@ -1118,6 +1166,13 @@ mono_image_load_file_for_image (MonoImage *image, int fileidx)
 
        if (fileidx < 1 || fileidx > t->rows)
                return NULL;
+
+       if (image->files && image->files [fileidx - 1])
+               return image->files [fileidx - 1];
+
+       if (!image->files)
+               image->files = g_new0 (MonoImage*, t->rows);
+
        fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME);
        fname = mono_metadata_string_heap (image, fname_id);
        base_dir = g_path_get_dirname (image->name);
@@ -1132,6 +1187,8 @@ mono_image_load_file_for_image (MonoImage *image, int fileidx)
                        if (res->modules [i] && !res->modules [i]->assembly)
                                res->modules [i]->assembly = image->assembly;
                }
+
+               image->files [fileidx - 1] = res;
        }
        g_free (name);
        g_free (base_dir);