* locales.c
[mono.git] / mono / metadata / image.c
index 0a720e2297b67d9c4c5a47f9d745c1aff29bd4f0..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)
@@ -445,7 +448,6 @@ load_modules (MonoImage *image, MonoImageOpenStatus *status)
                module_ref = g_build_filename (base_dir, name, NULL);
                image->modules [i] = mono_image_open (module_ref, status);
                if (image->modules [i]) {
-                       image->modules [i]->assembly = image->assembly;
                        //g_print ("loaded module %s from %s (%p)\n", module_ref, image->name, image->assembly);
                }
                /* 
@@ -456,6 +458,7 @@ load_modules (MonoImage *image, MonoImageOpenStatus *status)
                        *status = MONO_IMAGE_OK;
                g_free (module_ref);
        }
+
        g_free (base_dir);
 }
 
@@ -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);
 }
 
@@ -515,6 +541,7 @@ mono_image_init (MonoImage *image)
 {
        image->method_cache = g_hash_table_new (NULL, NULL);
        image->class_cache = g_hash_table_new (NULL, NULL);
+       image->field_cache = g_hash_table_new (NULL, NULL);
        image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
        image->array_cache = g_hash_table_new (NULL, NULL);
 
@@ -534,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 *
@@ -732,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);
 }
 
@@ -743,9 +780,7 @@ MonoImage *
 mono_image_loaded (const char *name)
 {
        MonoImage *res;
-       
-       if (strcmp (name, "mscorlib") == 0)
-               name = "corlib";
+        
        EnterCriticalSection (&images_mutex);
        res = g_hash_table_lookup (loaded_images_hash, name);
        LeaveCriticalSection (&images_mutex);
@@ -836,6 +871,7 @@ mono_image_open (const char *fname, MonoImageOpenStatus *status)
        image2 = g_hash_table_lookup (loaded_images_hash, fname);
        if (image2) {
                /* Somebody else beat us to it */
+               image2->ref_count ++;
                LeaveCriticalSection (&images_mutex);
                mono_image_close (image);
 
@@ -856,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
@@ -893,9 +941,11 @@ 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);
+       g_hash_table_destroy (image->field_cache);
        g_hash_table_destroy (image->array_cache);
        g_hash_table_foreach (image->name_cache, free_hash_table, NULL);
        g_hash_table_destroy (image->name_cache);
@@ -906,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);
@@ -925,7 +977,7 @@ mono_image_close (MonoImage *image)
                        g_free (ii->cli_sections);
                g_free (image->image_info);
        }
-       
+
        g_free (image);
 }
 
@@ -1103,6 +1155,46 @@ mono_image_get_resource (MonoImage *image, guint32 offset, guint32 *size)
        return data;
 }
 
+MonoImage*
+mono_image_load_file_for_image (MonoImage *image, int fileidx)
+{
+       char *base_dir, *name;
+       MonoImage *res;
+       MonoTableInfo  *t = &image->tables [MONO_TABLE_FILE];
+       const char *fname;
+       guint32 fname_id;
+
+       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);
+       name = g_build_filename (base_dir, fname, NULL);
+       res = mono_image_open (name, NULL);
+       if (res) {
+               int i;
+               t = &res->tables [MONO_TABLE_MODULEREF];
+               //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly);
+               res->assembly = image->assembly;
+               for (i = 0; i < t->rows; ++i) {
+                       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);
+       return res;
+}
+
 const char*
 mono_image_get_strong_name (MonoImage *image, guint32 *size)
 {