X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fassembly.c;h=69187a39eee43cdad5389575dbc8c619bc5fbbc7;hb=e152071d2a0061d7aa6d7f40b220b78f43132aa2;hp=5c466be5acccceb67a51542fc193dfc3c5a6878a;hpb=4adfaadd1dd400feb7b5175fd954bf12879ff16a;p=mono.git diff --git a/mono/metadata/assembly.c b/mono/metadata/assembly.c index 5c466be5acc..69187a39eee 100644 --- a/mono/metadata/assembly.c +++ b/mono/metadata/assembly.c @@ -4,8 +4,8 @@ * Author: * Miguel de Icaza (miguel@ximian.com) * - * (C) 2001 Ximian, Inc. http://www.ximian.com - * + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) */ #include #include @@ -15,7 +15,6 @@ #include #include "assembly.h" #include "image.h" -#include "rawbuffer.h" #include "object-internals.h" #include #include @@ -29,16 +28,21 @@ #include #include #include -#include +#include +#include #include #include -#ifndef PLATFORM_WIN32 +#ifndef HOST_WIN32 #include #include #include #endif +#ifdef PLATFORM_MACOSX +#include +#endif + /* AssemblyVersionMap: an assembly name and the assembly version set on which it is based */ typedef struct { const char* assembly_name; @@ -58,6 +62,7 @@ static char **assemblies_path = NULL; /* Contains the list of directories that point to auxiliary GACs */ static char **extra_gac_paths = NULL; +#ifndef DISABLE_ASSEMBLY_REMAPPING /* The list of system assemblies what will be remapped to the running * runtime version. WARNING: this list must be sorted. */ @@ -88,8 +93,12 @@ static const AssemblyVersionMap framework_assemblies [] = { {"Npgsql", 0}, {"PEAPI", 0}, {"System", 0}, + {"System.ComponentModel.DataAnnotations", 2}, + {"System.Configuration", 0}, {"System.Configuration.Install", 0}, + {"System.Core", 2}, {"System.Data", 0}, + {"System.Data.Linq", 2}, {"System.Data.OracleClient", 0}, {"System.Data.SqlXml", 0}, {"System.Design", 0}, @@ -104,12 +113,15 @@ static const AssemblyVersionMap framework_assemblies [] = { {"System.Security", 0}, {"System.ServiceProcess", 0}, {"System.Web", 0}, + {"System.Web.Abstractions", 2}, {"System.Web.Mobile", 0}, + {"System.Web.Routing", 2}, {"System.Web.Services", 0}, {"System.Windows.Forms", 0}, {"System.Xml", 0}, {"mscorlib", 0} }; +#endif /* * keeps track of loaded assemblies @@ -117,6 +129,27 @@ static const AssemblyVersionMap framework_assemblies [] = { static GList *loaded_assemblies = NULL; static MonoAssembly *corlib; +#if defined(__native_client__) + +/* On Native Client, allow mscorlib to be loaded from memory */ +/* instead of loaded off disk. If these are not set, default */ +/* mscorlib loading will take place */ + +/* NOTE: If mscorlib data is passed to mono in this way then */ +/* it needs to remain allocated during the use of mono. */ + +static void *corlibData = NULL; +static size_t corlibSize = 0; + +void +mono_set_corlib_data (void *data, size_t size) +{ + corlibData = data; + corlibSize = size; +} + +#endif + /* This protects loaded_assemblies and image->references */ #define mono_assemblies_lock() EnterCriticalSection (&assemblies_mutex) #define mono_assemblies_unlock() LeaveCriticalSection (&assemblies_mutex) @@ -130,6 +163,8 @@ static GSList *loaded_assembly_bindings = NULL; static MonoAssembly* mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, gboolean refonly, gboolean postload); +static MonoBoolean +mono_assembly_is_in_gac (const gchar *filanem); static gchar* encode_public_tok (const guchar *token, gint32 len) @@ -158,7 +193,7 @@ encode_public_tok (const guchar *token, gint32 len) gboolean mono_public_tokens_are_equal (const unsigned char *pubt1, const unsigned char *pubt2) { - return g_strcasecmp ((char*)pubt1, (char*)pubt2) == 0; + return memcmp (pubt1, pubt2, 16) == 0; } static void @@ -185,6 +220,7 @@ check_path_env (void) if (g_getenv ("MONO_DEBUG") == NULL) return; + splitted = assemblies_path; while (*splitted) { if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) g_warning ("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *splitted); @@ -218,7 +254,7 @@ check_extra_gac_path_env (void) { while (*splitted) { if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR)) - g_warning ("'%s' in MONO_GAC_PATH doesn't exist or has wrong permissions.", *splitted); + g_warning ("'%s' in MONO_GAC_PREFIX doesn't exist or has wrong permissions.", *splitted); splitted++; } @@ -227,16 +263,19 @@ check_extra_gac_path_env (void) { static gboolean assembly_binding_maps_name (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) { + if (!info || !info->name) + return FALSE; + if (strcmp (info->name, aname->name)) return FALSE; if (info->major != aname->major || info->minor != aname->minor) return FALSE; - if ((info->culture != NULL) != (aname->culture != NULL)) + if ((info->culture != NULL && info->culture [0]) != (aname->culture != NULL && aname->culture [0])) return FALSE; - if (info->culture && strcmp (info->culture, aname->culture)) + if (info->culture && aname->culture && strcmp (info->culture, aname->culture)) return FALSE; if (!mono_public_tokens_are_equal (info->public_key_token, aname->public_key_token)) @@ -248,6 +287,9 @@ assembly_binding_maps_name (MonoAssemblyBindingInfo *info, MonoAssemblyName *ana static void mono_assembly_binding_info_free (MonoAssemblyBindingInfo *info) { + if (!info) + return; + g_free (info->name); g_free (info->culture); } @@ -478,12 +520,12 @@ mono_set_dirs (const char *assembly_dir, const char *config_dir) mono_set_config_dir (config_dir); } -#ifndef PLATFORM_WIN32 +#ifndef HOST_WIN32 static char * compute_base (char *path) { - char *p = rindex (path, '/'); + char *p = strrchr (path, '/'); if (p == NULL) return NULL; @@ -492,7 +534,7 @@ compute_base (char *path) return NULL; *p = 0; - p = rindex (path, '/'); + p = strrchr (path, '/'); if (p == NULL) return NULL; @@ -537,7 +579,7 @@ set_dirs (char *exe) g_free (mono); } -#endif /* PLATFORM_WIN32 */ +#endif /* HOST_WIN32 */ /** * mono_set_rootdir: @@ -548,22 +590,59 @@ set_dirs (char *exe) void mono_set_rootdir (void) { -#ifdef PLATFORM_WIN32 - gchar *bindir, *installdir, *root, *name, *config; +#if defined(HOST_WIN32) || (defined(PLATFORM_MACOSX) && !defined(TARGET_ARM)) + gchar *bindir, *installdir, *root, *name, *resolvedname, *config; +#ifdef HOST_WIN32 name = mono_get_module_file_name ((HMODULE) &__ImageBase); - bindir = g_path_get_dirname (name); +#else + { + /* + * _NSGetExecutablePath may return -1 to indicate buf is not large + * enough, but we ignore that case to avoid having to do extra dynamic + * allocation for the path and hope that 4096 is enough - this is + * ok in the Linux/Solaris case below at least... + */ + + gchar buf[4096]; + guint buf_size = sizeof (buf); + + if (_NSGetExecutablePath (buf, &buf_size) == 0) + name = g_strdup (buf); + + if (name == NULL) { + fallback (); + return; + } + + name = mono_path_resolve_symlinks (name); + } +#endif + + resolvedname = mono_path_resolve_symlinks (name); + + bindir = g_path_get_dirname (resolvedname); installdir = g_path_get_dirname (bindir); root = g_build_path (G_DIR_SEPARATOR_S, installdir, "lib", NULL); config = g_build_filename (root, "..", "etc", NULL); +#ifdef HOST_WIN32 mono_set_dirs (root, config); +#else + if (g_file_test (root, G_FILE_TEST_EXISTS) && g_file_test (config, G_FILE_TEST_EXISTS)) + mono_set_dirs (root, config); + else + fallback (); +#endif g_free (config); g_free (root); g_free (installdir); g_free (bindir); g_free (name); + g_free (resolvedname); +#elif defined(DISABLE_MONO_AUTODETECTION) + fallback (); #else char buf [4096]; int s; @@ -677,9 +756,11 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname) char* mono_stringify_assembly_name (MonoAssemblyName *aname) { + const char *quote = (aname->name && g_ascii_isspace (aname->name [0])) ? "\"" : ""; + return g_strdup_printf ( - "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", - aname->name, + "%s%s%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s", + quote, aname->name, quote, aname->major, aname->minor, aname->build, aname->revision, aname->culture && *aname->culture? aname->culture: "neutral", aname->public_key_token [0] ? (char *)aname->public_key_token : "null", @@ -718,6 +799,7 @@ mono_assembly_addref (MonoAssembly *assembly) InterlockedIncrement (&assembly->ref_count); } +#ifndef DISABLE_ASSEMBLY_REMAPPING static MonoAssemblyName * mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname) { @@ -766,6 +848,7 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana } return aname; } +#endif /* * mono_assembly_get_assemblyref: @@ -848,7 +931,7 @@ mono_assembly_load_reference (MonoImage *image, int index) reference = mono_assembly_load (&aname, image->assembly? image->assembly->basedir: NULL, &status); if (reference == NULL){ - char *extra_msg = g_strdup (""); + char *extra_msg; if (status == MONO_IMAGE_ERROR_ERRNO && errno == ENOENT) { extra_msg = g_strdup_printf ("The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (%s).\n", image->assembly != NULL ? image->assembly->basedir : "" ); @@ -858,9 +941,11 @@ mono_assembly_load_reference (MonoImage *image, int index) extra_msg = g_strdup ("Cannot find an assembly referenced from this one.\n"); } else if (status == MONO_IMAGE_IMAGE_INVALID) { extra_msg = g_strdup ("The file exists but is not a valid assembly.\n"); + } else { + extra_msg = g_strdup (""); } - g_warning ("The following assembly referenced from %s could not be loaded:\n" + mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY, "The following assembly referenced from %s could not be loaded:\n" " Assembly: %s (assemblyref_index=%d)\n" " Version: %d.%d.%d.%d\n" " Public Key: %s\n%s", @@ -880,7 +965,7 @@ mono_assembly_load_reference (MonoImage *image, int index) if (reference != REFERENCE_MISSING){ mono_assembly_addref (reference); if (image->assembly) - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Ref addref %s %p -> %s %p: %d\n", + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Ref addref %s %p -> %s %p: %d", image->assembly->aname.name, image->assembly, reference->aname.name, reference, reference->ref_count); } else { if (image->assembly) @@ -1129,8 +1214,12 @@ absolute_dir (const gchar *filename) gchar *res; gint i; - if (g_path_is_absolute (filename)) - return g_path_get_dirname (filename); + if (g_path_is_absolute (filename)) { + part = g_path_get_dirname (filename); + res = g_strconcat (part, G_DIR_SEPARATOR_S, NULL); + g_free (part); + return res; + } cwd = g_get_current_dir (); mixed = g_build_filename (cwd, filename, NULL); @@ -1202,7 +1291,7 @@ mono_assembly_open_from_bundle (const char *filename, MonoImageOpenStatus *statu mono_assemblies_lock (); for (i = 0; !image && bundles [i]; ++i) { if (strcmp (bundles [i]->name, name) == 0) { - image = mono_image_open_from_data_full ((char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly); + image = mono_image_open_from_data_with_name ((char*)bundles [i]->data, bundles [i]->size, FALSE, status, refonly, name); break; } } @@ -1261,7 +1350,10 @@ mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboo mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Assembly Loader probing location: '%s'.", fname); - new_fname = mono_make_shadow_copy (fname); + + new_fname = NULL; + if (!mono_assembly_is_in_gac (fname)) + new_fname = mono_make_shadow_copy (fname); if (new_fname && new_fname != fname) { g_free (fname); fname = new_fname; @@ -1274,11 +1366,8 @@ mono_assembly_open_full (const char *filename, MonoImageOpenStatus *status, gboo if (bundles != NULL) image = mono_assembly_open_from_bundle (fname, status, refonly); - if (!image) { - mono_assemblies_lock (); + if (!image) image = mono_image_open_full (fname, status, refonly); - mono_assemblies_unlock (); - } if (!image){ if (*status == MONO_IMAGE_OK) @@ -1433,7 +1522,7 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname, return NULL; } -#if defined (PLATFORM_WIN32) +#if defined (HOST_WIN32) { gchar *tmp_fn; int i; @@ -1475,7 +1564,7 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname, /* Add a non-temporary reference because of ass->image */ mono_image_addref (image); - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image addref %s %p -> %s %p: %d\n", ass->aname.name, ass, image->name, image, image->ref_count); + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image addref %s %p -> %s %p: %d", ass->aname.name, ass, image->name, image, image->ref_count); /* * The load hooks might take locks so we can't call them while holding the @@ -1513,7 +1602,7 @@ mono_assembly_load_from_full (MonoImage *image, const char*fname, loaded_assemblies = g_list_prepend (loaded_assemblies, ass); mono_assemblies_unlock (); -#ifdef PLATFORM_WIN32 +#ifdef HOST_WIN32 if (image->is_module_handle) mono_image_fixup_vtable (image); #endif @@ -1602,6 +1691,10 @@ parse_public_key (const gchar *key, gchar** pubkey) bitlen = read32 (header + 12) >> 3; if ((bitlen + 16 + 4) != pkeylen) return FALSE; + + /* parsing is OK and the public key itself is not requested back */ + if (!pubkey) + return TRUE; /* Encode the size of the blob */ offset = 0; @@ -1618,8 +1711,8 @@ parse_public_key (const gchar *key, gchar** pubkey) arr [i] = g_ascii_xdigit_value (key [j++]) << 4; arr [i] |= g_ascii_xdigit_value (key [j++]); } - if (pubkey) - *pubkey = arr; + + *pubkey = arr; return TRUE; } @@ -1845,6 +1938,57 @@ mono_assembly_name_parse (const char *name, MonoAssemblyName *aname) return mono_assembly_name_parse_full (name, aname, FALSE, NULL, NULL); } +/** + * mono_assembly_name_new: + * @name: name to parse + * + * Allocate a new MonoAssemblyName and fill its values from the + * passed @name. + * + * Returns: a newly allocated structure or NULL if there was any failure. + */ +MonoAssemblyName* +mono_assembly_name_new (const char *name) +{ + MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1); + if (mono_assembly_name_parse (name, aname)) + return aname; + g_free (aname); + return NULL; +} + +const char* +mono_assembly_name_get_name (MonoAssemblyName *aname) +{ + return aname->name; +} + +const char* +mono_assembly_name_get_culture (MonoAssemblyName *aname) +{ + return aname->culture; +} + +mono_byte* +mono_assembly_name_get_pubkeytoken (MonoAssemblyName *aname) +{ + if (aname->public_key_token [0]) + return aname->public_key_token; + return NULL; +} + +uint16_t +mono_assembly_name_get_version (MonoAssemblyName *aname, uint16_t *minor, uint16_t *build, uint16_t *revision) +{ + if (minor) + *minor = aname->minor; + if (build) + *build = aname->build; + if (revision) + *revision = aname->revision; + return aname->major; +} + static MonoAssembly* probe_for_partial_name (const char *basepath, const char *fullname, MonoAssemblyName *aname, MonoImageOpenStatus *status) { @@ -1920,7 +2064,10 @@ MonoAssembly* mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status) { MonoAssembly *res; - MonoAssemblyName *aname, base_name, maped_aname; + MonoAssemblyName *aname, base_name; +#ifndef DISABLE_ASSEMBLY_REMAPPING + MonoAssemblyName maped_aname; +#endif gchar *fullname, *gacpath; gchar **paths; @@ -1930,12 +2077,14 @@ mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *sta if (!mono_assembly_name_parse (name, aname)) return NULL; +#ifndef DISABLE_ASSEMBLY_REMAPPING /* * If no specific version has been requested, make sure we load the * correct version for system assemblies. */ if ((aname->major | aname->minor | aname->build | aname->revision) == 0) aname = mono_assembly_remap_version (aname, &maped_aname); +#endif res = mono_assembly_loaded (aname); if (res) { @@ -1988,6 +2137,67 @@ mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *sta return res; } +static MonoBoolean +mono_assembly_is_in_gac (const gchar *filename) +{ + const gchar *rootdir; + gchar *gp; + gchar **paths; + + if (filename == NULL) + return FALSE; + + for (paths = extra_gac_paths; paths && *paths; paths++) { + if (strstr (*paths, filename) != *paths) + continue; + + gp = (gchar *) (filename + strlen (*paths)); + if (*gp != G_DIR_SEPARATOR) + continue; + gp++; + if (strncmp (gp, "lib", 3)) + continue; + gp += 3; + if (*gp != G_DIR_SEPARATOR) + continue; + gp++; + if (strncmp (gp, "mono", 4)) + continue; + gp += 4; + if (*gp != G_DIR_SEPARATOR) + continue; + gp++; + if (strncmp (gp, "gac", 3)) + continue; + gp += 3; + if (*gp != G_DIR_SEPARATOR) + continue; + + return TRUE; + } + + rootdir = mono_assembly_getrootdir (); + if (strstr (filename, rootdir) != filename) + return FALSE; + + gp = (gchar *) (filename + strlen (rootdir)); + if (*gp != G_DIR_SEPARATOR) + return FALSE; + gp++; + if (strncmp (gp, "mono", 4)) + return FALSE; + gp += 4; + if (*gp != G_DIR_SEPARATOR) + return FALSE; + gp++; + if (strncmp (gp, "gac", 3)) + return FALSE; + gp += 3; + if (*gp != G_DIR_SEPARATOR) + return FALSE; + return TRUE; +} + static MonoImage* mono_assembly_load_publisher_policy (MonoAssemblyName *aname) { @@ -2003,10 +2213,9 @@ mono_assembly_load_publisher_policy (MonoAssemblyName *aname) } else name = g_strdup (aname->name); - if (aname->culture) { - culture = g_strdup (aname->culture); - g_strdown (culture); - } else + if (aname->culture) + culture = g_utf8_strdown (aname->culture, -1); + else culture = g_strdup (""); pname = g_strdup_printf ("policy.%d.%d.%s", aname->major, aname->minor, name); @@ -2073,17 +2282,135 @@ search_binding_loaded (MonoAssemblyName *aname) return NULL; } +static inline gboolean +info_compare_versions (AssemblyVersionSet *left, AssemblyVersionSet *right) +{ + if (left->major != right->major || left->minor != right->minor || + left->build != right->build || left->revision != right->revision) + return FALSE; + + return TRUE; +} + +static inline gboolean +info_versions_equal (MonoAssemblyBindingInfo *left, MonoAssemblyBindingInfo *right) +{ + if (left->has_old_version_bottom != right->has_old_version_bottom) + return FALSE; + + if (left->has_old_version_top != right->has_old_version_top) + return FALSE; + + if (left->has_new_version != right->has_new_version) + return FALSE; + + if (left->has_old_version_bottom && !info_compare_versions (&left->old_version_bottom, &right->old_version_bottom)) + return FALSE; + + if (left->has_old_version_top && !info_compare_versions (&left->old_version_top, &right->old_version_top)) + return FALSE; + + if (left->has_new_version && !info_compare_versions (&left->new_version, &right->new_version)) + return FALSE; + + return TRUE; +} + +/* LOCKING: assumes all the necessary locks are held */ +static void +assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data) +{ + MonoAssemblyBindingInfo *info_copy; + GSList *tmp; + MonoAssemblyBindingInfo *info_tmp; + MonoDomain *domain = (MonoDomain*)user_data; + + if (!domain) + return; + + for (tmp = domain->assembly_bindings; tmp; tmp = tmp->next) { + info_tmp = tmp->data; + if (strcmp (info->name, info_tmp->name) == 0 && info_versions_equal (info, info_tmp)) + return; + } + + info_copy = mono_mempool_alloc0 (domain->mp, sizeof (MonoAssemblyBindingInfo)); + memcpy (info_copy, info, sizeof (MonoAssemblyBindingInfo)); + if (info->name) + info_copy->name = mono_mempool_strdup (domain->mp, info->name); + if (info->culture) + info_copy->culture = mono_mempool_strdup (domain->mp, info->culture); + + domain->assembly_bindings = g_slist_append_mempool (domain->mp, domain->assembly_bindings, info_copy); +} + +static inline gboolean +info_major_minor_in_range (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname) +{ + if (!info->has_old_version_bottom) + return FALSE; + + if (info->old_version_bottom.major > aname->major || info->old_version_bottom.minor > aname->minor) + return FALSE; + + if (info->has_old_version_top && (info->old_version_top.major < aname->major || info->old_version_top.minor < aname->minor)) + return FALSE; + + /* This is not the nicest way to do it, but it's a by-product of the way parsing is done */ + info->major = aname->major; + info->minor = aname->minor; + + return TRUE; +} + +/* LOCKING: Assumes that we are already locked - both loader and domain locks */ +static MonoAssemblyBindingInfo* +get_per_domain_assembly_binding_info (MonoDomain *domain, MonoAssemblyName *aname) +{ + MonoAssemblyBindingInfo *info; + GSList *list; + + if (!domain->assembly_bindings) + return NULL; + + info = NULL; + for (list = domain->assembly_bindings; list; list = list->next) { + info = list->data; + if (info && !strcmp (aname->name, info->name) && info_major_minor_in_range (info, aname)) + break; + info = NULL; + } + + if (info) { + if (info->name && info->public_key_token [0] && info->has_old_version_bottom && + info->has_new_version && assembly_binding_maps_name (info, aname)) + info->is_valid = TRUE; + else + info->is_valid = FALSE; + } + + return info; +} + static MonoAssemblyName* mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_name) { MonoAssemblyBindingInfo *info, *info2; MonoImage *ppimage; + MonoDomain *domain; if (aname->public_key_token [0] == 0) return aname; + domain = mono_domain_get (); mono_loader_lock (); info = search_binding_loaded (aname); + if (!info) { + mono_domain_lock (domain); + info = get_per_domain_assembly_binding_info (domain, aname); + mono_domain_unlock (domain); + } + mono_loader_unlock (); if (info) { if (!check_policy_versions (info, aname)) @@ -2093,14 +2420,36 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam return dest_name; } - info = g_new0 (MonoAssemblyBindingInfo, 1); - info->major = aname->major; - info->minor = aname->minor; - - ppimage = mono_assembly_load_publisher_policy (aname); - if (ppimage) { - get_publisher_policy_info (ppimage, aname, info); - mono_image_close (ppimage); + if (domain && domain->setup && domain->setup->configuration_file) { + mono_domain_lock (domain); + if (!domain->assembly_bindings_parsed) { + gchar *domain_config_file = mono_string_to_utf8 (domain->setup->configuration_file); + + mono_config_parse_assembly_bindings (domain_config_file, aname->major, aname->minor, domain, assembly_binding_info_parsed); + domain->assembly_bindings_parsed = TRUE; + g_free (domain_config_file); + } + mono_domain_unlock (domain); + + mono_loader_lock (); + mono_domain_lock (domain); + info = get_per_domain_assembly_binding_info (domain, aname); + mono_domain_unlock (domain); + mono_loader_unlock (); + } + + if (!info) { + info = g_new0 (MonoAssemblyBindingInfo, 1); + info->major = aname->major; + info->minor = aname->minor; + } + + if (!info->is_valid) { + ppimage = mono_assembly_load_publisher_policy (aname); + if (ppimage) { + get_publisher_policy_info (ppimage, aname, info); + mono_image_close (ppimage); + } } /* Define default error value if needed */ @@ -2158,8 +2507,7 @@ mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImag } if (aname->culture) { - culture = g_strdup (aname->culture); - g_strdown (culture); + culture = g_utf8_strdown (aname->culture, -1); } else { culture = g_strdup (""); } @@ -2204,17 +2552,39 @@ mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImag return result; } - MonoAssembly* mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *status) { char *corlib_file; + MonoAssemblyName *aname; if (corlib) { /* g_print ("corlib already loaded\n"); */ return corlib; } - + +#if defined(__native_client__) + if (corlibData != NULL && corlibSize != 0) { + int status = 0; + /* First "FALSE" instructs mono not to make a copy. */ + /* Second "FALSE" says this is not just a ref. */ + MonoImage* image = mono_image_open_from_data_full (corlibData, corlibSize, FALSE, &status, FALSE); + if (image == NULL || status != 0) + g_print("mono_image_open_from_data_full failed: %d\n", status); + corlib = mono_assembly_load_from_full (image, "mscorlib", &status, FALSE); + if (corlib == NULL || status != 0) + g_print ("mono_assembly_load_from_full failed: %d\n", status); + if (corlib) + return corlib; + } +#endif + + aname = mono_assembly_name_new ("mscorlib.dll"); + corlib = invoke_assembly_preload_hook (aname, assemblies_path); + mono_assembly_name_free (aname); + if (corlib != NULL) + return corlib; + if (assemblies_path) { corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE); if (corlib) @@ -2245,12 +2615,17 @@ mono_assembly_load_full_nosearch (MonoAssemblyName *aname, { MonoAssembly *result; char *fullpath, *filename; - MonoAssemblyName maped_aname, maped_name_pp; +#ifndef DISABLE_ASSEMBLY_REMAPPING + MonoAssemblyName maped_aname; +#endif + MonoAssemblyName maped_name_pp; int ext_index; const char *ext; int len; +#ifndef DISABLE_ASSEMBLY_REMAPPING aname = mono_assembly_remap_version (aname, &maped_aname); +#endif /* Reflection only assemblies don't get assembly binding */ if (!refonly) @@ -2361,9 +2736,11 @@ MonoAssembly* mono_assembly_loaded_full (MonoAssemblyName *aname, gboolean refonly) { MonoAssembly *res; +#ifndef DISABLE_ASSEMBLY_REMAPPING MonoAssemblyName maped_aname; aname = mono_assembly_remap_version (aname, &maped_aname); +#endif res = mono_assembly_invoke_search_hook_internal (aname, refonly, FALSE); @@ -2383,25 +2760,23 @@ mono_assembly_loaded (MonoAssemblyName *aname) return mono_assembly_loaded_full (aname, FALSE); } -/** - * mono_assembly_close: - * @assembly: the assembly to release. - * - * This method releases a reference to the @assembly. The assembly is - * only released when all the outstanding references to it are released. +/* + * Returns whether mono_assembly_close_finish() must be called as + * well. See comment for mono_image_close_except_pools() for why we + * unload in two steps. */ -void -mono_assembly_close (MonoAssembly *assembly) +gboolean +mono_assembly_close_except_image_pools (MonoAssembly *assembly) { GSList *tmp; - g_return_if_fail (assembly != NULL); + g_return_val_if_fail (assembly != NULL, FALSE); if (assembly == REFERENCE_MISSING) - return; - + return FALSE; + /* Might be 0 already */ if (InterlockedDecrement (&assembly->ref_count) > 0) - return; + return FALSE; mono_profiler_assembly_event (assembly, MONO_PROFILE_START_UNLOAD); @@ -2415,7 +2790,8 @@ mono_assembly_close (MonoAssembly *assembly) assembly->image->assembly = NULL; - mono_image_close (assembly->image); + if (!mono_image_close_except_pools (assembly->image)) + assembly->image = NULL; for (tmp = assembly->friend_assembly_names; tmp; tmp = tmp->next) { MonoAssemblyName *fname = tmp->data; @@ -2424,13 +2800,39 @@ mono_assembly_close (MonoAssembly *assembly) } g_slist_free (assembly->friend_assembly_names); g_free (assembly->basedir); + + mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD); + + return TRUE; +} + +void +mono_assembly_close_finish (MonoAssembly *assembly) +{ + g_assert (assembly && assembly != REFERENCE_MISSING); + + if (assembly->image) + mono_image_close_finish (assembly->image); + if (assembly->dynamic) { g_free ((char*)assembly->aname.culture); } else { g_free (assembly); } +} - mono_profiler_assembly_event (assembly, MONO_PROFILE_END_UNLOAD); +/** + * mono_assembly_close: + * @assembly: the assembly to release. + * + * This method releases a reference to the @assembly. The assembly is + * only released when all the outstanding references to it are released. + */ +void +mono_assembly_close (MonoAssembly *assembly) +{ + if (mono_assembly_close_except_image_pools (assembly)) + mono_assembly_close_finish (assembly); } MonoImage* @@ -2523,10 +2925,12 @@ mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies) bundles = assemblies; } +#define MONO_DECLSEC_FORMAT_10 0x3C #define MONO_DECLSEC_FORMAT_20 0x2E #define MONO_DECLSEC_FIELD 0x53 #define MONO_DECLSEC_PROPERTY 0x54 +#define SKIP_VISIBILITY_XML_ATTRIBUTE ("\"SkipVerification\"") #define SKIP_VISIBILITY_ATTRIBUTE_NAME ("System.Security.Permissions.SecurityPermissionAttribute") #define SKIP_VISIBILITY_ATTRIBUTE_SIZE (sizeof (SKIP_VISIBILITY_ATTRIBUTE_NAME) - 1) #define SKIP_VISIBILITY_PROPERTY_NAME ("SkipVerification") @@ -2569,6 +2973,16 @@ mono_assembly_try_decode_skip_verification (const char *p, const char *endn) { int i, j, num, len, params_len; + if (*p == MONO_DECLSEC_FORMAT_10) { + gsize read, written; + char *res = g_convert (p, endn - p, "UTF-8", "UTF-16LE", &read, &written, NULL); + if (res) { + gboolean found = strstr (res, SKIP_VISIBILITY_XML_ATTRIBUTE) != NULL; + g_free (res); + return found; + } + return FALSE; + } if (*p++ != MONO_DECLSEC_FORMAT_20) return FALSE;