Merge remote branch 'upstream/master'
[mono.git] / mono / metadata / assembly.c
index 4bb632cbb90be7dfb752e477a0684ea0cdf2f429..482762d0e1a213d9a113743cd28905e159aa3aa4 100644 (file)
@@ -29,6 +29,7 @@
 #include <mono/metadata/mono-config.h>
 #include <mono/utils/mono-digest.h>
 #include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-path.h>
 #include <mono/metadata/reflection.h>
 #include <mono/metadata/coree.h>
 
@@ -61,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.
  */
@@ -110,9 +112,9 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"System.Runtime.Serialization.Formatters.Soap", 0},
        {"System.Security", 0},
        {"System.ServiceProcess", 0},
+       {"System.Transactions", 2},
        {"System.Web", 0},
        {"System.Web.Abstractions", 2},
-       {"System.Web.Extensions", 2},
        {"System.Web.Mobile", 0},
        {"System.Web.Routing", 2},
        {"System.Web.Services", 0},
@@ -120,6 +122,7 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"System.Xml", 0},
        {"mscorlib", 0}
 };
+#endif
 
 /*
  * keeps track of loaded assemblies
@@ -194,13 +197,23 @@ mono_public_tokens_are_equal (const unsigned char *pubt1, const unsigned char *p
        return memcmp (pubt1, pubt2, 16) == 0;
 }
 
+/* Native Client can't get this info from an environment variable so */
+/* it's passed in to the runtime, or set manually by embedding code. */
+#ifdef __native_client__
+char* nacl_mono_path = NULL;
+#endif
+
 static void
 check_path_env (void)
 {
        const char *path;
        char **splitted, **dest;
        
+#ifdef __native_client__
+       path = nacl_mono_path;
+#else
        path = g_getenv ("MONO_PATH");
+#endif
        if (!path)
                return;
 
@@ -565,7 +578,7 @@ set_dirs (char *exe)
 
        config = g_build_filename (base, "etc", NULL);
        lib = g_build_filename (base, "lib", NULL);
-       mono = g_build_filename (lib, "mono/1.0", NULL);
+       mono = g_build_filename (lib, "mono/2.0", NULL);
        if (stat (mono, &buf) == -1)
                fallback ();
        else {
@@ -589,7 +602,7 @@ void
 mono_set_rootdir (void)
 {
 #if defined(HOST_WIN32) || (defined(PLATFORM_MACOSX) && !defined(TARGET_ARM))
-       gchar *bindir, *installdir, *root, *name, *config;
+       gchar *bindir, *installdir, *root, *name, *resolvedname, *config;
 
 #ifdef HOST_WIN32
        name = mono_get_module_file_name ((HMODULE) &__ImageBase);
@@ -615,7 +628,9 @@ mono_set_rootdir (void)
        }
 #endif
 
-       bindir = g_path_get_dirname (name);
+       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);
 
@@ -634,6 +649,7 @@ mono_set_rootdir (void)
        g_free (installdir);
        g_free (bindir);
        g_free (name);
+       g_free (resolvedname);
 #elif defined(DISABLE_MONO_AUTODETECTION)
        fallback ();
 #else
@@ -749,9 +765,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",
@@ -790,6 +808,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)
 {
@@ -838,6 +857,7 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
        }
        return aname;
 }
+#endif
 
 /*
  * mono_assembly_get_assemblyref:
@@ -954,11 +974,11 @@ 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)
-                               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s %p\n",
+                               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Failed to load assembly %s[%p]\n",
                                    image->assembly->aname.name, image->assembly);
                }
                
@@ -1553,7 +1573,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
@@ -1638,7 +1658,15 @@ parse_public_key (const gchar *key, gchar** pubkey)
        keylen = strlen (key) >> 1;
        if (keylen < 1)
                return FALSE;
-       
+
+       /* allow the ECMA standard key */
+       if (strcmp (key, "00000000000000000400000000000000") == 0) {
+               if (pubkey) {
+                       arr = g_strdup ("b77a5c561934e089");
+                       *pubkey = arr;
+               }
+               return TRUE;
+       }
        val = g_ascii_xdigit_value (key [0]) << 4;
        val |= g_ascii_xdigit_value (key [1]);
        switch (val) {
@@ -1707,7 +1735,7 @@ parse_public_key (const gchar *key, gchar** pubkey)
 }
 
 static gboolean
-build_assembly_name (const char *name, const char *version, const char *culture, const char *token, const char *key, guint32 flags, MonoAssemblyName *aname, gboolean save_public_key)
+build_assembly_name (const char *name, const char *version, const char *culture, const char *token, const char *key, guint32 flags, guint32 arch, MonoAssemblyName *aname, gboolean save_public_key)
 {
        gint major, minor, build, revision;
        gint len;
@@ -1737,6 +1765,7 @@ build_assembly_name (const char *name, const char *version, const char *culture,
        }
        
        aname->flags = flags;
+       aname->arch = arch;
        aname->name = g_strdup (name);
        
        if (culture) {
@@ -1793,7 +1822,7 @@ parse_assembly_directory_name (const char *name, const char *dirname, MonoAssemb
                return FALSE;
        }
        
-       res = build_assembly_name (name, parts[0], parts[1], parts[2], NULL, 0, aname, FALSE);
+       res = build_assembly_name (name, parts[0], parts[1], parts[2], NULL, 0, 0, aname, FALSE);
        g_strfreev (parts);
        return res;
 }
@@ -1814,6 +1843,7 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
        gboolean version_defined;
        gboolean token_defined;
        guint32 flags = 0;
+       guint32 arch = PROCESSOR_ARCHITECTURE_NONE;
 
        if (!is_version_defined)
                is_version_defined = &version_defined;
@@ -1887,7 +1917,19 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                }
 
                if (!g_ascii_strncasecmp (value, "ProcessorArchitecture=", 22)) {
-                       /* this is ignored for now, until we can change MonoAssemblyName */
+                       char *s = g_strstrip (value + 22);
+                       if (!g_ascii_strcasecmp (s, "None"))
+                               arch = PROCESSOR_ARCHITECTURE_NONE;
+                       else if (!g_ascii_strcasecmp (s, "MSIL"))
+                               arch = PROCESSOR_ARCHITECTURE_MSIL;
+                       else if (!g_ascii_strcasecmp (s, "X86"))
+                               arch = PROCESSOR_ARCHITECTURE_X86;
+                       else if (!g_ascii_strcasecmp (s, "IA64"))
+                               arch = PROCESSOR_ARCHITECTURE_IA64;
+                       else if (!g_ascii_strcasecmp (s, "AMD64"))
+                               arch = PROCESSOR_ARCHITECTURE_AMD64;
+                       else
+                               goto cleanup_and_fail;
                        tmp++;
                        continue;
                }
@@ -1901,7 +1943,7 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                goto cleanup_and_fail;
        }
 
-       res = build_assembly_name (dllname, version, culture, token, key, flags,
+       res = build_assembly_name (dllname, version, culture, token, key, flags, arch,
                aname, save_public_key);
        g_strfreev (parts);
        return res;
@@ -2053,7 +2095,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;
 
@@ -2063,12 +2108,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) {
@@ -2417,7 +2464,15 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
 
                mono_loader_lock ();
                mono_domain_lock (domain);
-               info = get_per_domain_assembly_binding_info (domain, aname);
+               info2 = get_per_domain_assembly_binding_info (domain, aname);
+
+               if (info2) {
+                       info = g_memdup (info2, sizeof (MonoAssemblyBindingInfo));
+                       info->name = g_strdup (info2->name);
+                       info->culture = g_strdup (info2->culture);
+                       info->domain_id = domain->domain_id;
+               }
+
                mono_domain_unlock (domain);
                mono_loader_unlock ();
        }
@@ -2540,6 +2595,7 @@ MonoAssembly*
 mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *status)
 {
        char *corlib_file;
+       MonoAssemblyName *aname;
 
        if (corlib) {
                /* g_print ("corlib already loaded\n"); */
@@ -2561,7 +2617,14 @@ mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *
                        return corlib;
        }
 #endif
-       
+
+       aname = mono_assembly_name_new ("mscorlib.dll");
+       corlib = invoke_assembly_preload_hook (aname, assemblies_path);
+       mono_assembly_name_free (aname);
+       g_free (aname);
+       if (corlib != NULL)
+               return corlib;
+
        if (assemblies_path) {
                corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status, FALSE);
                if (corlib)
@@ -2592,12 +2655,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)
@@ -2708,9 +2776,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);
 
@@ -2854,6 +2924,27 @@ mono_assemblies_cleanup (void)
        free_assembly_preload_hooks ();
 }
 
+/*LOCKING assumes loader lock is held*/
+void
+mono_assembly_cleanup_domain_bindings (guint32 domain_id)
+{
+       GSList **iter = &loaded_assembly_bindings;
+
+       while (*iter) {
+               GSList *l = *iter;
+               MonoAssemblyBindingInfo *info = l->data;
+
+               if (info->domain_id == domain_id) {
+                       *iter = l->next;
+                       mono_assembly_binding_info_free (info);
+                       g_free (info);
+                       g_slist_free_1 (l);
+               } else {
+                       iter = &l->next;
+               }
+       }
+}
+
 /*
  * Holds the assembly of the application, for
  * System.Diagnostics.Process::MainModule