2009-07-30 Rodrigo Kumpera <rkumpera@novell.com>
[mono.git] / mono / metadata / image.c
index 1093db2d7ad2c4f6aff8a19323855b20a2d901cc..47e85ea3690f288ec47d69d71eecf955f1c90f19 100644 (file)
@@ -34,6 +34,8 @@
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/object-internals.h>
+#include <mono/metadata/security-core-clr.h>
+#include <mono/metadata/verify-internals.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
@@ -128,7 +130,7 @@ mono_images_init (void)
        loaded_images_hash = g_hash_table_new (g_str_hash, g_str_equal);
        loaded_images_refonly_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
-       debug_assembly_unload = getenv ("MONO_DEBUG_ASSEMBLY_UNLOAD") != NULL;
+       debug_assembly_unload = g_getenv ("MONO_DEBUG_ASSEMBLY_UNLOAD") != NULL;
 }
 
 /**
@@ -333,9 +335,9 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
 
                ptr += 4;
                image->md_version_major = read16 (ptr);
-               ptr += 4;
+               ptr += 2;
                image->md_version_minor = read16 (ptr);
-               ptr += 4;
+               ptr += 6;
 
                version_string_len = read32 (ptr);
                ptr += 4;
@@ -615,6 +617,7 @@ mono_image_init (MonoImage *image)
 
        image->property_hash = mono_property_hash_new ();
        InitializeCriticalSection (&image->lock);
+       InitializeCriticalSection (&image->szarray_cache_lock);
 }
 
 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
@@ -766,24 +769,16 @@ do_load_header (MonoImage *image, MonoDotNetHeader *header, int offset)
        return offset;
 }
 
-static MonoImage *
-do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
-                   gboolean care_about_cli)
+gboolean
+mono_image_load_pe_data (MonoImage *image)
 {
        MonoCLIImageInfo *iinfo;
        MonoDotNetHeader *header;
        MonoMSDOSHeader msdos;
        gint32 offset = 0;
 
-       mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
-
-       mono_image_init (image);
-
        iinfo = image->image_info;
        header = &iinfo->cli_header;
-               
-       if (status)
-               *status = MONO_IMAGE_IMAGE_INVALID;
 
 #ifdef PLATFORM_WIN32
        if (!image->is_module_handle)
@@ -832,18 +827,35 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        
        if (!load_section_tables (image, iinfo, offset))
                goto invalid_image;
-       
-       if (care_about_cli == FALSE) {
-               goto done;
-       }
-       
+
+       return TRUE;
+
+invalid_image:
+       return FALSE;
+}
+
+gboolean
+mono_image_load_cli_data (MonoImage *image)
+{
+       MonoCLIImageInfo *iinfo;
+       MonoDotNetHeader *header;
+
+       iinfo = image->image_info;
+       header = &iinfo->cli_header;
+
        /* Load the CLI header */
        if (!load_cli_header (image, iinfo))
-               goto invalid_image;
+               return FALSE;
 
        if (!load_metadata (image, iinfo))
-               goto invalid_image;
+               return FALSE;
+
+       return TRUE;
+}
 
+void
+mono_image_load_names (MonoImage *image)
+{
        /* modules don't have an assembly table row */
        if (image->tables [MONO_TABLE_ASSEMBLY].rows) {
                image->assembly_name = mono_metadata_string_heap (image, 
@@ -854,6 +866,48 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        image->module_name = mono_metadata_string_heap (image, 
                        mono_metadata_decode_row_col (&image->tables [MONO_TABLE_MODULE],
                                        0, MONO_MODULE_NAME));
+}
+
+static MonoImage *
+do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
+                   gboolean care_about_cli, gboolean care_about_pecoff)
+{
+       MonoCLIImageInfo *iinfo;
+       MonoDotNetHeader *header;
+
+       mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
+
+       mono_image_init (image);
+
+       iinfo = image->image_info;
+       header = &iinfo->cli_header;
+               
+       if (status)
+               *status = MONO_IMAGE_IMAGE_INVALID;
+
+       if (care_about_pecoff == FALSE)
+               goto done;
+
+       if (!mono_verifier_verify_pe_data (image, NULL))
+               goto invalid_image;
+
+       if (!mono_image_load_pe_data (image))
+               goto invalid_image;
+       
+       if (care_about_cli == FALSE) {
+               goto done;
+       }
+
+       if (!mono_verifier_verify_cli_data (image, NULL))
+               goto invalid_image;
+
+       if (!mono_image_load_cli_data (image))
+               goto invalid_image;
+
+       if (!mono_verifier_verify_table_data (image, NULL))
+               goto invalid_image;
+
+       mono_image_load_names (image);
 
        load_modules (image);
 
@@ -872,7 +926,7 @@ invalid_image:
 
 static MonoImage *
 do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
-                   gboolean care_about_cli, gboolean refonly)
+                   gboolean care_about_cli, gboolean care_about_pecoff, gboolean refonly)
 {
        MonoCLIImageInfo *iinfo;
        MonoImage *image;
@@ -910,9 +964,11 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
        image->name = mono_path_resolve_symlinks (fname);
        image->ref_only = refonly;
        image->ref_count = 1;
+       /* if MONO_SECURITY_MODE_CORE_CLR is set then determine if this image is platform code */
+       image->core_clr_platform_code = mono_security_core_clr_determine_platform_image (image);
 
        mono_file_map_close (filed);
-       return do_mono_image_load (image, status, care_about_cli);
+       return do_mono_image_load (image, status, care_about_cli, care_about_pecoff);
 }
 
 MonoImage *
@@ -1035,7 +1091,7 @@ mono_image_open_from_data_full (char *data, guint32 data_len, gboolean need_copy
        image->image_info = iinfo;
        image->ref_only = refonly;
 
-       image = do_mono_image_load (image, status, TRUE);
+       image = do_mono_image_load (image, status, TRUE, TRUE);
        if (image == NULL)
                return NULL;
 
@@ -1065,7 +1121,7 @@ mono_image_open_from_module_handle (HMODULE module_handle, char* fname, gboolean
        image->ref_count = has_entry_point ? 0 : 1;
        image->has_entry_point = has_entry_point;
 
-       image = do_mono_image_load (image, status, TRUE);
+       image = do_mono_image_load (image, status, TRUE, TRUE);
        if (image == NULL)
                return NULL;
 
@@ -1168,7 +1224,7 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r
        }
        mono_images_unlock ();
 
-       image = do_mono_image_open (fname, status, TRUE, refonly);
+       image = do_mono_image_open (fname, status, TRUE, TRUE, refonly);
        if (image == NULL)
                return NULL;
 
@@ -1207,7 +1263,24 @@ mono_pe_file_open (const char *fname, MonoImageOpenStatus *status)
 {
        g_return_val_if_fail (fname != NULL, NULL);
        
-       return(do_mono_image_open (fname, status, FALSE, FALSE));
+       return(do_mono_image_open (fname, status, FALSE, TRUE, FALSE));
+}
+
+/**
+ * mono_image_open_raw
+ * @fname: filename that points to the module we want to open
+ * @status: An error condition is returned in this field
+ * 
+ * Returns an image without loading neither pe or cli data.
+ * 
+ * Use mono_image_load_pe_data and mono_image_load_cli_data to load them.  
+ */
+MonoImage *
+mono_image_open_raw (const char *fname, MonoImageOpenStatus *status)
+{
+       g_return_val_if_fail (fname != NULL, NULL);
+       
+       return(do_mono_image_open (fname, status, FALSE, FALSE, FALSE));
 }
 
 void
@@ -1244,12 +1317,12 @@ mono_image_fixup_vtable (MonoImage *image)
                if (slot_type & VTFIXUP_TYPE_32BIT)
                        while (slot_count--) {
                                *((guint32*) slot) = (guint32) mono_marshal_get_vtfixup_ftnptr (image, *((guint32*) slot), slot_type);
-                               ((guint32*) slot)++;
+                               slot = ((guint32*) slot) + 1;
                        }
                else if (slot_type & VTFIXUP_TYPE_64BIT)
                        while (slot_count--) {
                                *((guint64*) slot) = (guint64) mono_marshal_get_vtfixup_ftnptr (image, *((guint64*) slot), slot_type);
-                               ((guint64*) slot)++;
+                               slot = ((guint32*) slot) + 1;
                        }
                else
                        g_assert_not_reached();
@@ -1432,6 +1505,8 @@ mono_image_close (MonoImage *image)
                g_hash_table_foreach (image->array_cache, free_array_cache_entry, NULL);
                g_hash_table_destroy (image->array_cache);
        }
+       if (image->szarray_cache)
+               g_hash_table_destroy (image->szarray_cache);
        if (image->ptr_cache)
                g_hash_table_destroy (image->ptr_cache);
        if (image->name_cache) {
@@ -1450,6 +1525,7 @@ mono_image_close (MonoImage *image)
        free_hash (image->remoting_invoke_cache);
        free_hash (image->runtime_invoke_cache);
        free_hash (image->runtime_invoke_direct_cache);
+       free_hash (image->runtime_invoke_vcall_cache);
        free_hash (image->synchronized_cache);
        free_hash (image->unbox_wrapper_cache);
        free_hash (image->cominterop_invoke_cache);
@@ -1462,7 +1538,6 @@ mono_image_close (MonoImage *image)
        free_hash (image->castclass_cache);
        free_hash (image->proxy_isinst_cache);
        free_hash (image->thunk_invoke_cache);
-       free_hash (image->static_rgctx_invoke_cache);
 
        /* The ownership of signatures is not well defined */
        //g_hash_table_foreach (image->memberref_signatures, free_mr_signatures, NULL);
@@ -1506,6 +1581,7 @@ mono_image_close (MonoImage *image)
                g_free (image->references);
        mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (image->mempool);
 
+       DeleteCriticalSection (&image->szarray_cache_lock);
        DeleteCriticalSection (&image->lock);
 
        /*g_print ("destroy image %p (dynamic: %d)\n", image, image->dynamic);*/
@@ -1520,7 +1596,10 @@ mono_image_close (MonoImage *image)
                /* Dynamic images are GC_MALLOCed */
                g_free ((char*)image->module_name);
                mono_dynamic_image_free ((MonoDynamicImage*)image);
-               mono_mempool_destroy (image->mempool);
+               if (debug_assembly_unload)
+                       mono_mempool_invalidate (image->mempool);
+               else
+                       mono_mempool_destroy (image->mempool);
        }
 
        mono_profiler_module_event (image, MONO_PROFILE_END_UNLOAD);