Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / appdomain.c
index 819ce65616e9a93d8628e0b5a39c55ce0b0a06de..e04b84a7253da2ddaad0d46069337cf8e7ddd81d 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * appdomain.c: AppDomain functions
+/**
+ * \file
+ * AppDomain functions
  *
  * Authors:
  *     Dietmar Maurer (dietmar@ximian.com)
@@ -38,7 +39,7 @@
 #include <mono/metadata/appdomain-icalls.h>
 #include <mono/metadata/domain-internals.h>
 #include "mono/metadata/metadata-internals.h"
-#include <mono/metadata/assembly.h>
+#include <mono/metadata/assembly-internals.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/exception-internals.h>
 #include <mono/metadata/threads.h>
@@ -49,7 +50,6 @@
 #include <mono/metadata/marshal-internals.h>
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-debug-debugger.h>
 #include <mono/metadata/attach.h>
 #include <mono/metadata/w32file.h>
 #include <mono/metadata/lock-tracer.h>
 #include <direct.h>
 #endif
 
-/*
- * This is the version number of the corlib-runtime interface. When
- * making changes to this interface (by changing the layout
- * of classes the runtime knows about, changing icall signature or
- * semantics etc), increment this variable. Also increment the
- * pair of this variable in mscorlib in:
- *       mcs/class/corlib/System/Environment.cs
- *
- * Changes which are already detected at runtime, like the addition
- * of icalls, do not require an increment.
- */
-#define MONO_CORLIB_VERSION 164
-
 typedef struct
 {
        int runtime_count;
@@ -124,6 +111,9 @@ static MonoDomain *
 mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error);
 
 
+static void
+mono_context_set_default_context (MonoDomain *domain);
+
 static char *
 get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error);
 
@@ -202,7 +192,9 @@ create_domain_objects (MonoDomain *domain)
        string_vt = mono_class_vtable (domain, mono_defaults.string_class);
        string_empty_fld = mono_class_get_field_from_name (mono_defaults.string_class, "Empty");
        g_assert (string_empty_fld);
-       MonoString *empty_str = mono_string_intern_checked (mono_string_new (domain, ""), &error);
+       MonoString *empty_str = mono_string_new_checked (domain, "", &error);
+       mono_error_assert_ok (&error);
+       empty_str = mono_string_intern_checked (empty_str, &error);
        mono_error_assert_ok (&error);
        mono_field_static_set_value (string_vt, string_empty_fld, empty_str);
        domain->empty_string = empty_str;
@@ -210,7 +202,8 @@ create_domain_objects (MonoDomain *domain)
        /*
         * Create an instance early since we can't do it when there is no memory.
         */
-       arg = mono_string_new (domain, "Out of memory");
+       arg = mono_string_new_checked (domain, "Out of memory", &error);
+       mono_error_assert_ok (&error);
        domain->out_of_memory_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL, &error);
        mono_error_assert_ok (&error);
 
@@ -218,10 +211,12 @@ create_domain_objects (MonoDomain *domain)
         * These two are needed because the signal handlers might be executing on
         * an alternate stack, and Boehm GC can't handle that.
         */
-       arg = mono_string_new (domain, "A null value was found where an object instance was required");
+       arg = mono_string_new_checked (domain, "A null value was found where an object instance was required", &error);
+       mono_error_assert_ok (&error);
        domain->null_reference_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL, &error);
        mono_error_assert_ok (&error);
-       arg = mono_string_new (domain, "The requested operation caused a stack overflow.");
+       arg = mono_string_new_checked (domain, "The requested operation caused a stack overflow.", &error);
+       mono_error_assert_ok (&error);
        domain->stack_overflow_ex = mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL, &error);
        mono_error_assert_ok (&error);
 
@@ -243,14 +238,14 @@ create_domain_objects (MonoDomain *domain)
 
 /**
  * mono_runtime_init:
- * @domain: domain returned by mono_init ()
+ * \param domain domain returned by \c mono_init
  *
  * Initialize the core AppDomain: this function will run also some
  * IL initialization code, so it needs the execution engine to be fully 
  * operational.
  *
- * AppDomain.SetupInformation is set up in mono_runtime_exec_main, where
- * we know the entry_assembly.
+ * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where
+ * we know the \c entry_assembly.
  *
  */
 void
@@ -268,7 +263,7 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
        MonoAppDomain *ad;
        MonoClass *klass;
 
-       mono_error_init (error);
+       error_init (error);
 
        mono_portability_helpers_init ();
        
@@ -312,7 +307,7 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
        /* contexts use GC handles, so they must be initialized after the GC */
        mono_context_init_checked (domain, error);
        return_if_nok (error);
-       mono_context_set (domain->default_context);
+       mono_context_set_default_context (domain);
 
 #ifndef DISABLE_SOCKETS
        mono_network_init ();
@@ -329,6 +324,15 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
        return;
 }
 
+static void
+mono_context_set_default_context (MonoDomain *domain)
+{
+       HANDLE_FUNCTION_ENTER ();
+       mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext, domain->default_context));
+       HANDLE_FUNCTION_RETURN ();
+}
+
+
 static int
 mono_get_corlib_version (void)
 {
@@ -350,11 +354,9 @@ mono_get_corlib_version (void)
 }
 
 /**
- * mono_check_corlib_version
- *
+ * mono_check_corlib_version:
  * Checks that the corlib that is loaded matches the version of this runtime.
- *
- * Returns: NULL if the runtime will work with the corlib, or a g_malloc
+ * \returns NULL if the runtime will work with the corlib, or a \c g_malloc
  * allocated string with the error otherwise.
  */
 const char*
@@ -375,9 +377,8 @@ mono_check_corlib_version (void)
 
 /**
  * mono_context_init:
- * @domain: The domain where the System.Runtime.Remoting.Context.Context is initialized
- *
- * Initializes the @domain's default System.Runtime.Remoting's Context.
+ * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized
+ * Initializes the \p domain's default \c System.Runtime.Remoting 's Context.
  */
 void
 mono_context_init (MonoDomain *domain)
@@ -393,7 +394,7 @@ mono_context_init_checked (MonoDomain *domain, MonoError *error)
        MonoClass *klass;
        MonoAppContext *context;
 
-       mono_error_init (error);
+       error_init (error);
 
        klass = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
        context = (MonoAppContext *) mono_object_new_pinned (domain, klass, error);
@@ -401,13 +402,14 @@ mono_context_init_checked (MonoDomain *domain, MonoError *error)
 
        context->domain_id = domain->domain_id;
        context->context_id = 0;
-       ves_icall_System_Runtime_Remoting_Contexts_Context_RegisterContext (context);
+       mono_threads_register_app_context (context, error);
+       mono_error_assert_ok (error);
        domain->default_context = context;
 }
 
 /**
  * mono_runtime_cleanup:
- * @domain: unused.
+ * \param domain unused.
  *
  * Internal routine.
  *
@@ -436,12 +438,18 @@ mono_runtime_cleanup (MonoDomain *domain)
 
 static MonoDomainFunc quit_function = NULL;
 
+/**
+ * mono_install_runtime_cleanup:
+ */
 void
 mono_install_runtime_cleanup (MonoDomainFunc func)
 {
        quit_function = func;
 }
 
+/**
+ * mono_runtime_quit:
+ */
 void
 mono_runtime_quit ()
 {
@@ -451,10 +459,9 @@ mono_runtime_quit ()
 
 /**
  * mono_domain_create_appdomain:
- * @friendly_name: The friendly name of the appdomain to create
- * @configuration_file: The configuration file to initialize the appdomain with
- * 
- * Returns a MonoDomain initialized with the appdomain
+ * \param friendly_name The friendly name of the appdomain to create
+ * \param configuration_file The configuration file to initialize the appdomain with
+ * \returns a \c MonoDomain initialized with the appdomain
  */
 MonoDomain *
 mono_domain_create_appdomain (char *friendly_name, char *configuration_file)
@@ -468,17 +475,17 @@ mono_domain_create_appdomain (char *friendly_name, char *configuration_file)
 
 /**
  * mono_domain_create_appdomain_checked:
- * @friendly_name: The friendly name of the appdomain to create
- * @configuration_file: The configuration file to initialize the appdomain with
- * @error: Set on error.
+ * \param friendly_name The friendly name of the appdomain to create
+ * \param configuration_file The configuration file to initialize the appdomain with
+ * \param error Set on error.
  * 
- * Returns a MonoDomain initialized with the appdomain.  On failure sets @error and returns NULL.
+ * \returns a MonoDomain initialized with the appdomain.  On failure sets \p error and returns NULL.
  */
 MonoDomain *
 mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error)
 {
        HANDLE_FUNCTION_ENTER ();
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *result = NULL;
 
        MonoClass *klass = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
@@ -506,9 +513,9 @@ leave:
 
 /**
  * mono_domain_set_config:
- * @domain: MonoDomain initialized with the appdomain we want to change
- * @base_dir: new base directory for the appdomain
- * @config_file_name: path to the new configuration for the app domain
+ * \param domain \c MonoDomain initialized with the appdomain we want to change
+ * \param base_dir new base directory for the appdomain
+ * \param config_file_name path to the new configuration for the app domain
  *
  * Used to set the system configuration for an appdomain
  *
@@ -519,8 +526,28 @@ leave:
 void
 mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name)
 {
-       MONO_OBJECT_SETREF (domain->setup, application_base, mono_string_new (domain, base_dir));
-       MONO_OBJECT_SETREF (domain->setup, configuration_file, mono_string_new (domain, config_file_name));
+       HANDLE_FUNCTION_ENTER ();
+       MonoError error;
+       mono_domain_set_config_checked (domain, base_dir, config_file_name, &error);
+       mono_error_cleanup (&error);
+       HANDLE_FUNCTION_RETURN ();
+}
+
+gboolean
+mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error)
+{
+       error_init (error);
+       MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
+       MonoStringHandle base_dir_str = mono_string_new_handle (domain, base_dir, error);
+       if (!is_ok (error))
+               goto leave;
+       MONO_HANDLE_SET (setup, application_base, base_dir_str);
+       MonoStringHandle config_file_name_str = mono_string_new_handle (domain, config_file_name, error);
+       if (!is_ok (error))
+               goto leave;
+       MONO_HANDLE_SET (setup, configuration_file, config_file_name_str);
+leave:
+       return is_ok (error);
 }
 
 static MonoAppDomainSetupHandle
@@ -531,7 +558,7 @@ copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoE
        MonoClass *ads_class;
        MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL);
 
-       mono_error_init (error);
+       error_init (error);
 
        caller_domain = mono_domain_get ();
        ads_class = mono_class_load_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
@@ -595,7 +622,7 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHa
        MonoClass *adclass;
        MonoDomain *data;
 
-       mono_error_init (error);
+       error_init (error);
 
        adclass = mono_class_get_appdomain_class ();
 
@@ -609,7 +636,7 @@ mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHa
        data->domain = MONO_HANDLE_RAW (ad);
        data->friendly_name = g_strdup (friendly_name);
 
-       mono_profiler_appdomain_name (data, data->friendly_name);
+       MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name));
 
        MonoStringHandle app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base);
        if (MONO_HANDLE_IS_NULL (app_base)) {
@@ -663,10 +690,9 @@ leave:
 
 /**
  * mono_domain_has_type_resolve:
- * @domain: application domains being looked up
+ * \param domain application domain being looked up
  *
- * Returns: TRUE if the AppDomain.TypeResolve field has been
- * set.
+ * \returns TRUE if the \c AppDomain.TypeResolve field has been set.
  */
 gboolean
 mono_domain_has_type_resolve (MonoDomain *domain)
@@ -689,16 +715,16 @@ mono_domain_has_type_resolve (MonoDomain *domain)
 
 /**
  * mono_domain_try_type_resolve:
- * @domain: application domainwhere the name where the type is going to be resolved
- * @name: the name of the type to resolve or NULL.
- * @tb: A System.Reflection.Emit.TypeBuilder, used if name is NULL.
+ * \param domain application domainwhere the name where the type is going to be resolved
+ * \param name the name of the type to resolve or NULL.
+ * \param tb A \c System.Reflection.Emit.TypeBuilder, used if name is NULL.
  *
- * This routine invokes the internal System.AppDomain.DoTypeResolve and returns
+ * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
  * the assembly that matches name.
  *
- * If @name is null, the value of ((TypeBuilder)tb).FullName is used instead
+ * If \p name is null, the value of \c ((TypeBuilder)tb).FullName is used instead
  *
- * Returns: A MonoReflectionAssembly or NULL if not found
+ * \returns A \c MonoReflectionAssembly or NULL if not found
  */
 MonoReflectionAssembly *
 mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *tb)
@@ -717,7 +743,7 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject
        MonoReflectionAssembly *ret;
        void *params [1];
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (domain != NULL && ((name != NULL) || (tb != NULL)));
 
@@ -729,9 +755,10 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject
                }
        }
 
-       if (name)
-               *params = (MonoObject*)mono_string_new (mono_domain_get (), name);
-       else
+       if (name) {
+               *params = (MonoObject*)mono_string_new_checked (mono_domain_get (), name, error);
+               return_val_if_nok (error, NULL);
+       } else
                *params = tb;
 
        ret = (MonoReflectionAssembly *) mono_runtime_invoke_checked (method, domain->domain, params, error);
@@ -742,8 +769,7 @@ mono_domain_try_type_resolve_checked (MonoDomain *domain, char *name, MonoObject
 
 /**
  * mono_domain_owns_vtable_slot:
- *
- *  Returns whenever VTABLE_SLOT is inside a vtable which belongs to DOMAIN.
+ * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain.
  */
 gboolean
 mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
@@ -758,15 +784,13 @@ mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
 
 /**
  * mono_domain_set:
- * @domain: domain
- * @force: force setting.
+ * \param domain domain
+ * \param force force setting.
  *
- * Set the current appdomain to @domain. If @force is set, set it even
+ * Set the current appdomain to \p domain. If \p force is set, set it even
  * if it is being unloaded.
  *
- * Returns:
- *   TRUE on success;
- *   FALSE if the domain is unloaded
+ * \returns TRUE on success; FALSE if the domain is unloaded
  */
 gboolean
 mono_domain_set (MonoDomain *domain, gboolean force)
@@ -782,7 +806,7 @@ mono_domain_set (MonoDomain *domain, gboolean force)
 MonoObjectHandle
 ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        if (MONO_HANDLE_IS_NULL (name)) {
                mono_error_set_argument_null (error, "name", "");
@@ -830,7 +854,7 @@ ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle nam
 void
 ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        if (MONO_HANDLE_IS_NULL (name)) {
                mono_error_set_argument_null (error, "name", "");
@@ -851,7 +875,7 @@ ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle nam
 MonoAppDomainSetupHandle
 ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        g_assert (!MONO_HANDLE_IS_NULL (ad));
        MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
        g_assert (domain);
@@ -862,7 +886,7 @@ ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error)
 MonoStringHandle
 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        g_assert (!MONO_HANDLE_IS_NULL (ad));
        MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
        g_assert (domain);
@@ -873,7 +897,7 @@ ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *e
 MonoAppDomainHandle
 ves_icall_System_AppDomain_getCurDomain (MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *add = mono_domain_get ();
 
        return MONO_HANDLE_NEW (MonoAppDomain, add->domain);
@@ -882,7 +906,7 @@ ves_icall_System_AppDomain_getCurDomain (MonoError *error)
 MonoAppDomainHandle
 ves_icall_System_AppDomain_getRootDomain (MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *root = mono_get_root_domain ();
 
        return MONO_HANDLE_NEW (MonoAppDomain, root->domain);
@@ -1038,7 +1062,7 @@ mono_domain_set_options_from_config (MonoDomain *domain)
 MonoAppDomainHandle
 ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL);
 
 #ifdef DISABLE_APPDOMAINS
@@ -1058,7 +1082,7 @@ static gboolean
 add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error)
 {
        HANDLE_FUNCTION_ENTER ();
-       mono_error_init (error);
+       error_init (error);
        MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error);
        if (!is_ok (error))
                goto leave;
@@ -1070,7 +1094,7 @@ leave:
 MonoArrayHandle
 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
        MonoAssembly* ass;
        GSList *tmp;
@@ -1111,7 +1135,7 @@ MonoAssembly*
 mono_try_assembly_resolve (MonoDomain *domain, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error)
 {
        HANDLE_FUNCTION_ENTER ();
-       mono_error_init (error);
+       error_init (error);
        MonoAssembly *result = NULL;
        MonoStringHandle fname = mono_string_new_handle (domain, fname_raw, error);
        if (!is_ok (error))
@@ -1124,15 +1148,16 @@ leave:
 MonoAssembly*
 mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, MonoAssembly *requesting, gboolean refonly, MonoError *error)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoAssembly *ret = NULL;
        MonoMethod *method;
        MonoBoolean isrefonly;
        gpointer params [3];
 
-       mono_error_init (error);
+       error_init (error);
 
        if (mono_runtime_get_no_exec ())
-               return ret;
+               goto leave;
 
        g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname));
 
@@ -1143,14 +1168,29 @@ mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, Mo
        MonoReflectionAssemblyHandle requesting_handle;
        if (requesting) {
                requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
-               return_val_if_nok (error, ret);
+               if (!is_ok (error))
+                       goto leave;
        }
        params [0] = MONO_HANDLE_RAW (fname);
        params[1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
        params [2] = &isrefonly;
-       MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_invoke_checked (method, domain->domain, params, error));
+       MonoObject *exc = NULL;
+       MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_try_invoke (method, domain->domain, params, &exc, error));
+       if (!is_ok (error) || exc != NULL) {
+               if (is_ok (error))
+                       mono_error_set_exception_instance (error, (MonoException*)exc);
+               goto leave;
+       }
        ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL;
-       return ret;
+
+       if (ret && !refonly && ret->ref_only) {
+               /* .NET Framework throws System.IO.FileNotFoundException in this case */
+               mono_error_set_file_not_found (error, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only");
+               ret = NULL;
+               goto leave;
+       }
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (ret);
 }
 
 MonoAssembly *
@@ -1189,12 +1229,13 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
        if (!ht) {
                ht = g_hash_table_new (mono_aligned_addr_hash, NULL);
                destroy_ht = TRUE;
+               for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
+                       g_hash_table_insert (ht, tmp->data, tmp->data);
+               }
        }
 
        /* FIXME: handle lazy loaded assemblies */
-       for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
-               g_hash_table_insert (ht, tmp->data, tmp->data);
-       }
+
        if (!g_hash_table_lookup (ht, ass)) {
                mono_assembly_addref (ass);
                g_hash_table_insert (ht, ass, ass);
@@ -1203,11 +1244,12 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
        }
 
        if (ass->image->references) {
-               for (i = 0; ass->image->references [i] != NULL; i++) {
-                       if (ass->image->references [i] != REFERENCE_MISSING)
+               for (i = 0; i < ass->image->nreferences; i++) {
+                       if (ass->image->references[i] && ass->image->references [i] != REFERENCE_MISSING) {
                                if (!g_hash_table_lookup (ht, ass->image->references [i])) {
                                        add_assemblies_to_domain (domain, ass->image->references [i], ht);
                                }
+                       }
                }
        }
        if (destroy_ht)
@@ -1217,6 +1259,7 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
 static void
 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 {
+       HANDLE_FUNCTION_ENTER ();
        static MonoClassField *assembly_load_field;
        static MonoMethod *assembly_load_method;
        MonoError error;
@@ -1227,7 +1270,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 
        if (!domain->domain)
                /* This can happen during startup */
-               return;
+               goto leave;
 #ifdef ASSEMBLY_LOAD_DEBUG
        fprintf (stderr, "Loading %s into domain %s\n", assembly->aname.name, domain->friendly_name);
 #endif
@@ -1245,7 +1288,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
        mono_field_get_value ((MonoObject*) domain->domain, assembly_load_field, &load_value);
        if (load_value == NULL) {
                /* No events waiting to be triggered */
-               return;
+               goto leave;
        }
 
        MonoReflectionAssemblyHandle ref_assembly = mono_assembly_get_object_handle (domain, assembly, &error);
@@ -1260,6 +1303,8 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 
        mono_runtime_invoke_checked (assembly_load_method, domain->domain, params, &error);
        mono_error_cleanup (&error);
+leave:
+       HANDLE_FUNCTION_RETURN ();
 }
 
 /*
@@ -1455,7 +1500,7 @@ mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name)
 char *
 mono_make_shadow_copy (const char *filename, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        return (char *) filename;
 }
 #else
@@ -1530,7 +1575,7 @@ get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error)
        char *userdir;
        char *location;
 
-       mono_error_init (error);
+       error_init (error);
        
        setup = domain->setup;
        if (setup->cache_path != NULL && setup->application_name != NULL) {
@@ -1574,7 +1619,7 @@ get_shadow_assembly_location (const char *filename, MonoError *error)
        char *location, *tmploc;
        MonoDomain *domain = mono_domain_get ();
 
-       mono_error_init (error);
+       error_init (error);
        
        hash = get_cstring_hash (bname);
        hash2 = get_cstring_hash (dirname);
@@ -1759,7 +1804,7 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        char *shadow_dir;
        gint32 copy_error;
 
-       mono_error_init (oerror);
+       error_init (oerror);
 
        set_domain_search_path (domain);
 
@@ -1840,8 +1885,10 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
        sibling_source_len = strlen (sibling_source);
        sibling_target = g_strconcat (shadow, ".config", NULL);
        sibling_target_len = strlen (sibling_target);
-       
+
        copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".mdb", sibling_target, sibling_target_len, 7);
+       if (copy_result)
+               copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".pdb", sibling_target, sibling_target_len, 11);
        if (copy_result)
                copy_result = shadow_copy_sibling (sibling_source, sibling_source_len, ".config", sibling_target, sibling_target_len, 7);
        
@@ -1869,6 +1916,9 @@ mono_make_shadow_copy (const char *filename, MonoError *oerror)
 }
 #endif /* DISABLE_SHADOW_COPY */
 
+/**
+ * mono_domain_from_appdomain:
+ */
 MonoDomain *
 mono_domain_from_appdomain (MonoAppDomain *appdomain_raw)
 {
@@ -1900,9 +1950,11 @@ leave:
 
 
 static gboolean
-try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2,
-                                       const gchar *path3, const gchar *path4,
-                                       gboolean refonly, gboolean is_private)
+try_load_from (MonoAssembly **assembly,
+              const gchar *path1, const gchar *path2,
+              const gchar *path3, const gchar *path4,
+              gboolean refonly, gboolean is_private,
+              MonoAssemblyCandidatePredicate predicate, gpointer user_data)
 {
        gchar *fullpath;
        gboolean found = FALSE;
@@ -1921,14 +1973,14 @@ try_load_from (MonoAssembly **assembly, const gchar *path1, const gchar *path2,
                found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR);
        
        if (found)
-               *assembly = mono_assembly_open_full (fullpath, NULL, refonly);
+               *assembly = mono_assembly_open_predicate (fullpath, refonly, FALSE, predicate, user_data, NULL);
 
        g_free (fullpath);
        return (*assembly != NULL);
 }
 
 static MonoAssembly *
-real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolean refonly)
+real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolean refonly, MonoAssemblyCandidatePredicate predicate, gpointer user_data)
 {
        MonoAssembly *result = NULL;
        gchar **path;
@@ -1955,22 +2007,22 @@ real_load (gchar **search_path, const gchar *culture, const gchar *name, gboolea
                /* See test cases in bug #58992 and bug #57710 */
                /* 1st try: [culture]/[name].dll (culture may be empty) */
                strcpy (filename + len - 4, ".dll");
-               if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private))
+               if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private, predicate, user_data))
                        break;
 
                /* 2nd try: [culture]/[name].exe (culture may be empty) */
                strcpy (filename + len - 4, ".exe");
-               if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private))
+               if (try_load_from (&result, *path, local_culture, "", filename, refonly, is_private, predicate, user_data))
                        break;
 
                /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
                strcpy (filename + len - 4, ".dll");
-               if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private))
+               if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private, predicate, user_data))
                        break;
 
                /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
                strcpy (filename + len - 4, ".exe");
-               if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private))
+               if (try_load_from (&result, *path, local_culture, name, filename, refonly, is_private, predicate, user_data))
                        break;
        }
 
@@ -1995,12 +2047,28 @@ mono_domain_assembly_preload (MonoAssemblyName *aname,
 
        set_domain_search_path (domain);
 
+       MonoAssemblyCandidatePredicate predicate = NULL;
+       void* predicate_ud = NULL;
+#if !defined(DISABLE_DESKTOP_LOADER)
+       if (G_LIKELY (mono_loader_get_strict_strong_names ())) {
+               predicate = &mono_assembly_candidate_predicate_sn_same_name;
+               predicate_ud = aname;
+       }
+#endif
        if (domain->search_path && domain->search_path [0] != NULL) {
-               result = real_load (domain->search_path, aname->culture, aname->name, refonly);
+               if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s search path is:", domain->friendly_name);
+                       for (int i = 0; domain->search_path [i]; i++) {
+                               const char *p = domain->search_path[i];
+                               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "\tpath[%d] = '%s'", i, p);
+                       }
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "End of domain %s search path.", domain->friendly_name);                    
+               }
+               result = real_load (domain->search_path, aname->culture, aname->name, refonly, predicate, predicate_ud);
        }
 
        if (result == NULL && assemblies_path && assemblies_path [0] != NULL) {
-               result = real_load (assemblies_path, aname->culture, aname->name, refonly);
+               result = real_load (assemblies_path, aname->culture, aname->name, refonly, predicate, predicate_ud);
        }
 
        return result;
@@ -2036,7 +2104,7 @@ mono_domain_assembly_search (MonoAssemblyName *aname,
 MonoReflectionAssemblyHandle
 ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoolean refOnly, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = mono_domain_get ();
        char *name, *filename;
        MonoImageOpenStatus status = MONO_IMAGE_OK;
@@ -2054,7 +2122,7 @@ ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoole
        if (!is_ok (error))
                goto leave;
        
-       MonoAssembly *ass = mono_assembly_open_full (filename, &status, refOnly);
+       MonoAssembly *ass = mono_assembly_open_predicate (filename, refOnly, TRUE, NULL, NULL, &status);
        
        if (!ass) {
                if (status == MONO_IMAGE_IMAGE_INVALID)
@@ -2078,7 +2146,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad,
                                            MonoBoolean refonly,
                                            MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoAssembly *ass;
        MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
        MonoDomain *domain = MONO_HANDLE_GETVAL(ad, data);
@@ -2130,7 +2198,7 @@ ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad,
 MonoReflectionAssemblyHandle
 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoStringHandle assRef, MonoObjectHandle evidence, MonoBoolean refOnly, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
        MonoImageOpenStatus status = MONO_IMAGE_OK;
        MonoAssembly *ass;
@@ -2191,7 +2259,7 @@ fail:
 void
 ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain * domain = mono_domain_get_by_id (domain_id);
 
        if (NULL == domain) {
@@ -2208,11 +2276,8 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
         * Unloading seems to cause problems when running NUnit/NAnt, hence
         * this workaround.
         */
-       if (g_getenv ("MONO_NO_UNLOAD"))
+       if (g_hasenv ("MONO_NO_UNLOAD"))
                return;
-#ifdef __native_client__
-       return;
-#endif
 
        MonoException *exc = NULL;
        mono_domain_try_unload (domain, (MonoObject**)&exc);
@@ -2223,7 +2288,7 @@ ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
 gboolean
 ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = mono_domain_get_by_id (domain_id);
 
        if (!domain)
@@ -2233,9 +2298,11 @@ ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, Mono
 }
 
 void
-ves_icall_System_AppDomain_DoUnhandledException (MonoException *exc)
+ves_icall_System_AppDomain_DoUnhandledException (MonoExceptionHandle exc, MonoError *error)
 {
-       mono_unhandled_exception ((MonoObject*) exc);
+       error_init (error);
+       mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject, exc), error);
+       mono_error_assert_ok (error);
 }
 
 gint32
@@ -2243,7 +2310,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad,
                                            MonoReflectionAssemblyHandle refass, MonoArrayHandle args,
                                            MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoImage *image;
        MonoMethod *method;
 
@@ -2276,7 +2343,7 @@ ves_icall_System_AppDomain_GetIDFromDomain (MonoAppDomain * ad)
 MonoAppDomainHandle
 ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *old_domain = mono_domain_get ();
 
        if (!mono_domain_set (MONO_HANDLE_GETVAL (ad, data), FALSE)) {
@@ -2304,14 +2371,14 @@ ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *er
 void
 ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data));
 }
 
 void
 ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain *domain = mono_domain_get_by_id (domain_id);
 
        if (!domain) {
@@ -2329,28 +2396,31 @@ ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoErro
 void
 ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        mono_thread_pop_appdomain_ref ();
 }
 
-MonoAppContext * 
-ves_icall_System_AppDomain_InternalGetContext ()
+MonoAppContextHandle
+ves_icall_System_AppDomain_InternalGetContext (MonoError *error)
 {
-       return mono_context_get ();
+       error_init (error);
+       return mono_context_get_handle ();
 }
 
-MonoAppContext * 
-ves_icall_System_AppDomain_InternalGetDefaultContext ()
+MonoAppContextHandle
+ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError *error)
 {
-       return mono_domain_get ()->default_context;
+       error_init (error);
+       return MONO_HANDLE_NEW (MonoAppContext, mono_domain_get ()->default_context);
 }
 
-MonoAppContext * 
-ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc)
+MonoAppContextHandle
+ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc, MonoError *error)
 {
-       MonoAppContext *old_context = mono_context_get ();
+       error_init (error);
+       MonoAppContextHandle old_context = mono_context_get_handle ();
 
-       mono_context_set (mc);
+       mono_context_set_handle (mc);
 
        return old_context;
 }
@@ -2358,7 +2428,7 @@ ves_icall_System_AppDomain_InternalSetContext (MonoAppContext *mc)
 MonoStringHandle
 ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
        MonoDomain* mono_root_domain = mono_get_root_domain ();
        mono_domain_lock (mono_root_domain);
        if (process_guid_set) {
@@ -2373,6 +2443,9 @@ ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, Mon
        return newguid;
 }
 
+/**
+ * mono_domain_is_unloading:
+ */
 gboolean
 mono_domain_is_unloading (MonoDomain *domain)
 {
@@ -2479,14 +2552,14 @@ unload_thread_main (void *arg)
        MonoError error;
        unload_data *data = (unload_data*)arg;
        MonoDomain *domain = data->domain;
-       MonoThread *thread;
+       MonoInternalThread *internal;
        int i;
 
-       /* Have to attach to the runtime so shutdown can wait for this thread */
-       /* Force it to be attached to avoid racing during shutdown. */
-       thread = mono_thread_attach_full (mono_get_root_domain (), TRUE);
+       internal = mono_thread_internal_current ();
 
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Domain unloader"), TRUE, FALSE, &error);
+       MonoString *thread_name_str = mono_string_new_checked (mono_domain_get (), "Domain unloader", &error);
+       if (is_ok (&error))
+               mono_thread_set_name_internal (internal, thread_name_str, TRUE, FALSE, &error);
        if (!is_ok (&error)) {
                data->failure_reason = g_strdup (mono_error_get_message (&error));
                mono_error_cleanup (&error);
@@ -2520,7 +2593,6 @@ unload_thread_main (void *arg)
 
        mono_loader_lock (); //FIXME why do we need the loader lock here?
        mono_domain_lock (domain);
-#ifdef HAVE_SGEN_GC
        /*
         * We need to make sure that we don't have any remsets
         * pointing into static data of the to-be-freed domain because
@@ -2533,7 +2605,6 @@ unload_thread_main (void *arg)
        for (i = 0; i < domain->class_vtable_array->len; ++i)
                zero_static_data ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i));
        mono_gc_collect (0);
-#endif
        for (i = 0; i < domain->class_vtable_array->len; ++i)
                clear_cached_vtable ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i));
        deregister_reflection_info_roots (domain);
@@ -2543,8 +2614,6 @@ unload_thread_main (void *arg)
        mono_domain_unlock (domain);
        mono_loader_unlock ();
 
-       mono_threads_clear_cached_culture (domain);
-
        domain->state = MONO_APPDOMAIN_UNLOADED;
 
        /* printf ("UNLOADED %s.\n", domain->friendly_name); */
@@ -2558,22 +2627,20 @@ unload_thread_main (void *arg)
 
        mono_atomic_store_release (&data->done, TRUE);
        unload_data_unref (data);
-       mono_thread_detach (thread);
        return 0;
 
 failure:
        mono_atomic_store_release (&data->done, TRUE);
        unload_data_unref (data);
-       mono_thread_detach (thread);
        return 1;
 }
 
-/*
+/**
  * mono_domain_unload:
- * @domain: The domain to unload
+ * \param domain The domain to unload
  *
- *  Unloads an appdomain. Follows the process outlined in the comment
- *  for mono_domain_try_unload.
+ * Unloads an appdomain. Follows the process outlined in the comment
+ * for \c mono_domain_try_unload.
  */
 void
 mono_domain_unload (MonoDomain *domain)
@@ -2594,10 +2661,10 @@ guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertab
        return result;
 }
 
-/*
+/**
  * mono_domain_unload:
- * @domain: The domain to unload
- * @exc: Exception information
+ * \param domain The domain to unload
+ * \param exc Exception information
  *
  *  Unloads an appdomain. Follows the process outlined in:
  *  http://blogs.gotdotnet.com/cbrumme
@@ -2621,7 +2688,7 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
        MonoAppDomainState prev_state;
        MonoMethod *method;
        unload_data *thread_data;
-       MonoNativeThreadId tid;
+       MonoInternalThread *internal;
        MonoDomain *caller_domain = mono_domain_get ();
 
        /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
@@ -2678,10 +2745,15 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
        /* 
         * First we create a separate thread for unloading, since
         * we might have to abort some threads, including the current one.
+        *
+        * Have to attach to the runtime so shutdown can wait for this thread.
+        *
+        * Force it to be attached to avoid racing during shutdown.
         */
-       thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, NULL, &tid);
-       if (thread_handle == NULL)
-               return;
+       internal = mono_thread_create_internal (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, &error);
+       mono_error_assert_ok (&error);
+
+       thread_handle = mono_threads_open_thread_handle (internal->handle);
 
        /* Wait for the thread */       
        while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {