X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fimage.c;h=4fc6f218e1708a0ccc7c676f069f8743ef2f277b;hb=8784e2e1cbbd88b4872536d3a8077702dc547216;hp=7b1b4278315a2eddd8463dd5b6e86039efa3ed65;hpb=f9596050629ebf0d8d24fb256cc08f98d6d2c7e7;p=mono.git diff --git a/mono/metadata/image.c b/mono/metadata/image.c index 7b1b4278315..4fc6f218e17 100644 --- a/mono/metadata/image.c +++ b/mono/metadata/image.c @@ -28,6 +28,7 @@ #include "marshal.h" #include "coree.h" #include +#include #include #include #include @@ -66,18 +67,43 @@ enum { }; static GHashTable *loaded_images_hashes [4] = {NULL, NULL, NULL, NULL}; -static GHashTable *get_loaded_images_hash (gboolean refonly) +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) +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]; } +// Change the assembly set in `image` to the assembly set in `assemblyImage`. Halt if overwriting is attempted. +// Can be used on modules loaded through either the "file" or "module" mechanism +static gboolean +assign_assembly_parent_for_netmodule (MonoImage *image, MonoImage *assemblyImage, MonoError *error) +{ + // Assembly to assign + MonoAssembly *assembly = assemblyImage->assembly; + + while (1) { + // Assembly currently assigned + MonoAssembly *assemblyOld = image->assembly; + if (assemblyOld) { + if (assemblyOld == assembly) + return TRUE; + mono_error_set_bad_image (error, assemblyImage, "Attempted to load module %s which has already been loaded by assembly %s. This is not supported in Mono.", image->name, assemblyOld->image->name); + return FALSE; + } + gpointer result = InterlockedExchangePointer((gpointer *)&image->assembly, assembly); + if (result == assembly) + return TRUE; + } +} + static gboolean debug_assembly_unload = FALSE; #define mono_images_lock() if (mutex_inited) mono_os_mutex_lock (&images_mutex) @@ -632,13 +658,13 @@ load_modules (MonoImage *image) } /** - * mono_image_load_module: + * mono_image_load_module_checked: * * Load the module with the one-based index IDX from IMAGE and return it. Return NULL if - * it cannot be loaded. + * it cannot be loaded. NULL without MonoError being set will be interpreted as "not found". */ MonoImage* -mono_image_load_module (MonoImage *image, int idx) +mono_image_load_module_checked (MonoImage *image, int idx, MonoError *error) { MonoTableInfo *t; MonoTableInfo *file_table; @@ -648,6 +674,8 @@ mono_image_load_module (MonoImage *image, int idx) GList *list_iter, *valid_modules = NULL; MonoImageOpenStatus status; + mono_error_init (error); + if ((image->module_count == 0) || (idx > image->module_count || idx <= 0)) return NULL; if (image->modules_loaded [idx - 1]) @@ -683,10 +711,18 @@ mono_image_load_module (MonoImage *image, int idx) } if (valid) { module_ref = g_build_filename (base_dir, name, NULL); - image->modules [idx - 1] = mono_image_open_full (module_ref, &status, refonly); - if (image->modules [idx - 1]) { - mono_image_addref (image->modules [idx - 1]); - image->modules [idx - 1]->assembly = image->assembly; + MonoImage *moduleImage = mono_image_open_full (module_ref, &status, refonly); + if (moduleImage) { + if (!assign_assembly_parent_for_netmodule (moduleImage, image, error)) { + mono_image_close (moduleImage); + g_free (module_ref); + g_free (base_dir); + g_list_free (valid_modules); + return NULL; + } + + image->modules [idx - 1] = image; + #ifdef HOST_WIN32 if (image->modules [idx - 1]->is_module_handle) mono_image_fixup_vtable (image->modules [idx - 1]); @@ -705,6 +741,15 @@ mono_image_load_module (MonoImage *image, int idx) return image->modules [idx - 1]; } +MonoImage* +mono_image_load_module (MonoImage *image, int idx) +{ + MonoError error; + MonoImage *result = mono_image_load_module_checked (image, idx, &error); + mono_error_assert_ok (&error); + return result; +} + static gpointer class_key_extract (gpointer value) { @@ -716,7 +761,7 @@ class_key_extract (gpointer value) static gpointer* class_next_value (gpointer value) { - MonoClass *klass = (MonoClass *)value; + MonoClassDef *klass = (MonoClassDef *)value; return (gpointer*)&klass->next_class_cache; } @@ -1300,6 +1345,7 @@ mono_image_open_from_data_internal (char *data, guint32 data_len, gboolean need_ image->image_info = iinfo; image->ref_only = refonly; image->metadata_only = metadata_only; + image->ref_count = 1; image = do_mono_image_load (image, status, TRUE, TRUE); if (image == NULL) @@ -1652,6 +1698,17 @@ mono_wrapper_caches_free (MonoWrapperCaches *cache) free_hash (cache->thunk_invoke_cache); } +static void +mono_image_close_except_pools_all (MonoImage**images, int image_count) +{ + for (int i = 0; i < image_count; ++i) { + if (images [i]) { + if (!mono_image_close_except_pools (images [i])) + images [i] = NULL; + } + } +} + /* * Returns whether mono_image_close_finish() must be called as well. * We must unload images in two steps because clearing the domain in @@ -1772,7 +1829,6 @@ mono_image_close_except_pools (MonoImage *image) g_free (image->name); g_free (image->guid); g_free (image->version); - g_free (image->files); } if (image->method_cache) @@ -1801,6 +1857,7 @@ mono_image_close_except_pools (MonoImage *image) free_hash (image->stfld_wrapper_cache); free_hash (image->isinst_cache); free_hash (image->castclass_cache); + free_hash (image->icall_wrapper_cache); free_hash (image->proxy_isinst_cache); free_hash (image->var_cache_slow); free_hash (image->mvar_cache_slow); @@ -1850,12 +1907,8 @@ mono_image_close_except_pools (MonoImage *image) g_free (image->image_info); } - for (i = 0; i < image->module_count; ++i) { - if (image->modules [i]) { - if (!mono_image_close_except_pools (image->modules [i])) - image->modules [i] = NULL; - } - } + mono_image_close_except_pools_all (image->files, image->file_count); + mono_image_close_except_pools_all (image->modules, image->module_count); if (image->modules_loaded) g_free (image->modules_loaded); @@ -1874,6 +1927,17 @@ mono_image_close_except_pools (MonoImage *image) return TRUE; } +static void +mono_image_close_all (MonoImage**images, int image_count) +{ + for (int i = 0; i < image_count; ++i) { + if (images [i]) + mono_image_close_finish (images [i]); + } + if (images) + g_free (images); +} + void mono_image_close_finish (MonoImage *image) { @@ -1889,12 +1953,8 @@ mono_image_close_finish (MonoImage *image) image->references = NULL; } - for (i = 0; i < image->module_count; ++i) { - if (image->modules [i]) - mono_image_close_finish (image->modules [i]); - } - if (image->modules) - g_free (image->modules); + mono_image_close_all (image->files, image->file_count); + mono_image_close_all (image->modules, image->module_count); #ifndef DISABLE_PERFCOUNTERS mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (image->mempool); @@ -1991,13 +2051,13 @@ mono_image_walk_resource_tree (MonoCLIImageInfo *info, guint32 res_id, } #endif } else if (level==2) { - if (is_string == TRUE || (is_string == FALSE && lang_id != 0 && name_offset != lang_id)) + if (is_string || (lang_id != 0 && name_offset != lang_id)) return NULL; } else { g_assert_not_reached (); } - if(is_dir==TRUE) { + if (is_dir) { MonoPEResourceDir *res_dir=(MonoPEResourceDir *)(((char *)root)+dir_offset); MonoPEResourceDirEntry *sub_entries=(MonoPEResourceDirEntry *)(res_dir+1); guint32 entries, i; @@ -2151,8 +2211,9 @@ mono_image_get_resource (MonoImage *image, guint32 offset, guint32 *size) return data; } +// Returning NULL with no error set will be interpeted as "not found" MonoImage* -mono_image_load_file_for_image (MonoImage *image, int fileidx) +mono_image_load_file_for_image_checked (MonoImage *image, int fileidx, MonoError *error) { char *base_dir, *name; MonoImage *res; @@ -2160,6 +2221,8 @@ mono_image_load_file_for_image (MonoImage *image, int fileidx) const char *fname; guint32 fname_id; + mono_error_init (error); + if (fileidx < 1 || fileidx > t->rows) return NULL; @@ -2187,14 +2250,21 @@ mono_image_load_file_for_image (MonoImage *image, int fileidx) } else { int i; /* g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly); */ - res->assembly = image->assembly; + if (!assign_assembly_parent_for_netmodule (res, image, error)) { + mono_image_unlock (image); + mono_image_close (res); + return NULL; + } + for (i = 0; i < res->module_count; ++i) { if (res->modules [i] && !res->modules [i]->assembly) res->modules [i]->assembly = image->assembly; } - if (!image->files) + if (!image->files) { image->files = g_new0 (MonoImage*, t->rows); + image->file_count = t->rows; + } image->files [fileidx - 1] = res; mono_image_unlock (image); /* vtable fixup can't happen with the image lock held */ @@ -2210,6 +2280,15 @@ done: return res; } +MonoImage* +mono_image_load_file_for_image (MonoImage *image, int fileidx) +{ + MonoError error; + MonoImage *result = mono_image_load_file_for_image_checked (image, fileidx, &error); + mono_error_assert_ok (&error); + return result; +} + /** * mono_image_get_strong_name: * @image: a MonoImage @@ -2448,6 +2527,31 @@ mono_image_strdup (MonoImage *image, const char *s) return res; } +char* +mono_image_strdup_vprintf (MonoImage *image, const char *format, va_list args) +{ + char *buf; + mono_image_lock (image); + buf = mono_mempool_strdup_vprintf (image->mempool, format, args); + mono_image_unlock (image); +#ifndef DISABLE_PERFCOUNTERS + mono_perfcounters->loader_bytes += strlen (buf); +#endif + return buf; +} + +char* +mono_image_strdup_printf (MonoImage *image, const char *format, ...) +{ + char *buf; + va_list args; + + va_start (args, format); + buf = mono_image_strdup_vprintf (image, format, args); + va_end (args); + return buf; +} + GList* g_list_prepend_image (MonoImage *image, GList *list, gpointer data) { @@ -2520,6 +2624,7 @@ mono_image_property_lookup (MonoImage *image, gpointer subject, guint32 property void mono_image_property_insert (MonoImage *image, gpointer subject, guint32 property, gpointer value) { + CHECKED_METADATA_STORE_LOCAL (image->mempool, value); mono_image_lock (image); mono_property_hash_insert (image->property_hash, subject, property, value); mono_image_unlock (image);