Merge pull request #2338 from BogdanovKirill/httpwritefix3
[mono.git] / mono / metadata / image.c
index 56403f3463a61b24e0fc601a4b9fbb761ec78eae..fbbf58f6b3ea541d87a28fd78b583fa492585bbb 100644 (file)
@@ -27,7 +27,7 @@
 #include "marshal.h"
 #include "coree.h"
 #include <mono/io-layer/io-layer.h>
-#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-logger-internals.h>
 #include <mono/utils/mono-path.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-io-portability.h>
@@ -38,6 +38,7 @@
 #include <mono/metadata/security-core-clr.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/verify.h>
+#include <mono/metadata/image-internals.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #ifdef HAVE_UNISTD_H
 
 #define INVALID_ADDRESS 0xffffffff
 
+// Amount initially reserved in each image's mempool.
+// FIXME: This number is arbitrary, a more practical number should be found
+#define INITIAL_IMAGE_SIZE    512
+
 /*
- * Keeps track of the various assemblies loaded
+ * The "loaded images" hashes keep track of the various assemblies and netmodules loaded
+ * There are four, for all combinations of [look up by path or assembly name?]
+ * and [normal or reflection-only load?, as in Assembly.ReflectionOnlyLoad]
  */
-static GHashTable *loaded_images_hash;
-static GHashTable *loaded_images_refonly_hash;
+enum {
+       IMAGES_HASH_PATH = 0,
+       IMAGES_HASH_PATH_REFONLY = 1,
+       IMAGES_HASH_NAME = 2,
+       IMAGES_HASH_NAME_REFONLY = 3,
+       IMAGES_HASH_COUNT = 4
+};
+static GHashTable *loaded_images_hashes [4] = {NULL, NULL, NULL, NULL};
+
+static GHashTable *get_loaded_images_hash (gboolean refonly)
+{
+       int idx = refonly ? IMAGES_HASH_PATH_REFONLY : IMAGES_HASH_PATH;
+       return loaded_images_hashes [idx];
+}
+
+static GHashTable *get_loaded_images_by_name_hash (gboolean refonly)
+{
+       int idx = refonly ? IMAGES_HASH_NAME_REFONLY : IMAGES_HASH_NAME;
+       return loaded_images_hashes [idx];
+}
 
 static gboolean debug_assembly_unload = FALSE;
 
-#define mono_images_lock() if (mutex_inited) mono_mutex_lock (&images_mutex)
-#define mono_images_unlock() if (mutex_inited) mono_mutex_unlock (&images_mutex)
+#define mono_images_lock() if (mutex_inited) mono_os_mutex_lock (&images_mutex)
+#define mono_images_unlock() if (mutex_inited) mono_os_mutex_unlock (&images_mutex)
 static gboolean mutex_inited;
 static mono_mutex_t images_mutex;
 
+static void install_pe_loader (void);
+
 typedef struct ImageUnloadHook ImageUnloadHook;
 struct ImageUnloadHook {
        MonoImageUnloadFunc func;
@@ -87,7 +114,7 @@ mono_remove_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data)
        ImageUnloadHook *hook;
 
        for (l = image_unload_hooks; l; l = l->next) {
-               hook = l->data;
+               hook = (ImageUnloadHook *)l->data;
 
                if (hook->func == func && hook->user_data == user_data) {
                        g_free (hook);
@@ -104,17 +131,25 @@ mono_image_invoke_unload_hook (MonoImage *image)
        ImageUnloadHook *hook;
 
        for (l = image_unload_hooks; l; l = l->next) {
-               hook = l->data;
+               hook = (ImageUnloadHook *)l->data;
 
                hook->func (image, hook->user_data);
        }
 }
 
+static GSList *image_loaders;
+
+void
+mono_install_image_loader (const MonoImageLoader *loader)
+{
+       image_loaders = g_slist_prepend (image_loaders, (MonoImageLoader*)loader);
+}
+
 /* returns offset relative to image->raw_data */
 guint32
 mono_cli_rva_image_map (MonoImage *image, guint32 addr)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        const int top = iinfo->cli_section_count;
        MonoSectionTable *tables = iinfo->cli_section_tables;
        int i;
@@ -150,7 +185,7 @@ mono_cli_rva_image_map (MonoImage *image, guint32 addr)
 char *
 mono_image_rva_map (MonoImage *image, guint32 addr)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        const int top = iinfo->cli_section_count;
        MonoSectionTable *tables = iinfo->cli_section_tables;
        int i;
@@ -187,13 +222,16 @@ mono_image_rva_map (MonoImage *image, guint32 addr)
 void
 mono_images_init (void)
 {
-       mono_mutex_init_recursive (&images_mutex);
+       mono_os_mutex_init_recursive (&images_mutex);
 
-       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);
+       int hash_idx;
+       for(hash_idx = 0; hash_idx < IMAGES_HASH_COUNT; hash_idx++)
+               loaded_images_hashes [hash_idx] = g_hash_table_new (g_str_hash, g_str_equal);
 
        debug_assembly_unload = g_getenv ("MONO_DEBUG_ASSEMBLY_UNLOAD") != NULL;
 
+       install_pe_loader ();
+
        mutex_inited = TRUE;
 }
 
@@ -208,14 +246,17 @@ mono_images_cleanup (void)
        GHashTableIter iter;
        MonoImage *image;
 
-       mono_mutex_destroy (&images_mutex);
+       mono_os_mutex_destroy (&images_mutex);
 
-       g_hash_table_iter_init (&iter, loaded_images_hash);
+       // If an assembly image is still loaded at shutdown, this could indicate managed code is still running.
+       // Reflection-only images being still loaded doesn't indicate anything as harmful, so we don't check for it.
+       g_hash_table_iter_init (&iter, get_loaded_images_hash (FALSE));
        while (g_hash_table_iter_next (&iter, NULL, (void**)&image))
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly image '%s' still loaded at shutdown.", image->name);
 
-       g_hash_table_destroy (loaded_images_hash);
-       g_hash_table_destroy (loaded_images_refonly_hash);
+       int hash_idx;
+       for(hash_idx = 0; hash_idx < IMAGES_HASH_COUNT; hash_idx++)
+               g_hash_table_destroy (loaded_images_hashes [hash_idx]);
 
        mutex_inited = FALSE;
 }
@@ -233,7 +274,7 @@ mono_images_cleanup (void)
 int
 mono_image_ensure_section_idx (MonoImage *image, int section)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        MonoSectionTable *sect;
        
        g_return_val_if_fail (section < iinfo->cli_section_count, FALSE);
@@ -268,7 +309,7 @@ mono_image_ensure_section_idx (MonoImage *image, int section)
 int
 mono_image_ensure_section (MonoImage *image, const char *section)
 {
-       MonoCLIImageInfo *ii = image->image_info;
+       MonoCLIImageInfo *ii = (MonoCLIImageInfo *)image->image_info;
        int i;
        
        for (i = 0; i < ii->cli_section_count; i++){
@@ -315,8 +356,8 @@ load_section_tables (MonoImage *image, MonoCLIImageInfo *iinfo, guint32 offset)
        return TRUE;
 }
 
-static gboolean
-load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo)
+gboolean
+mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo)
 {
        guint32 offset;
        
@@ -466,12 +507,13 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
                        ptr += 4 - (pad % 4);
        }
 
+       i = ((MonoImageLoader*)image->loader)->load_tables (image);
        g_assert (image->heap_guid.data);
        g_assert (image->heap_guid.size >= 16);
 
        image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
 
-       return TRUE;
+       return i;
 }
 
 /*
@@ -519,8 +561,8 @@ load_tables (MonoImage *image)
        return TRUE;
 }
 
-static gboolean
-load_metadata (MonoImage *image, MonoCLIImageInfo *iinfo)
+gboolean
+mono_image_load_metadata (MonoImage *image, MonoCLIImageInfo *iinfo)
 {
        if (!load_metadata_ptrs (image, iinfo))
                return FALSE;
@@ -655,26 +697,26 @@ mono_image_load_module (MonoImage *image, int idx)
 static gpointer
 class_key_extract (gpointer value)
 {
-       MonoClass *class = value;
+       MonoClass *klass = (MonoClass *)value;
 
-       return GUINT_TO_POINTER (class->type_token);
+       return GUINT_TO_POINTER (klass->type_token);
 }
 
 static gpointer*
 class_next_value (gpointer value)
 {
-       MonoClass *class = value;
+       MonoClass *klass = (MonoClass *)value;
 
-       return (gpointer*)&class->next_class_cache;
+       return (gpointer*)&klass->next_class_cache;
 }
 
 void
 mono_image_init (MonoImage *image)
 {
-       mono_mutex_init_recursive (&image->lock);
-       mono_mutex_init_recursive (&image->szarray_cache_lock);
+       mono_os_mutex_init_recursive (&image->lock);
+       mono_os_mutex_init_recursive (&image->szarray_cache_lock);
 
-       image->mempool = mono_mempool_new_size (512);
+       image->mempool = mono_mempool_new_size (INITIAL_IMAGE_SIZE);
        mono_internal_hash_table_init (&image->class_cache,
                                       g_direct_hash,
                                       class_key_extract,
@@ -840,13 +882,19 @@ do_load_header (MonoImage *image, MonoDotNetHeader *header, int offset)
 
 gboolean
 mono_image_load_pe_data (MonoImage *image)
+{
+       return ((MonoImageLoader*)image->loader)->load_pe_data (image);
+}
+
+static gboolean
+pe_image_load_pe_data (MonoImage *image)
 {
        MonoCLIImageInfo *iinfo;
        MonoDotNetHeader *header;
        MonoMSDOSHeader msdos;
        gint32 offset = 0;
 
-       iinfo = image->image_info;
+       iinfo = (MonoCLIImageInfo *)image->image_info;
        header = &iinfo->cli_header;
 
 #ifdef HOST_WIN32
@@ -905,16 +953,24 @@ invalid_image:
 
 gboolean
 mono_image_load_cli_data (MonoImage *image)
+{
+       return ((MonoImageLoader*)image->loader)->load_cli_data (image);
+}
+
+static gboolean
+pe_image_load_cli_data (MonoImage *image)
 {
        MonoCLIImageInfo *iinfo;
+       MonoDotNetHeader *header;
 
-       iinfo = image->image_info;
+       iinfo = (MonoCLIImageInfo *)image->image_info;
+       header = &iinfo->cli_header;
 
        /* Load the CLI header */
-       if (!load_cli_header (image, iinfo))
+       if (!mono_image_load_cli_header (image, iinfo))
                return FALSE;
 
-       if (!load_metadata (image, iinfo))
+       if (!mono_image_load_metadata (image, iinfo))
                return FALSE;
 
        return TRUE;
@@ -938,6 +994,33 @@ mono_image_load_names (MonoImage *image)
        }
 }
 
+static gboolean
+pe_image_load_tables (MonoImage *image)
+{
+       return TRUE;
+}
+
+static gboolean
+pe_image_match (MonoImage *image)
+{
+       if (image->raw_data [0] == 'M' && image->raw_data [1] == 'Z')
+               return TRUE;
+       return FALSE;
+}
+
+static const MonoImageLoader pe_loader = {
+       pe_image_match,
+       pe_image_load_pe_data,
+       pe_image_load_cli_data,
+       pe_image_load_tables,
+};
+
+static void
+install_pe_loader (void)
+{
+       mono_install_image_loader (&pe_loader);
+}
+
 static MonoImage *
 do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
                    gboolean care_about_cli, gboolean care_about_pecoff)
@@ -945,39 +1028,54 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
        MonoCLIImageInfo *iinfo;
        MonoDotNetHeader *header;
        GSList *errors = NULL;
+       GSList *l;
 
        mono_profiler_module_event (image, MONO_PROFILE_START_LOAD);
 
        mono_image_init (image);
 
-       iinfo = image->image_info;
+       iinfo = (MonoCLIImageInfo *)image->image_info;
        header = &iinfo->cli_header;
-               
-       if (status)
-               *status = MONO_IMAGE_IMAGE_INVALID;
-
-       if (care_about_pecoff == FALSE)
-               goto done;
 
        if (!image->metadata_only) {
-               if (!mono_verifier_verify_pe_data (image, &errors))
+               for (l = image_loaders; l; l = l->next) {
+                       MonoImageLoader *loader = (MonoImageLoader *)l->data;
+                       if (loader->match (image)) {
+                               image->loader = loader;
+                               break;
+                       }
+               }
+               if (!image->loader) {
+                       *status = MONO_IMAGE_IMAGE_INVALID;
+                       goto invalid_image;
+               }
+
+               if (status)
+                       *status = MONO_IMAGE_IMAGE_INVALID;
+
+               if (care_about_pecoff == FALSE)
+                       goto done;
+
+               if (image->loader == &pe_loader && !mono_verifier_verify_pe_data (image, &errors))
                        goto invalid_image;
 
                if (!mono_image_load_pe_data (image))
                        goto invalid_image;
+       } else {
+               image->loader = (MonoImageLoader*)&pe_loader;
        }
 
        if (care_about_cli == FALSE) {
                goto done;
        }
 
-       if (!mono_verifier_verify_cli_data (image, &errors))
+       if (image->loader == &pe_loader && !mono_verifier_verify_cli_data (image, &errors))
                goto invalid_image;
 
        if (!mono_image_load_cli_data (image))
                goto invalid_image;
 
-       if (!mono_verifier_verify_table_data (image, &errors))
+       if (image->loader == &pe_loader && !mono_verifier_verify_table_data (image, &errors))
                goto invalid_image;
 
        mono_image_load_names (image);
@@ -993,7 +1091,7 @@ done:
 
 invalid_image:
        if (errors) {
-               MonoVerifyInfo *info = errors->data;
+               MonoVerifyInfo *info = (MonoVerifyInfo *)errors->data;
                g_warning ("Could not load image %s due to %s", image->name, info->message);
                mono_free_verify_list (errors);
        }
@@ -1029,11 +1127,11 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
        image = g_new0 (MonoImage, 1);
        image->raw_buffer_used = TRUE;
        image->raw_data_len = mono_file_map_size (filed);
-       image->raw_data = mono_file_map (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
+       image->raw_data = (char *)mono_file_map (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
 #if defined(HAVE_MMAP) && !defined (HOST_WIN32)
        if (!image->raw_data) {
                image->fileio_used = TRUE;
-               image->raw_data = mono_file_map_fileio (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
+               image->raw_data = (char *)mono_file_map_fileio (image->raw_data_len, MONO_MMAP_READ|MONO_MMAP_PRIVATE, mono_file_map_fd (filed), 0, &image->raw_data_handle);
        }
 #endif
        if (!image->raw_data) {
@@ -1056,23 +1154,35 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
        return do_mono_image_load (image, status, care_about_cli, care_about_pecoff);
 }
 
+/**
+ * mono_image_loaded:
+ * @name: path or assembly name of the image to load
+ * @refonly: Check with respect to reflection-only loads?
+ *
+ * This routine verifies that the given image is loaded.
+ * It checks either reflection-only loads only, or normal loads only, as specified by parameter.
+ *
+ * Returns: the loaded MonoImage, or NULL on failure.
+ */
 MonoImage *
 mono_image_loaded_full (const char *name, gboolean refonly)
 {
        MonoImage *res;
-       GHashTable *loaded_images = refonly ? loaded_images_refonly_hash : loaded_images_hash;
-        
+
        mono_images_lock ();
-       res = g_hash_table_lookup (loaded_images, name);
+       res = (MonoImage *)g_hash_table_lookup (get_loaded_images_hash (refonly), name);
+       if (!res)
+               res = (MonoImage *)g_hash_table_lookup (get_loaded_images_by_name_hash (refonly), name);
        mono_images_unlock ();
+
        return res;
 }
 
 /**
  * mono_image_loaded:
- * @name: name of the image to load
+ * @name: path or assembly name of the image to load
  *
- * This routine ensures that the given image is loaded.
+ * This routine verifies that the given image is loaded. Reflection-only loads do not count.
  *
  * Returns: the loaded MonoImage, or NULL on failure.
  */
@@ -1090,12 +1200,12 @@ typedef struct {
 static void
 find_by_guid (gpointer key, gpointer val, gpointer user_data)
 {
-       GuidData *data = user_data;
+       GuidData *data = (GuidData *)user_data;
        MonoImage *image;
 
        if (data->res)
                return;
-       image = val;
+       image = (MonoImage *)val;
        if (strcmp (data->guid, mono_image_get_guid (image)) == 0)
                data->res = image;
 }
@@ -1104,7 +1214,7 @@ MonoImage *
 mono_image_loaded_by_guid_full (const char *guid, gboolean refonly)
 {
        GuidData data;
-       GHashTable *loaded_images = refonly ? loaded_images_refonly_hash : loaded_images_hash;
+       GHashTable *loaded_images = get_loaded_images_hash (refonly);
        data.res = NULL;
        data.guid = guid;
 
@@ -1124,10 +1234,10 @@ static MonoImage *
 register_image (MonoImage *image)
 {
        MonoImage *image2;
-       GHashTable *loaded_images = image->ref_only ? loaded_images_refonly_hash : loaded_images_hash;
+       GHashTable *loaded_images = get_loaded_images_hash (image->ref_only);
 
        mono_images_lock ();
-       image2 = g_hash_table_lookup (loaded_images, image->name);
+       image2 = (MonoImage *)g_hash_table_lookup (loaded_images, image->name);
 
        if (image2) {
                /* Somebody else beat us to it */
@@ -1136,9 +1246,11 @@ register_image (MonoImage *image)
                mono_image_close (image);
                return image2;
        }
+
+       GHashTable *loaded_images_by_name = get_loaded_images_by_name_hash (image->ref_only);
        g_hash_table_insert (loaded_images, image->name, image);
-       if (image->assembly_name && (g_hash_table_lookup (loaded_images, image->assembly_name) == NULL))
-               g_hash_table_insert (loaded_images, (char *) image->assembly_name, image);      
+       if (image->assembly_name && (g_hash_table_lookup (loaded_images_by_name, image->assembly_name) == NULL))
+               g_hash_table_insert (loaded_images_by_name, (char *) image->assembly_name, image);
        mono_images_unlock ();
 
        return image;
@@ -1158,7 +1270,7 @@ mono_image_open_from_data_internal (char *data, guint32 data_len, gboolean need_
        }
        datac = data;
        if (need_copy) {
-               datac = g_try_malloc (data_len);
+               datac = (char *)g_try_malloc (data_len);
                if (!datac) {
                        if (status)
                                *status = MONO_IMAGE_ERROR_ERRNO;
@@ -1231,13 +1343,14 @@ MonoImage *
 mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean refonly)
 {
        MonoImage *image;
-       GHashTable *loaded_images;
+       GHashTable *loaded_images = get_loaded_images_hash (refonly);
        char *absfname;
        
        g_return_val_if_fail (fname != NULL, NULL);
        
 #ifdef HOST_WIN32
-       /* Load modules using LoadLibrary. */
+       // Win32 path: If we are running with mixed-mode assemblies enabled (ie have loaded mscoree.dll),
+       // then assemblies need to be loaded with LoadLibrary:
        if (!refonly && coree_module_handle) {
                HMODULE module_handle;
                guint16 *fname_utf16;
@@ -1248,8 +1361,8 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r
 
                /* There is little overhead because the OS loader lock is held by LoadLibrary. */
                mono_images_lock ();
-               image = g_hash_table_lookup (loaded_images_hash, absfname);
-               if (image) {
+               image = g_hash_table_lookup (loaded_images, absfname);
+               if (image) { // Image already loaded
                        g_assert (image->is_module_handle);
                        if (image->has_entry_point && image->ref_count == 0) {
                                /* Increment reference count on images loaded outside of the runtime. */
@@ -1266,13 +1379,14 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r
                        return image;
                }
 
+               // Image not loaded, load it now
                fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL);
                module_handle = MonoLoadImage (fname_utf16);
                if (status && module_handle == NULL)
                        last_error = GetLastError ();
 
                /* mono_image_open_from_module_handle is called by _CorDllMain. */
-               image = g_hash_table_lookup (loaded_images_hash, absfname);
+               image = g_hash_table_lookup (loaded_images, absfname);
                if (image)
                        mono_image_addref (image);
                mono_images_unlock ();
@@ -1315,17 +1429,17 @@ mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean r
         * the same image, we discard all but the first copy.
         */
        mono_images_lock ();
-       loaded_images = refonly ? loaded_images_refonly_hash : loaded_images_hash;
-       image = g_hash_table_lookup (loaded_images, absfname);
+       image = (MonoImage *)g_hash_table_lookup (loaded_images, absfname);
        g_free (absfname);
-       
-       if (image){
+
+       if (image) { // Image already loaded
                mono_image_addref (image);
                mono_images_unlock ();
                return image;
        }
        mono_images_unlock ();
 
+       // Image not loaded, load it now
        image = do_mono_image_open (fname, status, TRUE, TRUE, refonly, FALSE);
        if (image == NULL)
                return NULL;
@@ -1537,12 +1651,12 @@ gboolean
 mono_image_close_except_pools (MonoImage *image)
 {
        MonoImage *image2;
-       GHashTable *loaded_images;
+       GHashTable *loaded_images, *loaded_images_by_name;
        int i;
 
        g_return_val_if_fail (image != NULL, FALSE);
 
-       /* 
+       /*
         * Atomically decrement the refcount and remove ourselves from the hash tables, so
         * register_image () can't grab an image which is being closed.
         */
@@ -1553,14 +1667,15 @@ mono_image_close_except_pools (MonoImage *image)
                return FALSE;
        }
 
-       loaded_images = image->ref_only ? loaded_images_refonly_hash : loaded_images_hash;
-       image2 = g_hash_table_lookup (loaded_images, image->name);
+       loaded_images         = get_loaded_images_hash (image->ref_only);
+       loaded_images_by_name = get_loaded_images_by_name_hash (image->ref_only);
+       image2 = (MonoImage *)g_hash_table_lookup (loaded_images, image->name);
        if (image == image2) {
                /* This is not true if we are called from mono_image_open () */
                g_hash_table_remove (loaded_images, image->name);
        }
-       if (image->assembly_name && (g_hash_table_lookup (loaded_images, image->assembly_name) == image))
-               g_hash_table_remove (loaded_images, (char *) image->assembly_name);     
+       if (image->assembly_name && (g_hash_table_lookup (loaded_images_by_name, image->assembly_name) == image))
+               g_hash_table_remove (loaded_images_by_name, (char *) image->assembly_name);     
 
        mono_images_unlock ();
 
@@ -1625,7 +1740,7 @@ mono_image_close_except_pools (MonoImage *image)
        if (image->raw_data_allocated) {
                /* FIXME: do we need this? (image is disposed anyway) */
                /* image->raw_metadata and cli_sections might lie inside image->raw_data */
-               MonoCLIImageInfo *ii = image->image_info;
+               MonoCLIImageInfo *ii = (MonoCLIImageInfo *)image->image_info;
 
                if ((image->raw_metadata > image->raw_data) &&
                        (image->raw_metadata <= (image->raw_data + image->raw_data_len)))
@@ -1714,7 +1829,7 @@ mono_image_close_except_pools (MonoImage *image)
                mono_bitset_free (image->interface_bitset);
        }
        if (image->image_info){
-               MonoCLIImageInfo *ii = image->image_info;
+               MonoCLIImageInfo *ii = (MonoCLIImageInfo *)image->image_info;
 
                if (ii->cli_section_tables)
                        g_free (ii->cli_section_tables);
@@ -1732,8 +1847,8 @@ mono_image_close_except_pools (MonoImage *image)
        if (image->modules_loaded)
                g_free (image->modules_loaded);
 
-       mono_mutex_destroy (&image->szarray_cache_lock);
-       mono_mutex_destroy (&image->lock);
+       mono_os_mutex_destroy (&image->szarray_cache_lock);
+       mono_os_mutex_destroy (&image->lock);
 
        /*g_print ("destroy image %p (dynamic: %d)\n", image, image->dynamic);*/
        if (image_is_dynamic (image)) {
@@ -1934,7 +2049,7 @@ mono_image_lookup_resource (MonoImage *image, guint32 res_id, guint32 lang_id, g
 
        mono_image_ensure_section_idx (image, MONO_SECTION_RSRC);
 
-       info=image->image_info;
+       info = (MonoCLIImageInfo *)image->image_info;
        if(info==NULL) {
                return(NULL);
        }
@@ -2007,7 +2122,7 @@ mono_image_get_entry_point (MonoImage *image)
 const char*
 mono_image_get_resource (MonoImage *image, guint32 offset, guint32 *size)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        MonoCLIHeader *ch = &iinfo->cli_cli_header;
        const char* data;
 
@@ -2097,7 +2212,7 @@ done:
 const char*
 mono_image_get_strong_name (MonoImage *image, guint32 *size)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        MonoPEDirEntry *de = &iinfo->cli_cli_header.ch_strong_name;
        const char* data;
 
@@ -2125,7 +2240,7 @@ mono_image_get_strong_name (MonoImage *image, guint32 *size)
 guint32
 mono_image_strong_name_position (MonoImage *image, guint32 *size)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        MonoPEDirEntry *de = &iinfo->cli_cli_header.ch_strong_name;
        guint32 pos;
 
@@ -2269,7 +2384,7 @@ mono_image_is_dynamic (MonoImage *image)
 gboolean
 mono_image_has_authenticode_entry (MonoImage *image)
 {
-       MonoCLIImageInfo *iinfo = image->image_info;
+       MonoCLIImageInfo *iinfo = (MonoCLIImageInfo *)image->image_info;
        MonoDotNetHeader *header = &iinfo->cli_header;
        MonoPEDirEntry *de = &header->datadir.pe_certificate_table;
        // the Authenticode "pre" (non ASN.1) header is 8 bytes long
@@ -2326,7 +2441,7 @@ g_list_prepend_image (MonoImage *image, GList *list, gpointer data)
 {
        GList *new_list;
        
-       new_list = mono_image_alloc (image, sizeof (GList));
+       new_list = (GList *)mono_image_alloc (image, sizeof (GList));
        new_list->data = data;
        new_list->prev = list ? list->prev : NULL;
     new_list->next = list;
@@ -2344,7 +2459,7 @@ g_slist_append_image (MonoImage *image, GSList *list, gpointer data)
 {
        GSList *new_list;
 
-       new_list = mono_image_alloc (image, sizeof (GSList));
+       new_list = (GSList *)mono_image_alloc (image, sizeof (GSList));
        new_list->data = data;
        new_list->next = NULL;
 
@@ -2354,13 +2469,13 @@ g_slist_append_image (MonoImage *image, GSList *list, gpointer data)
 void
 mono_image_lock (MonoImage *image)
 {
-       mono_locks_acquire (&image->lock, ImageDataLock);
+       mono_locks_os_acquire (&image->lock, ImageDataLock);
 }
 
 void
 mono_image_unlock (MonoImage *image)
 {
-       mono_locks_release (&image->lock, ImageDataLock);
+       mono_locks_os_release (&image->lock, ImageDataLock);
 }
 
 
@@ -2414,11 +2529,50 @@ mono_image_property_remove (MonoImage *image, gpointer subject)
 }
 
 void
-mono_image_append_class_to_reflection_info_set (MonoClass *class)
+mono_image_append_class_to_reflection_info_set (MonoClass *klass)
 {
-       MonoImage *image = class->image;
+       MonoImage *image = klass->image;
        g_assert (image_is_dynamic (image));
        mono_image_lock (image);
-       image->reflection_info_unregister_classes = g_slist_prepend_mempool (image->mempool, image->reflection_info_unregister_classes, class);
+       image->reflection_info_unregister_classes = g_slist_prepend_mempool (image->mempool, image->reflection_info_unregister_classes, klass);
        mono_image_unlock (image);
 }
+
+// This is support for the mempool reference tracking feature in checked-build, but lives in image.c due to use of static variables of this file.
+
+/**
+ * mono_find_image_owner:
+ *
+ * Find the image, if any, which a given pointer is located in the memory of.
+ */
+MonoImage *
+mono_find_image_owner (void *ptr)
+{
+       mono_images_lock ();
+
+       MonoImage *owner = NULL;
+
+       // Iterate over both by-path image hashes
+       const int hash_candidates[] = {IMAGES_HASH_PATH, IMAGES_HASH_PATH_REFONLY};
+       int hash_idx;
+       for (hash_idx = 0; !owner && hash_idx < G_N_ELEMENTS (hash_candidates); hash_idx++)
+       {
+               GHashTable *target = loaded_images_hashes [hash_candidates [hash_idx]];
+               GHashTableIter iter;
+               MonoImage *image;
+
+               // Iterate over images within a hash
+               g_hash_table_iter_init (&iter, target);
+               while (!owner && g_hash_table_iter_next(&iter, NULL, (gpointer *)&image))
+               {
+                       mono_image_lock (image);
+                       if (mono_mempool_contains_addr (image->mempool, ptr))
+                               owner = image;
+                       mono_image_unlock (image);
+               }
+       }
+
+       mono_images_unlock ();
+
+       return owner;
+}