Merge pull request #900 from Blewzman/FixAggregateExceptionGetBaseException
[mono.git] / mono / metadata / assembly.c
index 2d0557264401727357c41bfdc125a9068ad3d1e2..459602bcfc58e34e1886401bf227c652f2c943bc 100644 (file)
 #include <mono/utils/mono-path.h>
 #include <mono/metadata/reflection.h>
 #include <mono/metadata/coree.h>
+#include <mono/metadata/cil-coff.h>
 #include <mono/utils/mono-io-portability.h>
 #include <mono/utils/atomic.h>
+#include <mono/utils/mono-mutex.h>
 
 #ifndef HOST_WIN32
 #include <sys/types.h>
@@ -55,6 +57,7 @@ typedef struct  {
 /* the default search path is empty, the first slot is replaced with the computed value */
 static const char*
 default_path [] = {
+       NULL,
        NULL,
        NULL
 };
@@ -106,6 +109,8 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"System.Data", 0},
        {"System.Data.Linq", 2},
        {"System.Data.OracleClient", 0},
+       {"System.Data.Services", 2},
+       {"System.Data.Services.Client", 2},
        {"System.Data.SqlXml", 0},
        {"System.Design", 0},
        {"System.DirectoryServices", 0},
@@ -114,19 +119,25 @@ static const AssemblyVersionMap framework_assemblies [] = {
        {"System.EnterpriseServices", 0},
        {"System.Management", 0},
        {"System.Messaging", 0},
+       {"System.Net", 2},
        {"System.Runtime.Remoting", 0},
        {"System.Runtime.Serialization", 3},
        {"System.Runtime.Serialization.Formatters.Soap", 0},
        {"System.Security", 0},
+       {"System.ServiceModel.Web", 2},
        {"System.ServiceProcess", 0},
        {"System.Transactions", 0},
        {"System.Web", 0},
        {"System.Web.Abstractions", 2},
+       {"System.Web.DynamicData", 2},
+       {"System.Web.Extensions", 2},
        {"System.Web.Mobile", 0},
        {"System.Web.Routing", 2},
        {"System.Web.Services", 0},
        {"System.Windows.Forms", 0},
        {"System.Xml", 0},
+       {"System.Xml.Linq", 2},
+       {"WindowsBase", 3},
        {"mscorlib", 0}
 };
 #endif
@@ -166,6 +177,8 @@ static CRITICAL_SECTION assemblies_mutex;
 /* If defined, points to the bundled assembly information */
 const MonoBundledAssembly **bundles;
 
+static mono_mutex_t assembly_binding_mutex;
+
 /* Loaded assembly binding info */
 static GSList *loaded_assembly_bindings = NULL;
 
@@ -644,6 +657,7 @@ mono_set_rootdir (void)
                gchar buf[4096];
                guint buf_size = sizeof (buf);
  
+               name = NULL;
                if (_NSGetExecutablePath (buf, &buf_size) == 0)
                        name = g_strdup (buf);
  
@@ -724,6 +738,19 @@ mono_assemblies_init (void)
        check_extra_gac_path_env ();
 
        InitializeCriticalSection (&assemblies_mutex);
+       mono_mutex_init (&assembly_binding_mutex);
+}
+
+static void
+mono_assembly_binding_lock (void)
+{
+       mono_locks_mutex_acquire (&assembly_binding_mutex, AssemblyBindingLock);
+}
+
+static void
+mono_assembly_binding_unlock (void)
+{
+       mono_locks_mutex_release (&assembly_binding_mutex, AssemblyBindingLock);
 }
 
 gboolean
@@ -731,6 +758,7 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
 {
        MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY];
        guint32 cols [MONO_ASSEMBLY_SIZE];
+       gint32 machine, flags;
 
        if (!t->rows)
                return FALSE;
@@ -775,6 +803,31 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
        else
                aname->public_key = 0;
 
+       machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
+       flags = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags;
+       switch (machine) {
+       case COFF_MACHINE_I386:
+               /* https://bugzilla.xamarin.com/show_bug.cgi?id=17632 */
+               if (flags & (CLI_FLAGS_32BITREQUIRED|CLI_FLAGS_PREFERRED32BIT))
+                       aname->arch = MONO_PROCESSOR_ARCHITECTURE_X86;
+               else if ((flags & 0x70) == 0x70)
+                       aname->arch = MONO_PROCESSOR_ARCHITECTURE_NONE;
+               else
+                       aname->arch = MONO_PROCESSOR_ARCHITECTURE_MSIL;
+               break;
+       case COFF_MACHINE_IA64:
+               aname->arch = MONO_PROCESSOR_ARCHITECTURE_IA64;
+               break;
+       case COFF_MACHINE_AMD64:
+               aname->arch = MONO_PROCESSOR_ARCHITECTURE_AMD64;
+               break;
+       case COFF_MACHINE_ARM:
+               aname->arch = MONO_PROCESSOR_ARCHITECTURE_ARM;
+               break;
+       default:
+               break;
+       }
+
        return TRUE;
 }
 
@@ -834,6 +887,11 @@ mono_assembly_addref (MonoAssembly *assembly)
        InterlockedIncrement (&assembly->ref_count);
 }
 
+/*
+ * CAUTION: This table must be kept in sync with
+ *          ivkm/reflect/Fusion.cs
+ */
+
 #define SILVERLIGHT_KEY "7cec85d7bea7798e"
 #define WINFX_KEY "31bf3856ad364e35"
 #define ECMA_KEY "b77a5c561934e089"
@@ -851,6 +909,8 @@ static KeyRemapEntry key_remap_table[] = {
        { "System.ComponentModel.Composition", WINFX_KEY, ECMA_KEY },
        { "System.ComponentModel.DataAnnotations", "ddd0da4d3e678217", WINFX_KEY },
        { "System.Core", SILVERLIGHT_KEY, ECMA_KEY },
+       // FIXME: MS uses MSFINAL_KEY for .NET 4.5
+       { "System.Net", SILVERLIGHT_KEY, MSFINAL_KEY },
        { "System.Numerics", WINFX_KEY, ECMA_KEY },
        { "System.Runtime.Serialization", SILVERLIGHT_KEY, ECMA_KEY },
        { "System.ServiceModel", WINFX_KEY, ECMA_KEY },
@@ -858,7 +918,7 @@ static KeyRemapEntry key_remap_table[] = {
        { "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 }
+       { "System.Xml.Serialization", WINFX_KEY, ECMA_KEY }
 };
 
 static void
@@ -874,7 +934,7 @@ remap_keys (MonoAssemblyName *aname)
 
                memcpy (aname->public_key_token, entry->to, MONO_PUBLIC_KEY_TOKEN_LENGTH);
                     
-               mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+               mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY,
                            "Remapped public key token of retargetable assembly %s from %s to %s",
                            aname->name, entry->from, entry->to);
                return;
@@ -910,7 +970,7 @@ mono_assembly_remap_version (MonoAssemblyName *aname, MonoAssemblyName *dest_ana
                
                remap_keys (dest_aname);
 
-               mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_ASSEMBLY,
+               mono_trace (G_LOG_LEVEL_INFO, 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,
@@ -1016,6 +1076,7 @@ mono_assembly_load_reference (MonoImage *image, int index)
                MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];
        
                image->references = g_new0 (MonoAssembly *, t->rows + 1);
+               image->nreferences = t->rows;
        }
        reference = image->references [index];
        mono_assemblies_unlock ();
@@ -2055,9 +2116,7 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                }
 
                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"))
+                       if (!g_ascii_strcasecmp (value, "MSIL"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_MSIL;
                        else if (!g_ascii_strcasecmp (value, "X86"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_X86;
@@ -2431,7 +2490,7 @@ mono_assembly_bind_version (MonoAssemblyBindingInfo *info, MonoAssemblyName *ana
        return dest_name;
 }
 
-/* LOCKING: Assumes that we are already locked */
+/* LOCKING: assembly_binding lock must be held */
 static MonoAssemblyBindingInfo*
 search_binding_loaded (MonoAssemblyName *aname)
 {
@@ -2508,16 +2567,23 @@ assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data)
        domain->assembly_bindings = g_slist_append_mempool (domain->mp, domain->assembly_bindings, info_copy);
 }
 
+static int
+get_version_number (int major, int minor)
+{
+       return major * 256 + minor;
+}
+
 static inline gboolean
 info_major_minor_in_range (MonoAssemblyBindingInfo *info, MonoAssemblyName *aname)
 {
+       int aname_version_number = get_version_number (aname->major, aname->minor);
        if (!info->has_old_version_bottom)
                return FALSE;
 
-       if (info->old_version_bottom.major > aname->major || info->old_version_bottom.minor > aname->minor)
+       if (get_version_number (info->old_version_bottom.major, info->old_version_bottom.minor) > aname_version_number)
                return FALSE;
 
-       if (info->has_old_version_top && (info->old_version_top.major < aname->major || info->old_version_top.minor < aname->minor))
+       if (info->has_old_version_top && get_version_number (info->old_version_top.major, info->old_version_top.minor) < aname_version_number)
                return FALSE;
 
        /* This is not the nicest way to do it, but it's a by-product of the way parsing is done */
@@ -2567,15 +2633,17 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
                return aname;
 
        domain = mono_domain_get ();
-       mono_loader_lock ();
+
+       mono_assembly_binding_lock ();
        info = search_binding_loaded (aname);
+       mono_assembly_binding_unlock ();
+
        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))
                        return aname;
@@ -2599,10 +2667,7 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
                                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) {
@@ -2613,7 +2678,6 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
                }
 
                mono_domain_unlock (domain);
-               mono_loader_unlock ();
        }
 
        if (!info) {
@@ -2637,7 +2701,7 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
                g_strlcpy ((char *)info->public_key_token, (const char *)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH);
        }
        
-       mono_loader_lock ();
+       mono_assembly_binding_lock ();
        info2 = search_binding_loaded (aname);
        if (info2) {
                /* This binding was added by another thread 
@@ -2649,7 +2713,7 @@ mono_assembly_apply_binding (MonoAssemblyName *aname, MonoAssemblyName *dest_nam
        } else
                loaded_assembly_bindings = g_slist_prepend (loaded_assembly_bindings, info);
                
-       mono_loader_unlock ();
+       mono_assembly_binding_unlock ();
        
        if (!info->is_valid || !check_policy_versions (info, aname))
                return aname;
@@ -2782,7 +2846,10 @@ mono_assembly_load_corlib (const MonoRuntimeInfo *runtime, MonoImageOpenStatus *
        }
        corlib = load_in_path (corlib_file, default_path, status, FALSE);
        g_free (corlib_file);
-
+       
+       if (corlib && !strcmp (runtime->framework_version, "4.5"))
+               default_path [1] = g_strdup_printf ("%s/mono/4.5/Facades", default_path [0]);
+               
        return corlib;
 }
 
@@ -3058,6 +3125,7 @@ mono_assemblies_cleanup (void)
        GSList *l;
 
        DeleteCriticalSection (&assemblies_mutex);
+       mono_mutex_destroy (&assembly_binding_mutex);
 
        for (l = loaded_assembly_bindings; l; l = l->next) {
                MonoAssemblyBindingInfo *info = l->data;
@@ -3072,12 +3140,14 @@ mono_assemblies_cleanup (void)
        free_assembly_preload_hooks ();
 }
 
-/*LOCKING assumes loader lock is held*/
+/*LOCKING takes the assembly_binding lock*/
 void
 mono_assembly_cleanup_domain_bindings (guint32 domain_id)
 {
-       GSList **iter = &loaded_assembly_bindings;
+       GSList **iter;
 
+       mono_assembly_binding_lock ();
+       iter = &loaded_assembly_bindings;
        while (*iter) {
                GSList *l = *iter;
                MonoAssemblyBindingInfo *info = l->data;
@@ -3091,6 +3161,7 @@ mono_assembly_cleanup_domain_bindings (guint32 domain_id)
                        iter = &l->next;
                }
        }
+       mono_assembly_binding_unlock ();
 }
 
 /*