NaCl runtime fixes
[mono.git] / mono / metadata / assembly.c
index 2a5e7fcb3acf661eaf1c442602b130f9f42131eb..2d0557264401727357c41bfdc125a9068ad3d1e2 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  */
 #include <config.h>
 #include <stdio.h>
 #include <mono/utils/mono-uri.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/utils/mono-digest.h>
-#include <mono/utils/mono-logger.h>
+#include <mono/utils/mono-logger-internal.h>
+#include <mono/utils/mono-path.h>
 #include <mono/metadata/reflection.h>
 #include <mono/metadata/coree.h>
+#include <mono/utils/mono-io-portability.h>
+#include <mono/utils/atomic.h>
 
 #ifndef HOST_WIN32
 #include <sys/types.h>
@@ -61,8 +65,12 @@ 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.
+ * The integer number is an index in the MonoRuntimeInfo structure, whose
+ * values can be found in domain.c - supported_runtimes. Look there
+ * to understand what remapping will be made.
  */
 static const AssemblyVersionMap framework_assemblies [] = {
        {"Accessibility", 0},
@@ -91,8 +99,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},
@@ -103,16 +115,21 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"System.Management", 0},
        {"System.Messaging", 0},
        {"System.Runtime.Remoting", 0},
+       {"System.Runtime.Serialization", 3},
        {"System.Runtime.Serialization.Formatters.Soap", 0},
        {"System.Security", 0},
        {"System.ServiceProcess", 0},
+       {"System.Transactions", 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
@@ -120,6 +137,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)
@@ -166,16 +204,24 @@ mono_public_tokens_are_equal (const unsigned char *pubt1, const unsigned char *p
        return memcmp (pubt1, pubt2, 16) == 0;
 }
 
-static void
-check_path_env (void)
+/**
+ * mono_set_assemblies_path:
+ * @path: list of paths that contain directories where Mono will look for assemblies
+ *
+ * Use this method to override the standard assembly lookup system and
+ * override any assemblies coming from the GAC.  This is the method
+ * that supports the MONO_PATH variable.
+ *
+ * Notice that MONO_PATH and this method are really a very bad idea as
+ * it prevents the GAC from working and it prevents the standard
+ * resolution mechanisms from working.  Nonetheless, for some debugging
+ * situations and bootstrapping setups, this is useful to have. 
+ */
+void
+mono_set_assemblies_path (const char* path)
 {
-       const char *path;
        char **splitted, **dest;
        
-       path = g_getenv ("MONO_PATH");
-       if (!path)
-               return;
-
        splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000);
        if (assemblies_path)
                g_strfreev (assemblies_path);
@@ -199,6 +245,27 @@ check_path_env (void)
        }
 }
 
+/* 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;
+       path = g_getenv ("MONO_PATH");
+#ifdef __native_client__
+       if (!path)
+               path = nacl_mono_path;
+#endif
+       if (!path || assemblies_path != NULL)
+               return;
+
+       mono_set_assemblies_path(path);
+}
+
 static void
 check_extra_gac_path_env (void) {
        const char *path;
@@ -233,16 +300,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))
@@ -254,6 +324,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);
 }
@@ -494,7 +567,7 @@ compute_base (char *path)
                return NULL;
 
        /* Not a well known Mono executable, we are embedded, cant guess the base  */
-       if (strcmp (p, "/mono") && strcmp (p, "/monodis") && strcmp (p, "/mint") && strcmp (p, "/monodiet"))
+       if (strcmp (p, "/mono") && strcmp (p, "/mono-sgen") && strcmp (p, "/pedump") && strcmp (p, "/monodis") && strcmp (p, "/mint") && strcmp (p, "/monodiet"))
                return NULL;
            
        *p = 0;
@@ -514,7 +587,7 @@ fallback (void)
        mono_set_dirs (MONO_ASSEMBLIES, MONO_CFG_DIR);
 }
 
-static void
+static G_GNUC_UNUSED void
 set_dirs (char *exe)
 {
        char *base;
@@ -531,7 +604,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 {
@@ -555,7 +628,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);
@@ -581,18 +654,28 @@ 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);
 
        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
@@ -708,9 +791,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",
@@ -749,6 +834,53 @@ mono_assembly_addref (MonoAssembly *assembly)
        InterlockedIncrement (&assembly->ref_count);
 }
 
+#define SILVERLIGHT_KEY "7cec85d7bea7798e"
+#define WINFX_KEY "31bf3856ad364e35"
+#define ECMA_KEY "b77a5c561934e089"
+#define MSFINAL_KEY "b03f5f7f11d50a3a"
+
+typedef struct {
+       const char *name;
+       const char *from;
+       const char *to;
+} KeyRemapEntry;
+
+static KeyRemapEntry key_remap_table[] = {
+       { "Microsoft.CSharp", WINFX_KEY, MSFINAL_KEY },
+       { "System", SILVERLIGHT_KEY, ECMA_KEY },
+       { "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY },
+       { "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY },
+       { "System.Core", SILVERLIGHT_KEY, ECMA_KEY },
+       { "System.Numerics", WINFX_KEY, ECMA_KEY },
+       { "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY },
+       { "System.ServiceModel", WINFX_KEY, ECMA_KEY },
+       { "System.ServiceModel.Web", SILVERLIGHT_KEY, WINFX_KEY },
+       { "System.Windows", SILVERLIGHT_KEY, MSFINAL_KEY },
+       { "System.Xml", SILVERLIGHT_KEY, ECMA_KEY },
+       { "System.Xml.Linq", WINFX_KEY, ECMA_KEY },
+       { "System.Xml.Serialization", WINFX_KEY, MSFINAL_KEY }
+};
+
+static void
+remap_keys (MonoAssemblyName *aname)
+{
+       int i;
+       for (i = 0; i < G_N_ELEMENTS (key_remap_table); i++) {
+               const KeyRemapEntry *entry = &key_remap_table [i];
+
+               if (strcmp (aname->name, entry->name) ||
+                   !mono_public_tokens_are_equal (aname->public_key_token, (const unsigned char*) entry->from))
+                       continue;
+
+               memcpy (aname->public_key_token, entry->to, MONO_PUBLIC_KEY_TOKEN_LENGTH);
+                    
+               mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+                           "Remapped public key token of retargetable assembly %s from %s to %s",
+                           aname->name, entry->from, entry->to);
+               return;
+       }
+}
+
 static MonoAssemblyName *
 mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_aname)
 {
@@ -756,8 +888,40 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
        int pos, first, last;
 
        if (aname->name == NULL) return aname;
+
        current_runtime = mono_get_runtime_info ();
 
+       if (aname->flags & ASSEMBLYREF_RETARGETABLE_FLAG) {
+               const AssemblyVersionSet* vset;
+
+               /* Remap to current runtime */
+               vset = &current_runtime->version_sets [0];
+
+               memcpy (dest_aname, aname, sizeof(MonoAssemblyName));
+               dest_aname->major = vset->major;
+               dest_aname->minor = vset->minor;
+               dest_aname->build = vset->build;
+               dest_aname->revision = vset->revision;
+               dest_aname->flags &= ~ASSEMBLYREF_RETARGETABLE_FLAG;
+
+               /* Remap assembly name */
+               if (!strcmp (aname->name, "System.Net"))
+                       dest_aname->name = g_strdup ("System");
+               
+               remap_keys (dest_aname);
+
+               mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+                                       "The request to load the retargetable assembly %s v%d.%d.%d.%d was remapped to %s v%d.%d.%d.%d",
+                                       aname->name,
+                                       aname->major, aname->minor, aname->build, aname->revision,
+                                       dest_aname->name,
+                                       vset->major, vset->minor, vset->build, vset->revision
+                                       );
+
+               return dest_aname;
+       }
+       
+#ifndef DISABLE_ASSEMBLY_REMAPPING
        first = 0;
        last = G_N_ELEMENTS (framework_assemblies) - 1;
        
@@ -795,6 +959,8 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
                        first = pos + 1;
                }
        }
+#endif
+
        return aname;
 }
 
@@ -893,7 +1059,7 @@ mono_assembly_load_reference (MonoImage *image, int index)
                        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",
@@ -913,11 +1079,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);
                }
                
@@ -1512,7 +1678,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
@@ -1588,7 +1754,7 @@ mono_assembly_name_free (MonoAssemblyName *aname)
 }
 
 static gboolean
-parse_public_key (const gchar *key, gchar** pubkey)
+parse_public_key (const gchar *key, gchar** pubkey, gboolean *is_ecma)
 {
        const gchar *pkey;
        gchar header [16], val, *arr;
@@ -1597,7 +1763,16 @@ 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) {
+                       *pubkey = g_strdup (key);
+                       *is_ecma = TRUE;
+               }
+               return TRUE;
+       }
+       *is_ecma = FALSE;
        val = g_ascii_xdigit_value (key [0]) << 4;
        val |= g_ascii_xdigit_value (key [1]);
        switch (val) {
@@ -1666,7 +1841,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;
@@ -1696,6 +1871,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) {
@@ -1719,10 +1895,20 @@ build_assembly_name (const char *name, const char *version, const char *culture,
        }
 
        if (key) {
-               if (strcmp (key, "null") == 0 || !parse_public_key (key, &pkey)) {
+               gboolean is_ecma;
+               if (strcmp (key, "null") == 0 || !parse_public_key (key, &pkey, &is_ecma)) {
                        mono_assembly_name_free (aname);
                        return FALSE;
                }
+
+               if (is_ecma) {
+                       if (save_public_key)
+                               aname->public_key = (guint8*)pkey;
+                       else
+                               g_free (pkey);
+                       g_strlcpy ((gchar*)aname->public_key_token, "b77a5c561934e089", MONO_PUBLIC_KEY_TOKEN_LENGTH);
+                       return TRUE;
+               }
                
                len = mono_metadata_decode_blob_size ((const gchar *) pkey, (const gchar **) &pkeyptr);
                // We also need to generate the key token
@@ -1752,11 +1938,30 @@ 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;
 }
 
+static gboolean
+split_key_value (const gchar *pair, gchar **key, guint32 *keylen, gchar **value)
+{
+       char *eqsign = strchr (pair, '=');
+       if (!eqsign) {
+               *key = NULL;
+               *keylen = 0;
+               *value = NULL;
+               return FALSE;
+       }
+
+       *key = (gchar*)pair;
+       *keylen = eqsign - *key;
+       while (*keylen > 0 && g_ascii_isspace ((*key) [*keylen - 1]))
+               (*keylen)--;
+       *value = g_strstrip (eqsign + 1);
+       return TRUE;
+}
+
 gboolean
 mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboolean save_public_key, gboolean *is_version_defined, gboolean *is_token_defined)
 {
@@ -1767,12 +1972,14 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
        gchar *key = NULL;
        gchar *retargetable = NULL;
        gboolean res;
-       gchar *value;
+       gchar *value, *part_name;
+       guint32 part_name_len;
        gchar **parts;
        gchar **tmp;
        gboolean version_defined;
        gboolean token_defined;
        guint32 flags = 0;
+       guint32 arch = MONO_PROCESSOR_ARCHITECTURE_NONE;
 
        if (!is_version_defined)
                is_version_defined = &version_defined;
@@ -1792,10 +1999,12 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
        tmp++;
 
        while (*tmp) {
-               value = g_strstrip (*tmp);
-               if (!g_ascii_strncasecmp (value, "Version=", 8)) {
+               if (!split_key_value (g_strstrip (*tmp), &part_name, &part_name_len, &value))
+                       goto cleanup_and_fail;
+
+               if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Version", part_name_len)) {
                        *is_version_defined = TRUE;
-                       version = g_strstrip (value + 8);
+                       version = value;
                        if (strlen (version) == 0) {
                                goto cleanup_and_fail;
                        }
@@ -1803,8 +2012,8 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        continue;
                }
 
-               if (!g_ascii_strncasecmp (value, "Culture=", 8)) {
-                       culture = g_strstrip (value + 8);
+               if (part_name_len == 7 && !g_ascii_strncasecmp (part_name, "Culture", part_name_len)) {
+                       culture = value;
                        if (strlen (culture) == 0) {
                                goto cleanup_and_fail;
                        }
@@ -1812,9 +2021,9 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        continue;
                }
 
-               if (!g_ascii_strncasecmp (value, "PublicKeyToken=", 15)) {
+               if (part_name_len == 14 && !g_ascii_strncasecmp (part_name, "PublicKeyToken", part_name_len)) {
                        *is_token_defined = TRUE;
-                       token = g_strstrip (value + 15);
+                       token = value;
                        if (strlen (token) == 0) {
                                goto cleanup_and_fail;
                        }
@@ -1822,8 +2031,8 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        continue;
                }
 
-               if (!g_ascii_strncasecmp (value, "PublicKey=", 10)) {
-                       key = g_strstrip (value + 10);
+               if (part_name_len == 9 && !g_ascii_strncasecmp (part_name, "PublicKey", part_name_len)) {
+                       key = value;
                        if (strlen (key) == 0) {
                                goto cleanup_and_fail;
                        }
@@ -1831,8 +2040,8 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        continue;
                }
 
-               if (!g_ascii_strncasecmp (value, "Retargetable=", 13)) {
-                       retargetable = g_strstrip (value + 13);
+               if (part_name_len == 12 && !g_ascii_strncasecmp (part_name, "Retargetable", part_name_len)) {
+                       retargetable = value;
                        if (strlen (retargetable) == 0) {
                                goto cleanup_and_fail;
                        }
@@ -1845,8 +2054,19 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        continue;
                }
 
-               if (!g_ascii_strncasecmp (value, "ProcessorArchitecture=", 22)) {
-                       /* this is ignored for now, until we can change MonoAssemblyName */
+               if (part_name_len == 21 && !g_ascii_strncasecmp (part_name, "ProcessorArchitecture", part_name_len)) {
+                       if (!g_ascii_strcasecmp (value, "None"))
+                               arch = MONO_PROCESSOR_ARCHITECTURE_NONE;
+                       else if (!g_ascii_strcasecmp (value, "MSIL"))
+                               arch = MONO_PROCESSOR_ARCHITECTURE_MSIL;
+                       else if (!g_ascii_strcasecmp (value, "X86"))
+                               arch = MONO_PROCESSOR_ARCHITECTURE_X86;
+                       else if (!g_ascii_strcasecmp (value, "IA64"))
+                               arch = MONO_PROCESSOR_ARCHITECTURE_IA64;
+                       else if (!g_ascii_strcasecmp (value, "AMD64"))
+                               arch = MONO_PROCESSOR_ARCHITECTURE_AMD64;
+                       else
+                               goto cleanup_and_fail;
                        tmp++;
                        continue;
                }
@@ -1860,7 +2080,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;
@@ -1886,6 +2106,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)
 {
@@ -1961,7 +2232,8 @@ MonoAssembly*
 mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status)
 {
        MonoAssembly *res;
-       MonoAssemblyName *aname, base_name, maped_aname;
+       MonoAssemblyName *aname, base_name;
+       MonoAssemblyName mapped_aname;
        gchar *fullname, *gacpath;
        gchar **paths;
 
@@ -1976,7 +2248,7 @@ mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *sta
         * correct version for system assemblies.
         */ 
        if ((aname->major | aname->minor | aname->build | aname->revision) == 0)
-               aname = mono_assembly_remap_version (aname, &maped_aname);
+               aname = mono_assembly_remap_version (aname, &mapped_aname);
        
        res = mono_assembly_loaded (aname);
        if (res) {
@@ -2174,17 +2446,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))
@@ -2194,14 +2584,50 @@ 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_name = mono_string_to_utf8 (domain->setup->configuration_file);
+                       gchar *domain_config_file_path = mono_portability_find_file (domain_config_file_name, TRUE);
+
+                       if (!domain_config_file_path)
+                               domain_config_file_path = domain_config_file_name;
+                       
+                       mono_config_parse_assembly_bindings (domain_config_file_path, aname->major, aname->minor, domain, assembly_binding_info_parsed);
+                       domain->assembly_bindings_parsed = TRUE;
+                       if (domain_config_file_name != domain_config_file_path)
+                               g_free (domain_config_file_name);
+                       g_free (domain_config_file_path);
+               }
+               mono_domain_unlock (domain);
+
+               mono_loader_lock ();
+               mono_domain_lock (domain);
+               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 ();
+       }
+
+       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 */
@@ -2304,17 +2730,40 @@ 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);
+       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)
@@ -2345,7 +2794,8 @@ mono_assembly_load_full_nosearch (MonoAssemblyName *aname,
 {
        MonoAssembly *result;
        char *fullpath, *filename;
-       MonoAssemblyName maped_aname, maped_name_pp;
+       MonoAssemblyName maped_aname;
+       MonoAssemblyName maped_name_pp;
        int ext_index;
        const char *ext;
        int len;
@@ -2483,6 +2933,21 @@ mono_assembly_loaded (MonoAssemblyName *aname)
        return mono_assembly_loaded_full (aname, FALSE);
 }
 
+void
+mono_assembly_release_gc_roots (MonoAssembly *assembly)
+{
+       if (assembly == NULL || assembly == REFERENCE_MISSING)
+               return;
+
+       if (assembly->dynamic) {
+               int i;
+               MonoDynamicImage *dynimg = (MonoDynamicImage *)assembly->image;
+               for (i = 0; i < dynimg->image.module_count; ++i)
+                       mono_dynamic_image_release_gc_roots ((MonoDynamicImage *)dynimg->image.modules [i]);
+               mono_dynamic_image_release_gc_roots (dynimg);
+       }
+}
+
 /*
  * Returns whether mono_assembly_close_finish() must be called as
  * well.  See comment for mono_image_close_except_pools() for why we
@@ -2607,6 +3072,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