6 * Dietmar Maurer (dietmar@ximian.com)
8 * Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2012 Xamarin Inc
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #undef ASSEMBLY_LOAD_DEBUG
21 #include <sys/types.h>
23 #ifdef HAVE_SYS_TIME_H
32 #ifdef HAVE_SYS_UTIME_H
33 #include <sys/utime.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/appdomain-icalls.h>
40 #include <mono/metadata/class-init.h>
41 #include <mono/metadata/domain-internals.h>
42 #include "mono/metadata/metadata-internals.h"
43 #include <mono/metadata/assembly-internals.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/exception-internals.h>
46 #include <mono/metadata/threads.h>
47 #include <mono/metadata/threadpool.h>
48 #include <mono/metadata/tabledefs.h>
49 #include <mono/metadata/mono-gc.h>
50 #include <mono/metadata/mono-hash-internals.h>
51 #include <mono/metadata/marshal.h>
52 #include <mono/metadata/marshal-internals.h>
53 #include <mono/metadata/monitor.h>
54 #include <mono/metadata/mono-debug.h>
55 #include <mono/metadata/attach.h>
56 #include <mono/metadata/w32file.h>
57 #include <mono/metadata/lock-tracer.h>
58 #include <mono/metadata/console-io.h>
59 #include <mono/metadata/threads-types.h>
60 #include <mono/metadata/tokentype.h>
61 #include <mono/metadata/profiler-private.h>
62 #include <mono/metadata/reflection-internals.h>
63 #include <mono/metadata/abi-details.h>
64 #include <mono/metadata/w32socket.h>
65 #include <mono/utils/mono-uri.h>
66 #include <mono/utils/mono-logger-internals.h>
67 #include <mono/utils/mono-path.h>
68 #include <mono/utils/mono-stdlib.h>
69 #include <mono/utils/mono-io-portability.h>
70 #include <mono/utils/mono-error-internals.h>
71 #include <mono/utils/atomic.h>
72 #include <mono/utils/mono-memory-model.h>
73 #include <mono/utils/mono-threads.h>
74 #include <mono/metadata/w32handle.h>
75 #include <mono/metadata/w32error.h>
76 #include <mono/utils/w32api.h>
80 #include "object-internals.h"
81 #include "icall-decl.h"
86 int assemblybinding_count
;
91 #ifndef ENABLE_NETCORE
92 static gunichar2 process_guid
[36];
93 static gboolean process_guid_set
= FALSE
;
96 static gboolean no_exec
= FALSE
;
99 static int n_appctx_props
;
100 static char **appctx_keys
;
101 static char **appctx_values
;
105 mono_check_corlib_version_internal (void);
107 static MonoAssembly
*
108 mono_domain_assembly_preload (MonoAssemblyLoadContext
*alc
,
109 MonoAssemblyName
*aname
,
110 gchar
**assemblies_path
,
115 static MonoAssembly
*
116 mono_domain_assembly_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
117 MonoAssemblyName
*aname
,
125 mono_domain_fire_assembly_load (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error_out
);
128 mono_domain_asmctx_from_path (const char *fname
, MonoAssembly
*requesting_assembly
, gpointer user_data
, MonoAssemblyContextKind
*out_asmctx
);
131 add_assemblies_to_domain (MonoDomain
*domain
, MonoAssembly
*ass
, GHashTable
*hash
);
134 add_assembly_to_alc (MonoAssemblyLoadContext
*alc
, MonoAssembly
*ass
);
136 static MonoAppDomainHandle
137 mono_domain_create_appdomain_internal (char *friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
);
140 mono_domain_create_appdomain_checked (char *friendly_name
, char *configuration_file
, MonoError
*error
);
144 mono_context_set_default_context (MonoDomain
*domain
);
147 get_shadow_assembly_location_base (MonoDomain
*domain
, MonoError
*error
);
149 static MonoLoadFunc load_function
= NULL
;
151 /* Lazy class loading functions */
152 static GENERATE_GET_CLASS_WITH_CACHE (assembly
, "System.Reflection", "Assembly");
154 GENERATE_GET_CLASS_WITH_CACHE (appdomain
, MONO_APPDOMAIN_CLASS_NAME_SPACE
, MONO_APPDOMAIN_CLASS_NAME
);
155 GENERATE_GET_CLASS_WITH_CACHE (appdomain_setup
, MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE
, MONO_APPDOMAIN_SETUP_CLASS_NAME
);
158 mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain
);
161 mono_error_set_appdomain_unloaded (MonoError
*error
)
163 mono_error_set_generic_error (error
, "System", "AppDomainUnloadedException", "");
167 mono_install_runtime_load (MonoLoadFunc func
)
169 load_function
= func
;
173 mono_runtime_load (const char *filename
, const char *runtime_version
)
175 g_assert (load_function
);
176 return load_function (filename
, runtime_version
);
180 * mono_runtime_set_no_exec:
182 * Instructs the runtime to operate in static mode, i.e. avoid/do not
183 * allow managed code execution. This is useful for running the AOT
184 * compiler on platforms which allow full-aot execution only. This
185 * should be called before mono_runtime_init ().
188 mono_runtime_set_no_exec (gboolean val
)
194 * mono_runtime_get_no_exec:
196 * If true, then the runtime will not allow managed code execution.
199 mono_runtime_get_no_exec (void)
205 create_domain_objects (MonoDomain
*domain
)
207 HANDLE_FUNCTION_ENTER ();
210 MonoDomain
*old_domain
= mono_domain_get ();
211 MonoStringHandle arg
;
212 MonoVTable
*string_vt
;
213 MonoClassField
*string_empty_fld
;
215 if (domain
!= old_domain
) {
216 mono_thread_push_appdomain_ref (domain
);
217 mono_domain_set_internal_with_options (domain
, FALSE
);
221 * Initialize String.Empty. This enables the removal of
222 * the static cctor of the String class.
224 string_vt
= mono_class_vtable_checked (domain
, mono_defaults
.string_class
, error
);
225 mono_error_assert_ok (error
);
226 string_empty_fld
= mono_class_get_field_from_name_full (mono_defaults
.string_class
, "Empty", NULL
);
227 g_assert (string_empty_fld
);
228 MonoStringHandle empty_str
= mono_string_new_handle (domain
, "", error
);
229 mono_error_assert_ok (error
);
230 empty_str
= mono_string_intern_checked (empty_str
, error
);
231 mono_error_assert_ok (error
);
232 mono_field_static_set_value_internal (string_vt
, string_empty_fld
, MONO_HANDLE_RAW (empty_str
));
233 domain
->empty_string
= MONO_HANDLE_RAW (empty_str
);
236 * Create an instance early since we can't do it when there is no memory.
238 arg
= mono_string_new_handle (domain
, "Out of memory", error
);
239 mono_error_assert_ok (error
);
240 domain
->out_of_memory_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "OutOfMemoryException", arg
, NULL_HANDLE_STRING
, error
));
241 mono_error_assert_ok (error
);
244 * These two are needed because the signal handlers might be executing on
245 * an alternate stack, and Boehm GC can't handle that.
247 arg
= mono_string_new_handle (domain
, "A null value was found where an object instance was required", error
);
248 mono_error_assert_ok (error
);
249 domain
->null_reference_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "NullReferenceException", arg
, NULL_HANDLE_STRING
, error
));
250 mono_error_assert_ok (error
);
251 arg
= mono_string_new_handle (domain
, "The requested operation caused a stack overflow.", error
);
252 mono_error_assert_ok (error
);
253 domain
->stack_overflow_ex
= MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults
.corlib
, "System", "StackOverflowException", arg
, NULL_HANDLE_STRING
, error
));
254 mono_error_assert_ok (error
);
256 /*The ephemeron tombstone i*/
257 domain
->ephemeron_tombstone
= MONO_HANDLE_RAW (mono_object_new_handle (domain
, mono_defaults
.object_class
, error
));
258 mono_error_assert_ok (error
);
260 if (domain
!= old_domain
) {
261 mono_thread_pop_appdomain_ref ();
262 mono_domain_set_internal_with_options (old_domain
, FALSE
);
266 * This class is used during exception handling, so initialize it here, to prevent
267 * stack overflows while handling stack overflows.
269 mono_class_init_internal (mono_class_create_array (mono_defaults
.int_class
, 1));
270 HANDLE_FUNCTION_RETURN ();
275 * \param domain domain returned by \c mono_init
277 * Initialize the core AppDomain: this function will run also some
278 * IL initialization code, so it needs the execution engine to be fully
281 * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where
282 * we know the \c entry_assembly.
286 mono_runtime_init (MonoDomain
*domain
, MonoThreadStartCB start_cb
, MonoThreadAttachCB attach_cb
)
289 mono_runtime_init_checked (domain
, start_cb
, attach_cb
, error
);
290 mono_error_cleanup (error
);
294 mono_runtime_init_checked (MonoDomain
*domain
, MonoThreadStartCB start_cb
, MonoThreadAttachCB attach_cb
, MonoError
*error
)
296 HANDLE_FUNCTION_ENTER ();
298 MonoAppDomainSetupHandle setup
;
299 MonoAppDomainHandle ad
;
303 mono_portability_helpers_init ();
305 mono_gc_base_init ();
306 mono_monitor_init ();
307 mono_marshal_init ();
308 mono_gc_init_icalls ();
310 mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload
, GUINT_TO_POINTER (FALSE
), FALSE
);
311 mono_install_assembly_search_hook_v2 (mono_domain_assembly_search
, GUINT_TO_POINTER (FALSE
), FALSE
, FALSE
);
312 mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search
, GUINT_TO_POINTER (FALSE
), FALSE
, TRUE
);
313 mono_install_assembly_load_hook_v2 (mono_domain_fire_assembly_load
, NULL
);
315 #ifndef ENABLE_NETCORE // refonly hooks
316 mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload
, GUINT_TO_POINTER (TRUE
), TRUE
);
317 mono_install_assembly_search_hook_v2 (mono_domain_assembly_search
, GUINT_TO_POINTER (TRUE
), TRUE
, FALSE
);
318 mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search
, GUINT_TO_POINTER (TRUE
), TRUE
, TRUE
);
319 mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path
, NULL
);
322 mono_thread_init (start_cb
, attach_cb
);
324 if (!mono_runtime_get_no_exec ()) {
325 MonoClass
*klass
= mono_class_get_appdomain_setup_class ();
326 setup
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_pinned_handle (domain
, klass
, error
));
327 goto_if_nok (error
, exit
);
329 klass
= mono_class_get_appdomain_class ();
331 ad
= MONO_HANDLE_CAST (MonoAppDomain
, mono_object_new_pinned_handle (domain
, klass
, error
));
332 goto_if_nok (error
, exit
);
334 MONO_HANDLE_SETVAL (ad
, data
, MonoDomain
*, domain
);
335 domain
->domain
= MONO_HANDLE_RAW (ad
);
336 domain
->setup
= MONO_HANDLE_RAW (setup
);
339 mono_thread_attach (domain
);
341 mono_type_initialization_init ();
343 if (!mono_runtime_get_no_exec ())
344 create_domain_objects (domain
);
346 /* GC init has to happen after thread init */
349 /* contexts use GC handles, so they must be initialized after the GC */
350 #ifndef ENABLE_NETCORE
351 mono_context_init_checked (domain
, error
);
352 goto_if_nok (error
, exit
);
353 mono_context_set_default_context (domain
);
356 #ifdef ENABLE_NETCORE
357 if (!mono_runtime_get_no_exec ())
358 mono_runtime_install_appctx_properties ();
361 #ifndef DISABLE_SOCKETS
362 mono_network_init ();
365 mono_console_init ();
368 mono_locks_tracer_init ();
370 /* mscorlib is loaded before we install the load hook */
371 mono_domain_fire_assembly_load (mono_domain_default_alc (domain
), mono_defaults
.corlib
->assembly
, NULL
, error
);
372 goto_if_nok (error
, exit
);
375 HANDLE_FUNCTION_RETURN ();
379 mono_context_set_default_context (MonoDomain
*domain
)
381 if (mono_runtime_get_no_exec ())
384 HANDLE_FUNCTION_ENTER ();
385 mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext
, domain
->default_context
));
386 HANDLE_FUNCTION_RETURN ();
390 mono_get_corlib_version (void)
395 MonoClassField
*field
;
397 klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System", "Environment");
398 mono_class_init_internal (klass
);
399 field
= mono_class_get_field_from_name_full (klass
, "mono_corlib_version", NULL
);
403 if (! (field
->type
->attrs
& (FIELD_ATTRIBUTE_STATIC
| FIELD_ATTRIBUTE_LITERAL
)))
407 MonoTypeEnum field_type
;
408 const char *data
= mono_class_get_field_default_value (field
, &field_type
);
409 if (field_type
!= MONO_TYPE_STRING
)
411 mono_metadata_read_constant_value (data
, field_type
, &value
, error
);
412 mono_error_assert_ok (error
);
414 char *res
= mono_string_from_blob (value
, error
);
415 mono_error_assert_ok (error
);
421 * mono_check_corlib_version:
422 * Checks that the corlib that is loaded matches the version of this runtime.
423 * \returns NULL if the runtime will work with the corlib, or a \c g_malloc
424 * allocated string with the error otherwise.
427 mono_check_corlib_version (void)
430 MONO_ENTER_GC_UNSAFE
;
431 res
= mono_check_corlib_version_internal ();
437 mono_check_corlib_version_internal (void)
439 #if defined(MONO_CROSS_COMPILE)
440 /* Can't read the corlib version because we only have the target class layouts */
445 char *version
= mono_get_corlib_version ();
447 result
= g_strdup_printf ("expected corlib string (%s) but not found or not string", MONO_CORLIB_VERSION
);
450 if (strcmp (version
, MONO_CORLIB_VERSION
) != 0) {
451 result
= g_strdup_printf ("The runtime did not find the mscorlib.dll it expected. "
452 "Expected interface version %s but found %s. Check that "
453 "your runtime and class libraries are matching.",
454 MONO_CORLIB_VERSION
, version
);
458 /* Check that the managed and unmanaged layout of MonoInternalThread matches */
459 guint32 native_offset
;
460 guint32 managed_offset
;
461 native_offset
= (guint32
) MONO_STRUCT_OFFSET (MonoInternalThread
, last
);
462 managed_offset
= mono_field_get_offset (mono_class_get_field_from_name_full (mono_defaults
.internal_thread_class
, "last", NULL
));
463 if (native_offset
!= managed_offset
)
464 result
= g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset
, managed_offset
);
472 * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized
473 * Initializes the \p domain's default \c System.Runtime.Remoting 's Context.
476 mono_context_init (MonoDomain
*domain
)
479 mono_context_init_checked (domain
, error
);
480 mono_error_cleanup (error
);
484 mono_context_init_checked (MonoDomain
*domain
, MonoError
*error
)
486 HANDLE_FUNCTION_ENTER ();
489 MonoAppContextHandle context
;
492 if (mono_runtime_get_no_exec ())
495 klass
= mono_class_load_from_name (mono_defaults
.corlib
, "System.Runtime.Remoting.Contexts", "Context");
496 context
= MONO_HANDLE_CAST (MonoAppContext
, mono_object_new_pinned_handle (domain
, klass
, error
));
497 goto_if_nok (error
, exit
);
499 MONO_HANDLE_SETVAL (context
, domain_id
, gint32
, domain
->domain_id
);
500 MONO_HANDLE_SETVAL (context
, context_id
, gint32
, 0);
501 mono_threads_register_app_context (context
, error
);
502 mono_error_assert_ok (error
);
503 domain
->default_context
= MONO_HANDLE_RAW (context
);
505 HANDLE_FUNCTION_RETURN ();
509 * mono_runtime_cleanup:
510 * \param domain unused.
514 * This must not be called while there are still running threads executing
518 mono_runtime_cleanup (MonoDomain
*domain
)
520 mono_attach_cleanup ();
522 /* This ends up calling any pending pending (for at most 2 seconds) */
525 mono_thread_cleanup ();
527 #ifndef DISABLE_SOCKETS
528 mono_network_cleanup ();
530 mono_marshal_cleanup ();
532 mono_type_initialization_cleanup ();
534 mono_monitor_cleanup ();
537 static MonoDomainFunc quit_function
= NULL
;
540 * mono_install_runtime_cleanup:
543 mono_install_runtime_cleanup (MonoDomainFunc func
)
545 quit_function
= func
;
554 if (quit_function
!= NULL
)
555 quit_function (mono_get_root_domain (), NULL
);
559 * mono_domain_create_appdomain:
560 * \param friendly_name The friendly name of the appdomain to create
561 * \param configuration_file The configuration file to initialize the appdomain with
562 * \returns a \c MonoDomain initialized with the appdomain
565 mono_domain_create_appdomain (char *friendly_name
, char *configuration_file
)
567 HANDLE_FUNCTION_ENTER ();
569 MONO_ENTER_GC_UNSAFE
;
571 domain
= mono_domain_create_appdomain_checked (friendly_name
, configuration_file
, error
);
572 mono_error_cleanup (error
);
574 HANDLE_FUNCTION_RETURN_VAL (domain
);
578 * mono_domain_create_appdomain_checked:
579 * \param friendly_name The friendly name of the appdomain to create
580 * \param configuration_file The configuration file to initialize the appdomain with
581 * \param error Set on error.
583 * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL.
586 mono_domain_create_appdomain_checked (char *friendly_name
, char *configuration_file
, MonoError
*error
)
588 HANDLE_FUNCTION_ENTER ();
590 MonoDomain
*result
= NULL
;
592 MonoClass
*klass
= mono_class_get_appdomain_setup_class ();
593 MonoAppDomainSetupHandle setup
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_handle (mono_domain_get (), klass
, error
));
594 goto_if_nok (error
, leave
);
595 MonoStringHandle config_file
;
596 if (configuration_file
!= NULL
) {
597 config_file
= mono_string_new_handle (mono_domain_get (), configuration_file
, error
);
598 goto_if_nok (error
, leave
);
600 config_file
= MONO_HANDLE_NEW (MonoString
, NULL
);
602 MONO_HANDLE_SET (setup
, configuration_file
, config_file
);
604 MonoAppDomainHandle ad
;
605 ad
= mono_domain_create_appdomain_internal (friendly_name
, setup
, error
);
606 goto_if_nok (error
, leave
);
608 result
= mono_domain_from_appdomain_handle (ad
);
610 HANDLE_FUNCTION_RETURN_VAL (result
);
614 * mono_domain_set_config:
615 * \param domain \c MonoDomain initialized with the appdomain we want to change
616 * \param base_dir new base directory for the appdomain
617 * \param config_file_name path to the new configuration for the app domain
619 * Used to set the system configuration for an appdomain
621 * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException:
622 * Error Initializing the configuration system. ---> System.ArgumentException:
623 * The 'ExeConfigFilename' argument cannot be null.' for some managed calls.
626 mono_domain_set_config (MonoDomain
*domain
, const char *base_dir
, const char *config_file_name
)
628 HANDLE_FUNCTION_ENTER ();
629 MONO_ENTER_GC_UNSAFE
;
631 mono_domain_set_config_checked (domain
, base_dir
, config_file_name
, error
);
632 mono_error_cleanup (error
);
634 HANDLE_FUNCTION_RETURN ();
638 mono_domain_set_config_checked (MonoDomain
*domain
, const char *base_dir
, const char *config_file_name
, MonoError
*error
)
641 MonoAppDomainSetupHandle setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
642 MonoStringHandle base_dir_str
= mono_string_new_handle (domain
, base_dir
, error
);
643 goto_if_nok (error
, leave
);
644 MONO_HANDLE_SET (setup
, application_base
, base_dir_str
);
645 MonoStringHandle config_file_name_str
;
646 config_file_name_str
= mono_string_new_handle (domain
, config_file_name
, error
);
647 goto_if_nok (error
, leave
);
648 MONO_HANDLE_SET (setup
, configuration_file
, config_file_name_str
);
650 return is_ok (error
);
653 static MonoAppDomainSetupHandle
654 copy_app_domain_setup (MonoDomain
*domain
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
656 HANDLE_FUNCTION_ENTER ();
657 MonoDomain
*caller_domain
;
658 MonoClass
*ads_class
;
659 MonoAppDomainSetupHandle result
= MONO_HANDLE_NEW (MonoAppDomainSetup
, NULL
);
663 caller_domain
= mono_domain_get ();
664 ads_class
= mono_class_get_appdomain_setup_class ();
666 MonoAppDomainSetupHandle copy
= MONO_HANDLE_CAST (MonoAppDomainSetup
, mono_object_new_handle(domain
, ads_class
, error
));
667 goto_if_nok (error
, leave
);
669 mono_domain_set_internal_with_options (domain
, TRUE
);
671 #define XCOPY_FIELD(type, dst, field, src, error) \
673 TYPED_HANDLE_NAME (type) src_val = MONO_HANDLE_NEW_GET (type, (src), field); \
674 TYPED_HANDLE_NAME (type) copied_val = MONO_HANDLE_CAST (type, mono_marshal_xdomain_copy_value_handle (MONO_HANDLE_CAST (MonoObject, src_val), error)); \
675 goto_if_nok (error, leave); \
676 MONO_HANDLE_SET ((dst),field,copied_val); \
679 #define COPY_VAL(dst,field,type,src) \
681 MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \
684 XCOPY_FIELD (MonoString
, copy
, application_base
, setup
, error
);
685 XCOPY_FIELD (MonoString
, copy
, application_name
, setup
, error
);
686 XCOPY_FIELD (MonoString
, copy
, cache_path
, setup
, error
);
687 XCOPY_FIELD (MonoString
, copy
, configuration_file
, setup
, error
);
688 XCOPY_FIELD (MonoString
, copy
, dynamic_base
, setup
, error
);
689 XCOPY_FIELD (MonoString
, copy
, license_file
, setup
, error
);
690 XCOPY_FIELD (MonoString
, copy
, private_bin_path
, setup
, error
);
691 XCOPY_FIELD (MonoString
, copy
, private_bin_path_probe
, setup
, error
);
692 XCOPY_FIELD (MonoString
, copy
, shadow_copy_directories
, setup
, error
);
693 XCOPY_FIELD (MonoString
, copy
, shadow_copy_files
, setup
, error
);
694 COPY_VAL (copy
, publisher_policy
, MonoBoolean
, setup
);
695 COPY_VAL (copy
, path_changed
, MonoBoolean
, setup
);
696 COPY_VAL (copy
, loader_optimization
, int, setup
);
697 COPY_VAL (copy
, disallow_binding_redirects
, MonoBoolean
, setup
);
698 COPY_VAL (copy
, disallow_code_downloads
, MonoBoolean
, setup
);
699 XCOPY_FIELD (MonoArray
, copy
, domain_initializer_args
, setup
, error
);
700 COPY_VAL (copy
, disallow_appbase_probe
, MonoBoolean
, setup
);
701 XCOPY_FIELD (MonoObject
, copy
, application_trust
, setup
, error
);
702 XCOPY_FIELD (MonoArray
, copy
, configuration_bytes
, setup
, error
);
703 XCOPY_FIELD (MonoArray
, copy
, serialized_non_primitives
, setup
, error
);
708 mono_domain_set_internal_with_options (caller_domain
, TRUE
);
710 MONO_HANDLE_ASSIGN (result
, copy
);
712 HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup
, result
);
715 static MonoAppDomainHandle
716 mono_domain_create_appdomain_internal (char *friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
718 HANDLE_FUNCTION_ENTER ();
719 MonoAppDomainHandle result
= MONO_HANDLE_NEW (MonoAppDomain
, NULL
);
725 adclass
= mono_class_get_appdomain_class ();
727 /* FIXME: pin all those objects */
728 data
= mono_domain_create();
730 MonoAppDomainHandle ad
= MONO_HANDLE_CAST (MonoAppDomain
, mono_object_new_handle (data
, adclass
, error
));
731 goto_if_nok (error
, leave
);
732 MONO_HANDLE_SETVAL (ad
, data
, MonoDomain
*, data
);
733 data
->domain
= MONO_HANDLE_RAW (ad
);
734 data
->friendly_name
= g_strdup (friendly_name
);
736 MONO_PROFILER_RAISE (domain_name
, (data
, data
->friendly_name
));
738 MonoStringHandle app_base
;
739 app_base
= MONO_HANDLE_NEW_GET (MonoString
, setup
, application_base
);
740 if (MONO_HANDLE_IS_NULL (app_base
)) {
741 /* Inherit from the root domain since MS.NET does this */
742 MonoDomain
*root
= mono_get_root_domain ();
743 MonoAppDomainSetupHandle root_setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, root
->setup
);
744 MonoStringHandle root_app_base
= MONO_HANDLE_NEW_GET (MonoString
, root_setup
, application_base
);
745 if (!MONO_HANDLE_IS_NULL (root_app_base
)) {
746 /* N.B. new string is in the new domain */
747 uint32_t gchandle
= mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject
, root_app_base
), TRUE
);
748 MonoStringHandle s
= mono_string_new_utf16_handle (data
, mono_string_chars_internal (MONO_HANDLE_RAW (root_app_base
)), mono_string_handle_length (root_app_base
), error
);
749 mono_gchandle_free_internal (gchandle
);
750 if (!is_ok (error
)) {
751 g_free (data
->friendly_name
);
754 MONO_HANDLE_SET (setup
, application_base
, s
);
758 mono_context_init_checked (data
, error
);
759 goto_if_nok (error
, leave
);
761 data
->setup
= MONO_HANDLE_RAW (copy_app_domain_setup (data
, setup
, error
));
762 if (!is_ok (error
)) {
763 g_free (data
->friendly_name
);
767 mono_domain_set_options_from_config (data
);
768 add_assemblies_to_domain (data
, mono_defaults
.corlib
->assembly
, NULL
);
770 #ifndef DISABLE_SHADOW_COPY
771 /*FIXME, guard this for when the debugger is not running */
772 char *shadow_location
;
773 shadow_location
= get_shadow_assembly_location_base (data
, error
);
774 if (!is_ok (error
)) {
775 g_free (data
->friendly_name
);
779 g_free (shadow_location
);
782 create_domain_objects (data
);
784 MONO_HANDLE_ASSIGN (result
, ad
);
786 HANDLE_FUNCTION_RETURN_REF (MonoAppDomain
, result
);
790 * mono_domain_has_type_resolve:
791 * \param domain application domain being looked up
793 * \returns TRUE if the \c AppDomain.TypeResolve field has been set.
796 mono_domain_has_type_resolve (MonoDomain
*domain
)
798 #ifdef ENABLE_NETCORE
801 static MonoClassField
*field
= NULL
;
805 field
= mono_class_get_field_from_name_full (mono_defaults
.appdomain_class
, "TypeResolve", NULL
);
809 /*pedump doesn't create an appdomin, so the domain object doesn't exist.*/
813 mono_field_get_value_internal ((MonoObject
*)(domain
->domain
), field
, &o
);
819 * mono_domain_try_type_resolve:
820 * \param domain application domain in which to resolve the type
821 * \param name the name of the type to resolve or NULL.
822 * \param typebuilder A \c System.Reflection.Emit.TypeBuilder, used if name is NULL.
824 * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
825 * the assembly that matches name, or ((TypeBuilder)typebuilder).FullName.
827 * \returns A \c MonoReflectionAssembly or NULL if not found
829 MonoReflectionAssembly
*
830 mono_domain_try_type_resolve (MonoDomain
*domain
, char *name
, MonoObject
*typebuilder_raw
)
832 HANDLE_FUNCTION_ENTER ();
835 g_assert (name
|| typebuilder_raw
);
839 MonoReflectionAssemblyHandle ret
= NULL_HANDLE_INIT
;
842 MonoStringHandle name_handle
= mono_string_new_handle (mono_domain_get (), name
, error
);
843 goto_if_nok (error
, exit
);
844 ret
= mono_domain_try_type_resolve_name (domain
, name_handle
, error
);
846 MONO_HANDLE_DCL (MonoObject
, typebuilder
);
847 ret
= mono_domain_try_type_resolve_typebuilder (domain
, MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, typebuilder
), error
);
851 mono_error_cleanup (error
);
852 HANDLE_FUNCTION_RETURN_OBJ (ret
);
856 * mono_class_get_appdomain_do_type_resolve_method:
858 * This routine returns System.AppDomain.DoTypeResolve.
861 mono_class_get_appdomain_do_type_resolve_method (MonoError
*error
)
863 static MonoMethod
*method
; // cache
868 // not cached yet, fill cache under caller's lock
870 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeResolve", -1, 0, error
);
873 g_warning ("%s method AppDomain.DoTypeResolve not found. %s\n", __func__
, mono_error_get_message (error
));
879 * mono_class_get_appdomain_do_type_builder_resolve_method:
881 * This routine returns System.AppDomain.DoTypeBuilderResolve.
884 mono_class_get_appdomain_do_type_builder_resolve_method (MonoError
*error
)
886 static MonoMethod
*method
; // cache
891 // not cached yet, fill cache under caller's lock
893 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeBuilderResolve", -1, 0, error
);
896 g_warning ("%s method AppDomain.DoTypeBuilderResolve not found. %s\n", __func__
, mono_error_get_message (error
));
902 * mono_domain_try_type_resolve_name:
903 * \param domain application domain in which to resolve the type
904 * \param name the name of the type to resolve.
906 * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
907 * the assembly that matches name.
909 * \returns A \c MonoReflectionAssembly or NULL if not found
911 MonoReflectionAssemblyHandle
912 mono_domain_try_type_resolve_name (MonoDomain
*domain
, MonoStringHandle name
, MonoError
*error
)
914 HANDLE_FUNCTION_ENTER ();
916 void *params
[1] = { 0 };
919 g_assert (MONO_HANDLE_BOOL (name
));
925 method
= mono_class_get_appdomain_do_type_resolve_method (error
);
926 goto_if_nok (error
, return_null
);
928 MonoAppDomainHandle appdomain
;
929 appdomain
= MONO_HANDLE_NEW (MonoAppDomain
, domain
->domain
);
931 MonoObjectHandle ret
;
932 params
[0] = MONO_HANDLE_RAW (name
);
933 ret
= mono_runtime_invoke_handle (method
, MONO_HANDLE_CAST (MonoObject
, appdomain
), params
, error
);
934 goto_if_nok (error
, return_null
);
939 HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly
, MONO_HANDLE_CAST (MonoReflectionAssembly
, ret
));
943 * mono_domain_try_type_resolve_typebuilder:
944 * \param domain application domain in which to resolve the type
945 * \param typebuilder A \c System.Reflection.Emit.TypeBuilder; typebuilder.FullName is the name of the type to resolve.
947 * This routine invokes the internal \c System.AppDomain.DoTypeBuilderResolve and returns
948 * the assembly that matches typebuilder.FullName.
950 * \returns A \c MonoReflectionAssembly or NULL_HANDLE if not found
952 MonoReflectionAssemblyHandle
953 mono_domain_try_type_resolve_typebuilder (MonoDomain
*domain
, MonoReflectionTypeBuilderHandle typebuilder
, MonoError
*error
)
955 HANDLE_FUNCTION_ENTER ();
958 g_assert (MONO_HANDLE_BOOL (typebuilder
));
963 MonoMethod
* const method
= mono_class_get_appdomain_do_type_builder_resolve_method (error
);
964 goto_if_nok (error
, return_null
);
966 MonoAppDomainHandle appdomain
;
967 appdomain
= MONO_HANDLE_NEW (MonoAppDomain
, domain
->domain
);
969 args
[0] = MONO_HANDLE_RAW (typebuilder
);
971 MonoObjectHandle ret
;
972 ret
= mono_runtime_invoke_handle (method
, MONO_HANDLE_CAST (MonoObject
, appdomain
), args
, error
);
973 goto_if_nok (error
, return_null
);
978 HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly
, MONO_HANDLE_CAST (MonoReflectionAssembly
, ret
));
982 * mono_domain_owns_vtable_slot:
983 * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain.
986 mono_domain_owns_vtable_slot (MonoDomain
*domain
, gpointer vtable_slot
)
990 mono_domain_lock (domain
);
991 res
= mono_mempool_contains_addr (domain
->mp
, vtable_slot
);
992 mono_domain_unlock (domain
);
997 mono_domain_set_fast (MonoDomain
*domain
, gboolean force
)
999 MONO_REQ_GC_UNSAFE_MODE
;
1000 if (!force
&& domain
->state
== MONO_APPDOMAIN_UNLOADED
)
1003 mono_domain_set_internal_with_options (domain
, TRUE
);
1007 #ifndef ENABLE_NETCORE
1009 ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad
, MonoStringHandle name
, MonoError
*error
)
1013 if (MONO_HANDLE_IS_NULL (name
)) {
1014 mono_error_set_argument_null (error
, "name", "");
1018 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1019 MonoDomain
*add
= MONO_HANDLE_GETVAL (ad
, data
);
1022 char *str
= mono_string_handle_to_utf8 (name
, error
);
1023 return_val_if_nok (error
, NULL_HANDLE
);
1025 mono_domain_lock (add
);
1027 MonoAppDomainSetupHandle ad_setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, add
->setup
);
1029 if (!strcmp (str
, "APPBASE"))
1030 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, application_base
);
1031 else if (!strcmp (str
, "APP_CONFIG_FILE"))
1032 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, configuration_file
);
1033 else if (!strcmp (str
, "DYNAMIC_BASE"))
1034 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, dynamic_base
);
1035 else if (!strcmp (str
, "APP_NAME"))
1036 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, application_name
);
1037 else if (!strcmp (str
, "CACHE_BASE"))
1038 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, cache_path
);
1039 else if (!strcmp (str
, "PRIVATE_BINPATH"))
1040 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, private_bin_path
);
1041 else if (!strcmp (str
, "BINPATH_PROBE_ONLY"))
1042 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, private_bin_path_probe
);
1043 else if (!strcmp (str
, "SHADOW_COPY_DIRS"))
1044 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, shadow_copy_directories
);
1045 else if (!strcmp (str
, "FORCE_CACHE_INSTALL"))
1046 o
= MONO_HANDLE_NEW_GET (MonoString
, ad_setup
, shadow_copy_files
);
1048 o
= MONO_HANDLE_NEW (MonoString
, (MonoString
*)mono_g_hash_table_lookup (add
->env
, MONO_HANDLE_RAW (name
)));
1050 mono_domain_unlock (add
);
1053 return MONO_HANDLE_CAST (MonoObject
, o
);
1057 ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad
, MonoStringHandle name
, MonoObjectHandle data
, MonoError
*error
)
1061 if (MONO_HANDLE_IS_NULL (name
)) {
1062 mono_error_set_argument_null (error
, "name", "");
1066 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1067 MonoDomain
*add
= MONO_HANDLE_GETVAL (ad
, data
);
1070 mono_domain_lock (add
);
1072 mono_g_hash_table_insert_internal (add
->env
, MONO_HANDLE_RAW (name
), MONO_HANDLE_RAW (data
));
1074 mono_domain_unlock (add
);
1077 MonoAppDomainSetupHandle
1078 ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad
, MonoError
*error
)
1081 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1082 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1085 return MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
1089 ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad
, MonoError
*error
)
1092 g_assert (!MONO_HANDLE_IS_NULL (ad
));
1093 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1096 return mono_string_new_handle (domain
, domain
->friendly_name
, error
);
1100 ves_icall_System_AppDomain_getCurDomain (MonoError
*error
)
1103 MonoDomain
*add
= mono_domain_get ();
1105 return MONO_HANDLE_NEW (MonoAppDomain
, add
->domain
);
1109 ves_icall_System_AppDomain_getRootDomain (MonoError
*error
)
1112 MonoDomain
*root
= mono_get_root_domain ();
1114 return MONO_HANDLE_NEW (MonoAppDomain
, root
->domain
);
1118 ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (MonoError
*error
)
1120 MonoDomain
*domain
= mono_domain_get ();
1122 return domain
->throw_unobserved_task_exceptions
;
1127 get_attribute_value (const gchar
**attribute_names
,
1128 const gchar
**attribute_values
,
1129 const char *att_name
)
1132 for (n
= 0; attribute_names
[n
] != NULL
; n
++) {
1133 if (strcmp (attribute_names
[n
], att_name
) == 0)
1134 return g_strdup (attribute_values
[n
]);
1140 start_element (GMarkupParseContext
*context
,
1141 const gchar
*element_name
,
1142 const gchar
**attribute_names
,
1143 const gchar
**attribute_values
,
1147 RuntimeConfig
*runtime_config
= (RuntimeConfig
*)user_data
;
1149 if (strcmp (element_name
, "runtime") == 0) {
1150 runtime_config
->runtime_count
++;
1154 if (strcmp (element_name
, "assemblyBinding") == 0) {
1155 runtime_config
->assemblybinding_count
++;
1159 if (runtime_config
->runtime_count
!= 1)
1162 if (strcmp (element_name
, "ThrowUnobservedTaskExceptions") == 0) {
1163 const char *value
= get_attribute_value (attribute_names
, attribute_values
, "enabled");
1165 if (value
&& g_ascii_strcasecmp (value
, "true") == 0)
1166 runtime_config
->domain
->throw_unobserved_task_exceptions
= TRUE
;
1169 if (runtime_config
->assemblybinding_count
!= 1)
1172 if (strcmp (element_name
, "probing") != 0)
1175 g_free (runtime_config
->domain
->private_bin_path
);
1176 runtime_config
->domain
->private_bin_path
= get_attribute_value (attribute_names
, attribute_values
, "privatePath");
1177 if (runtime_config
->domain
->private_bin_path
&& !runtime_config
->domain
->private_bin_path
[0]) {
1178 g_free (runtime_config
->domain
->private_bin_path
);
1179 runtime_config
->domain
->private_bin_path
= NULL
;
1185 end_element (GMarkupParseContext
*context
,
1186 const gchar
*element_name
,
1190 RuntimeConfig
*runtime_config
= (RuntimeConfig
*)user_data
;
1191 if (strcmp (element_name
, "runtime") == 0)
1192 runtime_config
->runtime_count
--;
1193 else if (strcmp (element_name
, "assemblyBinding") == 0)
1194 runtime_config
->assemblybinding_count
--;
1198 parse_error (GMarkupParseContext
*context
, GError
*gerror
, gpointer user_data
)
1200 RuntimeConfig
*state
= (RuntimeConfig
*)user_data
;
1202 const gchar
*filename
;
1204 filename
= state
&& state
->filename
? (gchar
*) state
->filename
: "<unknown>";
1205 msg
= gerror
&& gerror
->message
? gerror
->message
: "";
1206 g_warning ("Error parsing %s: %s", filename
, msg
);
1209 static const GMarkupParser
1219 mono_domain_set_options_from_config (MonoDomain
*domain
)
1222 gchar
*config_file_name
= NULL
, *text
= NULL
, *config_file_path
= NULL
;
1224 GMarkupParseContext
*context
;
1225 RuntimeConfig runtime_config
;
1228 if (!domain
|| !domain
->setup
|| !domain
->setup
->configuration_file
)
1231 config_file_name
= mono_string_to_utf8_checked_internal (domain
->setup
->configuration_file
, error
);
1232 if (!is_ok (error
)) {
1233 mono_error_cleanup (error
);
1237 config_file_path
= mono_portability_find_file (config_file_name
, TRUE
);
1238 if (!config_file_path
)
1239 config_file_path
= config_file_name
;
1241 if (!g_file_get_contents (config_file_path
, &text
, &len
, NULL
))
1244 runtime_config
.runtime_count
= 0;
1245 runtime_config
.assemblybinding_count
= 0;
1246 runtime_config
.domain
= domain
;
1247 runtime_config
.filename
= config_file_path
;
1250 if (len
> 3 && text
[0] == '\xef' && text
[1] == (gchar
) '\xbb' && text
[2] == '\xbf')
1251 offset
= 3; /* Skip UTF-8 BOM */
1253 context
= g_markup_parse_context_new (&mono_parser
, (GMarkupParseFlags
)0, &runtime_config
, NULL
);
1254 if (g_markup_parse_context_parse (context
, text
+ offset
, len
- offset
, NULL
))
1255 g_markup_parse_context_end_parse (context
, NULL
);
1256 g_markup_parse_context_free (context
);
1260 if (config_file_name
!= config_file_path
)
1261 g_free (config_file_name
);
1262 g_free (config_file_path
);
1265 #ifndef ENABLE_NETCORE
1267 ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name
, MonoAppDomainSetupHandle setup
, MonoError
*error
)
1270 MonoAppDomainHandle ad
= MONO_HANDLE_NEW (MonoAppDomain
, NULL
);
1272 #ifdef DISABLE_APPDOMAINS
1273 mono_error_set_not_supported (error
, "AppDomain creation is not supported on this runtime.");
1277 fname
= mono_string_handle_to_utf8 (friendly_name
, error
);
1278 return_val_if_nok (error
, ad
);
1279 ad
= mono_domain_create_appdomain_internal (fname
, setup
, error
);
1287 add_assembly_to_array (MonoDomain
*domain
, MonoArrayHandle dest
, int dest_idx
, MonoAssembly
* assm
, MonoError
*error
)
1289 HANDLE_FUNCTION_ENTER ();
1291 MonoReflectionAssemblyHandle assm_obj
= mono_assembly_get_object_handle (domain
, assm
, error
);
1292 goto_if_nok (error
, leave
);
1293 MONO_HANDLE_ARRAY_SETREF (dest
, dest_idx
, assm_obj
);
1295 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
1298 static MonoArrayHandle
1299 get_assembly_array_from_domain (MonoDomain
*domain
, MonoBoolean refonly
, MonoError
*error
)
1302 GPtrArray
*assemblies
;
1304 assemblies
= mono_domain_get_assemblies (domain
, refonly
);
1306 MonoArrayHandle res
= mono_array_new_handle (domain
, mono_class_get_assembly_class (), assemblies
->len
, error
);
1307 goto_if_nok (error
, leave
);
1308 for (i
= 0; i
< assemblies
->len
; ++i
) {
1309 if (!add_assembly_to_array (domain
, res
, i
, (MonoAssembly
*)g_ptr_array_index (assemblies
, i
), error
))
1314 g_ptr_array_free (assemblies
, TRUE
);
1318 #ifdef ENABLE_NETCORE
1320 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError
*error
)
1322 MonoDomain
*domain
= mono_domain_get ();
1323 return get_assembly_array_from_domain (domain
, FALSE
, error
);
1327 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad
, MonoBoolean refonly
, MonoError
*error
)
1329 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
1330 return get_assembly_array_from_domain (domain
, refonly
, error
);
1335 mono_try_assembly_resolve (MonoAssemblyLoadContext
*alc
, const char *fname_raw
, MonoAssembly
*requesting
, gboolean refonly
, MonoError
*error
)
1337 HANDLE_FUNCTION_ENTER ();
1339 MonoAssembly
*result
= NULL
;
1340 MonoStringHandle fname
= mono_string_new_handle (mono_alc_domain (alc
), fname_raw
, error
);
1341 goto_if_nok (error
, leave
);
1342 result
= mono_try_assembly_resolve_handle (alc
, fname
, requesting
, refonly
, error
);
1344 HANDLE_FUNCTION_RETURN_VAL (result
);
1348 mono_try_assembly_resolve_handle (MonoAssemblyLoadContext
*alc
, MonoStringHandle fname
, MonoAssembly
*requesting
, gboolean refonly
, MonoError
*error
)
1350 HANDLE_FUNCTION_ENTER ();
1351 MonoAssembly
*ret
= NULL
;
1352 MonoDomain
*domain
= mono_alc_domain (alc
);
1353 static MonoMethod
*method
;
1355 if (mono_runtime_get_no_exec ())
1358 #ifndef ENABLE_NETCORE
1359 MonoBoolean isrefonly
;
1360 gpointer params
[3];
1362 g_assert (domain
!= NULL
&& !MONO_HANDLE_IS_NULL (fname
));
1364 method
= mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoAssemblyResolve", -1, 0, error
);
1365 g_assert (method
!= NULL
);
1367 isrefonly
= refonly
? 1 : 0;
1368 MonoReflectionAssemblyHandle requesting_handle
;
1370 requesting_handle
= mono_assembly_get_object_handle (domain
, requesting
, error
);
1371 goto_if_nok (error
, leave
);
1373 params
[0] = MONO_HANDLE_RAW (fname
);
1374 params
[1] = requesting
? MONO_HANDLE_RAW (requesting_handle
) : NULL
;
1375 params
[2] = &isrefonly
;
1378 MonoReflectionAssemblyHandle result
;
1379 result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, MONO_HANDLE_NEW (MonoObject
, mono_runtime_try_invoke (method
, domain
->domain
, params
, &exc
, error
)));
1380 if (!is_ok (error
) || exc
!= NULL
) {
1382 mono_error_set_exception_instance (error
, (MonoException
*)exc
);
1385 ret
= !MONO_HANDLE_IS_NULL (result
) ? MONO_HANDLE_GETVAL (result
, assembly
) : NULL
;
1387 if (ret
&& !refonly
&& mono_asmctx_get_kind (&ret
->context
) == MONO_ASMCTX_REFONLY
) {
1388 /* .NET Framework throws System.IO.FileNotFoundException in this case */
1389 mono_error_set_file_not_found (error
, NULL
, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only");
1395 ERROR_DECL (local_error
);
1396 MonoClass
*alc_class
= mono_class_get_assembly_load_context_class ();
1397 g_assert (alc_class
);
1398 MonoMethod
*found
= mono_class_get_method_from_name_checked (alc_class
, "OnAssemblyResolve", -1, 0, local_error
);
1399 mono_error_assert_ok (local_error
);
1404 MonoReflectionAssemblyHandle requesting_handle
;
1406 requesting_handle
= mono_assembly_get_object_handle (domain
, requesting
, error
);
1407 goto_if_nok (error
, leave
);
1410 gpointer params
[2];
1411 params
[0] = requesting
? MONO_HANDLE_RAW (requesting_handle
) : NULL
;
1412 params
[1] = MONO_HANDLE_RAW (fname
);
1413 MonoReflectionAssemblyHandle result
;
1414 result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_runtime_try_invoke_handle (method
, NULL_HANDLE
, params
, error
));
1415 goto_if_nok (error
, leave
);
1417 if (MONO_HANDLE_BOOL (result
))
1418 ret
= MONO_HANDLE_GETVAL (result
, assembly
);
1422 HANDLE_FUNCTION_RETURN_VAL (ret
);
1426 mono_domain_assembly_postload_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
1427 MonoAssemblyName
*aname
,
1428 gboolean refonly
, gboolean postload
,
1430 MonoError
*error_out
)
1433 MonoAssembly
*assembly
;
1436 aname_str
= mono_stringify_assembly_name (aname
);
1438 /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
1440 assembly
= mono_try_assembly_resolve (alc
, aname_str
, requesting
, refonly
, error
);
1442 mono_error_cleanup (error
);
1448 * LOCKING: assumes assemblies_lock in the domain is already locked.
1451 add_assemblies_to_domain (MonoDomain
*domain
, MonoAssembly
*ass
, GHashTable
*ht
)
1455 gboolean destroy_ht
= FALSE
;
1457 g_assert (ass
!= NULL
);
1459 if (!ass
->aname
.name
)
1463 ht
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
1465 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
1466 g_hash_table_insert (ht
, tmp
->data
, tmp
->data
);
1470 /* FIXME: handle lazy loaded assemblies */
1472 if (!g_hash_table_lookup (ht
, ass
)) {
1473 mono_assembly_addref (ass
);
1474 g_hash_table_insert (ht
, ass
, ass
);
1475 domain
->domain_assemblies
= g_slist_append (domain
->domain_assemblies
, ass
);
1476 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Assembly %s[%p] added to domain %s, ref_count=%d", ass
->aname
.name
, ass
, domain
->friendly_name
, ass
->ref_count
);
1479 if (ass
->image
->references
) {
1480 for (i
= 0; i
< ass
->image
->nreferences
; i
++) {
1481 if (ass
->image
->references
[i
] && ass
->image
->references
[i
] != REFERENCE_MISSING
) {
1482 if (!g_hash_table_lookup (ht
, ass
->image
->references
[i
])) {
1483 add_assemblies_to_domain (domain
, ass
->image
->references
[i
], ht
);
1489 g_hash_table_destroy (ht
);
1492 #ifdef ENABLE_NETCORE
1494 add_assembly_to_alc (MonoAssemblyLoadContext
*alc
, MonoAssembly
*ass
)
1499 g_assert (ass
!= NULL
);
1501 if (!ass
->aname
.name
)
1504 mono_alc_assemblies_lock (alc
);
1506 for (tmp
= alc
->loaded_assemblies
; tmp
; tmp
= tmp
->next
) {
1507 if (tmp
->data
== ass
) {
1508 mono_alc_assemblies_unlock (alc
);
1513 mono_assembly_addref (ass
);
1514 // Prepending here will break the test suite with frequent InvalidCastExceptions, so we have to append
1515 alc
->loaded_assemblies
= g_slist_append (alc
->loaded_assemblies
, ass
);
1516 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass
->aname
.name
, ass
, (gpointer
)alc
, ass
->ref_count
);
1518 if (ass
->image
->references
) {
1519 for (i
= 0; i
< ass
->image
->nreferences
; i
++) {
1520 // TODO: remove all this after we're confident this assert isn't hit
1521 g_assertf (!ass
->image
->references
[i
], "Did not expect reference %d of %s to be resolved", i
, ass
->image
->name
);
1525 mono_alc_assemblies_unlock (alc
);
1530 mono_domain_fire_assembly_load (MonoAssemblyLoadContext
*alc
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error_out
)
1532 HANDLE_FUNCTION_ENTER ();
1533 static MonoClassField
*assembly_load_field
;
1534 static MonoMethod
*assembly_load_method
;
1536 MonoDomain
*domain
= mono_alc_domain (alc
);
1538 MonoObjectHandle appdomain
;
1540 if (!MONO_BOOL (domain
->domain
))
1541 goto leave
; // This can happen during startup
1543 if (mono_runtime_get_no_exec ())
1546 #ifdef ASSEMBLY_LOAD_DEBUG
1547 fprintf (stderr
, "Loading %s into domain %s\n", assembly
->aname
.name
, domain
->friendly_name
);
1549 appdomain
= MONO_HANDLE_NEW (MonoObject
, &domain
->domain
->mbr
.obj
);
1550 klass
= mono_handle_class (appdomain
);
1552 mono_domain_assemblies_lock (domain
);
1553 add_assemblies_to_domain (domain
, assembly
, NULL
);
1554 mono_domain_assemblies_unlock (domain
);
1555 #ifdef ENABLE_NETCORE
1556 add_assembly_to_alc (alc
, assembly
);
1559 if (assembly_load_field
== NULL
) {
1560 assembly_load_field
= mono_class_get_field_from_name_full (klass
, "AssemblyLoad", NULL
);
1561 g_assert (assembly_load_field
);
1564 if (!MONO_HANDLE_GET_FIELD_BOOL (appdomain
, MonoObject
*, assembly_load_field
))
1565 goto leave
; // No events waiting to be triggered
1567 MonoReflectionAssemblyHandle reflection_assembly
;
1568 reflection_assembly
= mono_assembly_get_object_handle (domain
, assembly
, error
);
1569 mono_error_assert_ok (error
);
1571 if (assembly_load_method
== NULL
) {
1572 assembly_load_method
= mono_class_get_method_from_name_checked (klass
, "DoAssemblyLoad", -1, 0, error
);
1573 g_assert (assembly_load_method
);
1577 params
[0] = MONO_HANDLE_RAW (reflection_assembly
);
1578 mono_runtime_invoke_handle_void (assembly_load_method
, appdomain
, params
, error
);
1580 mono_error_cleanup (error
);
1581 HANDLE_FUNCTION_RETURN ();
1585 mono_domain_asmctx_from_path (const char *fname
, MonoAssembly
*requesting_assembly
, gpointer user_data
, MonoAssemblyContextKind
*out_asmctx
)
1587 MonoDomain
*domain
= mono_domain_get ();
1588 char **search_path
= NULL
;
1590 for (search_path
= domain
->search_path
; search_path
&& *search_path
; search_path
++) {
1591 if (mono_path_filename_in_basedir (fname
, *search_path
)) {
1592 *out_asmctx
= MONO_ASMCTX_DEFAULT
;
1600 * LOCKING: Acquires the domain assemblies lock.
1603 set_domain_search_path (MonoDomain
*domain
)
1605 HANDLE_FUNCTION_ENTER ();
1607 MonoAppDomainSetupHandle setup
;
1609 gchar
*search_path
= NULL
;
1611 gchar
**pvt_split
= NULL
;
1612 GError
*gerror
= NULL
;
1613 gint appbaselen
= -1;
1616 * We use the low-level domain assemblies lock, since this is called from
1617 * assembly loads hooks, which means this thread might hold the loader lock.
1619 mono_domain_assemblies_lock (domain
);
1621 if (!MONO_BOOL (domain
->setup
))
1624 setup
= MONO_HANDLE_NEW (MonoAppDomainSetup
, domain
->setup
);
1626 if (domain
->search_path
&& !MONO_HANDLE_GET_BOOL (setup
, path_changed
))
1629 if (!MONO_HANDLE_GET_BOOL (setup
, application_base
))
1630 goto exit
; // Must set application base to get private path working
1632 if (MONO_HANDLE_GET_BOOL (setup
, private_bin_path
)) {
1633 search_path
= mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString
, setup
, private_bin_path
), error
);
1634 if (!is_ok (error
)) { /*FIXME maybe we should bubble up the error.*/
1635 g_warning ("Could not decode AppDomain search path since it contains invalid characters");
1640 if (domain
->private_bin_path
) {
1641 if (search_path
== NULL
)
1642 search_path
= domain
->private_bin_path
;
1644 gchar
*tmp2
= search_path
;
1645 search_path
= g_strjoin (";", search_path
, domain
->private_bin_path
, NULL
);
1652 * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of
1653 * directories relative to ApplicationBase separated by semicolons (see
1654 * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx)
1655 * The loop below copes with the fact that some Unix applications may use ':' (or
1656 * System.IO.Path.PathSeparator) as the path search separator. We replace it with
1657 * ';' for the subsequent split.
1659 * The issue was reported in bug #81446
1661 #ifndef TARGET_WIN32
1662 g_strdelimit (search_path
, ':', ';');
1664 pvt_split
= g_strsplit (search_path
, ";", 1000);
1665 g_free (search_path
);
1666 for (tmp
= pvt_split
; *tmp
; tmp
++, npaths
++);
1669 g_strfreev (domain
->search_path
);
1670 domain
->search_path
= NULL
;
1672 tmp
= g_new (gchar
*, npaths
+ 1);
1673 tmp
[npaths
] = NULL
;
1675 *tmp
= mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString
, setup
, application_base
), error
);
1676 if (!is_ok (error
)) {
1681 domain
->search_path
= tmp
;
1683 /* FIXME: is this needed? */
1684 if (strncmp (*tmp
, "file://", 7) == 0) {
1690 uri
= g_strdup_printf ("file:///%s", uri
+ 7);
1693 uri
= mono_escape_uri_string (tmpuri
);
1694 *tmp
= g_filename_from_uri (uri
, NULL
, &gerror
);
1700 if (gerror
!= NULL
) {
1701 g_warning ("%s\n", gerror
->message
);
1702 g_error_free (gerror
);
1709 for (gsize i
= 1; pvt_split
&& i
< npaths
; i
++) {
1710 if (g_path_is_absolute (pvt_split
[i
- 1])) {
1711 tmp
[i
] = g_strdup (pvt_split
[i
- 1]);
1713 tmp
[i
] = g_build_filename (tmp
[0], pvt_split
[i
- 1], NULL
);
1716 if (strchr (tmp
[i
], '.')) {
1720 reduced
= mono_path_canonicalize (tmp
[i
]);
1721 if (appbaselen
== -1)
1722 appbaselen
= strlen (tmp
[0]);
1724 if (strncmp (tmp
[0], reduced
, appbaselen
)) {
1727 tmp
[i
] = g_strdup ("");
1737 if (MONO_HANDLE_GET_BOOL (setup
, private_bin_path_probe
)) {
1739 tmp
[0] = g_strdup ("");
1742 MONO_HANDLE_SETVAL (setup
, path_changed
, MonoBoolean
, FALSE
);
1744 mono_error_cleanup (error
);
1745 g_strfreev (pvt_split
);
1746 mono_domain_assemblies_unlock (domain
);
1747 HANDLE_FUNCTION_RETURN ();
1750 #ifdef DISABLE_SHADOW_COPY
1752 mono_is_shadow_copy_enabled (MonoDomain
*domain
, const gchar
*dir_name
)
1758 mono_make_shadow_copy (const char *filename
, MonoError
*error
)
1761 return (char *) filename
;
1766 SHADOW_COPY_SIBLING_EXT_APPEND
,
1767 SHADOW_COPY_SIBLING_EXT_REPLACE
,
1768 } ShadowCopySiblingExt
;
1772 make_sibling_path (const gchar
*path
, gint pathlen
, const char *extension
, ShadowCopySiblingExt extopt
)
1774 gchar
*result
= NULL
;
1776 case SHADOW_COPY_SIBLING_EXT_APPEND
: {
1777 result
= g_strconcat (path
, extension
, NULL
);
1780 case SHADOW_COPY_SIBLING_EXT_REPLACE
: {
1781 /* expect path to be a .dll or .exe (or some case insensitive variant) */
1782 g_assert (pathlen
>= 4 && path
[pathlen
- 4] == '.');
1783 GString
*s
= g_string_sized_new (pathlen
- 4 + strlen (extension
));
1784 g_string_append_len (s
, path
, pathlen
- 4);
1785 g_string_append (s
, extension
);
1786 result
= g_string_free (s
, FALSE
);
1790 g_assert_not_reached ();
1796 shadow_copy_sibling (const gchar
*src_pristine
, gint srclen
, const char *extension
, ShadowCopySiblingExt extopt
, const gchar
*target_pristine
, gint targetlen
)
1799 gunichar2
*orig
= NULL
;
1800 gunichar2
*dest
= NULL
;
1801 gboolean copy_result
= TRUE
;
1802 gchar
*target
= NULL
;
1804 char *src
= make_sibling_path (src_pristine
, srclen
, extension
, extopt
);
1806 if (IS_PORTABILITY_CASE
) {
1807 file
= mono_portability_find_file (src
, TRUE
);
1810 } else if (!g_file_test (src
, G_FILE_TEST_IS_REGULAR
))
1813 orig
= g_utf8_to_utf16 (src
, strlen (src
), NULL
, NULL
, NULL
);
1815 target
= make_sibling_path (target_pristine
, targetlen
, extension
, extopt
);
1817 dest
= g_utf8_to_utf16 (target
, strlen (target
), NULL
, NULL
, NULL
);
1819 mono_w32file_delete (dest
);
1822 copy_result
= mono_w32file_copy (orig
, dest
, TRUE
, ©_error
);
1824 /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
1825 * overwritten when updated in their original locations. */
1827 copy_result
= mono_w32file_set_attributes (dest
, FILE_ATTRIBUTE_NORMAL
);
1839 get_cstring_hash (const char *str
)
1844 if (!str
|| !str
[0])
1847 gsize
const len
= strlen (str
);
1849 for (gsize i
= 0; i
< len
; i
++) {
1850 h
= (h
<< 5) - h
+ *p
;
1858 * Returned memory is malloc'd. Called must free it
1861 get_shadow_assembly_location_base (MonoDomain
*domain
, MonoError
*error
)
1863 MonoAppDomainSetup
*setup
;
1864 char *cache_path
= NULL
;
1865 char *appname
= NULL
;
1866 char *userdir
= NULL
;
1871 setup
= domain
->setup
;
1872 if (setup
->cache_path
!= NULL
&& setup
->application_name
!= NULL
) {
1873 cache_path
= mono_string_to_utf8_checked_internal (setup
->cache_path
, error
);
1874 return_val_if_nok (error
, NULL
);
1876 #ifndef TARGET_WIN32
1879 for (i
= strlen (cache_path
) - 1; i
>= 0; i
--)
1880 if (cache_path
[i
] == '\\')
1881 cache_path
[i
] = '/';
1885 appname
= mono_string_to_utf8_checked_internal (setup
->application_name
, error
);
1886 if (!is_ok (error
)) {
1887 g_free (cache_path
);
1891 location
= g_build_filename (cache_path
, appname
, "assembly", "shadow", NULL
);
1893 userdir
= g_strdup_printf ("%s-mono-cachepath", g_get_user_name ());
1894 location
= g_build_filename (g_get_tmp_dir (), userdir
, "assembly", "shadow", NULL
);
1897 g_free (cache_path
);
1903 get_shadow_assembly_location (const char *filename
, MonoError
*error
)
1905 gint32 hash
= 0, hash2
= 0;
1907 char path_hash
[30];
1908 char *bname
= g_path_get_basename (filename
);
1909 char *dirname
= g_path_get_dirname (filename
);
1910 char *location
, *tmploc
;
1911 MonoDomain
*domain
= mono_domain_get ();
1915 hash
= get_cstring_hash (bname
);
1916 hash2
= get_cstring_hash (dirname
);
1917 g_snprintf (name_hash
, sizeof (name_hash
), "%08x", hash
);
1918 g_snprintf (path_hash
, sizeof (path_hash
), "%08x_%08x_%08x", hash
^ hash2
, hash2
, domain
->shadow_serial
);
1919 tmploc
= get_shadow_assembly_location_base (domain
, error
);
1920 if (!is_ok (error
)) {
1926 location
= g_build_filename (tmploc
, name_hash
, path_hash
, bname
, NULL
);
1934 private_file_needs_copying (const char *src
, struct stat
*sbuf_src
, char *dest
)
1936 struct stat sbuf_dest
;
1938 gchar
*real_src
= mono_portability_find_file (src
, TRUE
);
1941 stat_src
= (gchar
*)src
;
1943 stat_src
= real_src
;
1945 if (stat (stat_src
, sbuf_src
) == -1) {
1946 time_t tnow
= time (NULL
);
1951 memset (sbuf_src
, 0, sizeof (*sbuf_src
));
1952 sbuf_src
->st_mtime
= tnow
;
1953 sbuf_src
->st_atime
= tnow
;
1960 if (stat (dest
, &sbuf_dest
) == -1)
1963 if (sbuf_src
->st_size
== sbuf_dest
.st_size
&&
1964 sbuf_src
->st_mtime
== sbuf_dest
.st_mtime
)
1971 shadow_copy_create_ini (const char *shadow
, const char *filename
)
1973 gunichar2
*u16_ini
= NULL
;
1974 gboolean result
= FALSE
;
1976 HANDLE handle
= INVALID_HANDLE_VALUE
;
1977 gchar
*full_path
= NULL
;
1979 char *dir_name
= g_path_get_dirname (shadow
);
1980 char *ini_file
= g_build_filename (dir_name
, "__AssemblyInfo__.ini", NULL
);
1982 result
= g_file_test (ini_file
, G_FILE_TEST_IS_REGULAR
);
1986 u16_ini
= g_utf8_to_utf16 (ini_file
, strlen (ini_file
), NULL
, NULL
, NULL
);
1990 handle
= mono_w32file_create (u16_ini
, GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, CREATE_NEW
, FileAttributes_Normal
);
1991 if (handle
== INVALID_HANDLE_VALUE
)
1994 full_path
= mono_path_resolve_symlinks (filename
);
1997 result
= mono_w32file_write (handle
, full_path
, strlen (full_path
), &n
, &win32error
);
1999 if (handle
!= INVALID_HANDLE_VALUE
)
2000 mono_w32file_close (handle
);
2008 mono_is_shadow_copy_enabled (MonoDomain
*domain
, const gchar
*dir_name
)
2011 MonoAppDomainSetup
*setup
;
2012 gchar
*all_dirs
= NULL
;
2014 gchar
**directories
= NULL
;
2015 gchar
*shadow_status_string
;
2016 gchar
*base_dir
= NULL
;
2017 gboolean shadow_enabled
;
2018 gboolean found
= FALSE
;
2023 setup
= domain
->setup
;
2024 if (setup
== NULL
|| setup
->shadow_copy_files
== NULL
)
2027 shadow_status_string
= mono_string_to_utf8_checked_internal (setup
->shadow_copy_files
, error
);
2031 shadow_enabled
= !g_ascii_strncasecmp (shadow_status_string
, "true", 4);
2032 g_free (shadow_status_string
);
2034 if (!shadow_enabled
)
2037 found
= (setup
->shadow_copy_directories
== NULL
);
2041 /* Is dir_name a shadow_copy destination already? */
2042 base_dir
= get_shadow_assembly_location_base (domain
, error
);
2046 found
= !!strstr (dir_name
, base_dir
);
2050 all_dirs
= mono_string_to_utf8_checked_internal (setup
->shadow_copy_directories
, error
);
2054 directories
= g_strsplit (all_dirs
, G_SEARCHPATH_SEPARATOR_S
, 1000);
2055 dir_ptr
= directories
;
2056 while (!found
&& *dir_ptr
) {
2057 found
= (**dir_ptr
!= '\0' && !strcmp (*dir_ptr
, dir_name
));
2061 mono_error_cleanup (error
);
2063 g_strfreev (directories
);
2069 This function raises exceptions so it can cause as sorts of nasty stuff if called
2070 while holding a lock.
2071 Returns old file name if shadow copy is disabled, new shadow copy file name if successful
2072 or NULL if source file not found.
2073 FIXME bubble up the error instead of raising it here
2076 mono_make_shadow_copy (const char *filename
, MonoError
*oerror
)
2079 gint filename_len
, shadow_len
;
2080 gunichar2
*orig
, *dest
;
2083 gboolean copy_result
;
2084 struct stat src_sbuf
;
2085 struct utimbuf utbuf
;
2086 char *dir_name
= g_path_get_dirname (filename
);
2087 MonoDomain
*domain
= mono_domain_get ();
2091 error_init (oerror
);
2093 set_domain_search_path (domain
);
2095 if (!mono_is_shadow_copy_enabled (domain
, dir_name
)) {
2097 return (char *) filename
;
2100 /* Is dir_name a shadow_copy destination already? */
2101 shadow_dir
= get_shadow_assembly_location_base (domain
, error
);
2102 if (!is_ok (error
)) {
2103 mono_error_cleanup (error
);
2105 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (invalid characters in shadow directory name).");
2109 if (strstr (dir_name
, shadow_dir
)) {
2110 g_free (shadow_dir
);
2112 return (char *) filename
;
2114 g_free (shadow_dir
);
2117 shadow
= get_shadow_assembly_location (filename
, error
);
2118 if (!is_ok (error
)) {
2119 mono_error_cleanup (error
);
2120 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (invalid characters in file name).");
2124 if (g_ensure_directory_exists (shadow
) == FALSE
) {
2126 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (ensure directory exists).");
2130 if (!private_file_needs_copying (filename
, &src_sbuf
, shadow
))
2131 return (char*) shadow
;
2133 orig
= g_utf8_to_utf16 (filename
, strlen (filename
), NULL
, NULL
, NULL
);
2134 dest
= g_utf8_to_utf16 (shadow
, strlen (shadow
), NULL
, NULL
, NULL
);
2135 mono_w32file_delete (dest
);
2137 /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather
2138 * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
2139 * and not have it runtime error" */
2140 attrs
= mono_w32file_get_attributes (orig
);
2141 if (attrs
== INVALID_FILE_ATTRIBUTES
) {
2143 return (char *)filename
;
2146 copy_result
= mono_w32file_copy (orig
, dest
, TRUE
, ©_error
);
2148 /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
2149 * overwritten when updated in their original locations. */
2151 copy_result
= mono_w32file_set_attributes (dest
, FILE_ATTRIBUTE_NORMAL
);
2156 if (copy_result
== FALSE
) {
2159 /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */
2160 if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND
|| mono_w32error_get_last() == ERROR_PATH_NOT_FOUND
)
2161 return NULL
; /* file not found, shadow copy failed */
2163 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy (mono_w32file_copy).");
2167 /* attempt to copy .mdb, .pdb and .config if they exist */
2168 filename_len
= strlen (filename
);
2169 shadow_len
= strlen (shadow
);
2171 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".mdb", SHADOW_COPY_SIBLING_EXT_APPEND
, shadow
, shadow_len
);
2173 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".pdb", SHADOW_COPY_SIBLING_EXT_REPLACE
, shadow
, shadow_len
);
2175 copy_result
= shadow_copy_sibling (filename
, filename_len
, ".config", SHADOW_COPY_SIBLING_EXT_APPEND
, shadow
, shadow_len
);
2179 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
2183 /* Create a .ini file containing the original assembly location */
2184 if (!shadow_copy_create_ini (shadow
, filename
)) {
2186 mono_error_set_execution_engine (oerror
, "Failed to create shadow copy .ini file.");
2190 utbuf
.actime
= src_sbuf
.st_atime
;
2191 utbuf
.modtime
= src_sbuf
.st_mtime
;
2192 utime (shadow
, &utbuf
);
2196 #endif /* DISABLE_SHADOW_COPY */
2199 * mono_domain_from_appdomain:
2202 mono_domain_from_appdomain (MonoAppDomain
*appdomain_raw
)
2204 HANDLE_FUNCTION_ENTER ();
2206 MONO_ENTER_GC_UNSAFE
;
2207 MONO_HANDLE_DCL (MonoAppDomain
, appdomain
);
2208 result
= mono_domain_from_appdomain_handle (appdomain
);
2209 MONO_EXIT_GC_UNSAFE
;
2210 HANDLE_FUNCTION_RETURN_VAL (result
);
2214 mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain
)
2216 HANDLE_FUNCTION_ENTER ();
2217 MonoDomain
*dom
= NULL
;
2218 if (MONO_HANDLE_IS_NULL (appdomain
))
2221 if (mono_class_is_transparent_proxy (mono_handle_class (appdomain
))) {
2222 MonoTransparentProxyHandle tp
= MONO_HANDLE_CAST (MonoTransparentProxy
, appdomain
);
2223 MonoRealProxyHandle rp
= MONO_HANDLE_NEW_GET (MonoRealProxy
, tp
, rp
);
2225 dom
= mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp
, target_domain_id
));
2227 dom
= MONO_HANDLE_GETVAL (appdomain
, data
);
2230 HANDLE_FUNCTION_RETURN_VAL (dom
);
2235 try_load_from (MonoAssembly
**assembly
,
2236 const gchar
*path1
, const gchar
*path2
,
2237 const gchar
*path3
, const gchar
*path4
,
2238 const MonoAssemblyOpenRequest
*req
)
2241 gboolean found
= FALSE
;
2244 fullpath
= g_build_filename (path1
, path2
, path3
, path4
, NULL
);
2246 if (IS_PORTABILITY_SET
) {
2247 gchar
*new_fullpath
= mono_portability_find_file (fullpath
, TRUE
);
2250 fullpath
= new_fullpath
;
2254 found
= g_file_test (fullpath
, G_FILE_TEST_IS_REGULAR
);
2257 *assembly
= mono_assembly_request_open (fullpath
, req
, NULL
);
2261 return (*assembly
!= NULL
);
2264 static MonoAssembly
*
2265 real_load (gchar
**search_path
, const gchar
*culture
, const gchar
*name
, const MonoAssemblyOpenRequest
*req
)
2267 MonoAssembly
*result
= NULL
;
2270 const gchar
*local_culture
;
2273 if (!culture
|| *culture
== '\0') {
2276 local_culture
= culture
;
2279 filename
= g_strconcat (name
, ".dll", NULL
);
2280 len
= strlen (filename
);
2282 for (path
= search_path
; *path
; path
++) {
2283 if (**path
== '\0') {
2284 continue; /* Ignore empty ApplicationBase */
2287 /* See test cases in bug #58992 and bug #57710 */
2288 /* 1st try: [culture]/[name].dll (culture may be empty) */
2289 strcpy (filename
+ len
- 4, ".dll");
2290 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
2293 /* 2nd try: [culture]/[name].exe (culture may be empty) */
2294 strcpy (filename
+ len
- 4, ".exe");
2295 if (try_load_from (&result
, *path
, local_culture
, "", filename
, req
))
2298 /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
2299 strcpy (filename
+ len
- 4, ".dll");
2300 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
2303 /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
2304 strcpy (filename
+ len
- 4, ".exe");
2305 if (try_load_from (&result
, *path
, local_culture
, name
, filename
, req
))
2314 * Try loading the assembly from ApplicationBase and PrivateBinPath
2315 * and then from assemblies_path if any.
2316 * LOCKING: This is called from the assembly loading code, which means the caller
2317 * might hold the loader lock. Thus, this function must not acquire the domain lock.
2319 static MonoAssembly
*
2320 mono_domain_assembly_preload (MonoAssemblyLoadContext
*alc
,
2321 MonoAssemblyName
*aname
,
2322 gchar
**assemblies_path
,
2327 MonoDomain
*domain
= mono_alc_domain (alc
);
2328 MonoAssembly
*result
= NULL
;
2329 #ifdef ENABLE_NETCORE
2331 g_assert (domain
== mono_domain_get ());
2334 set_domain_search_path (domain
);
2336 MonoAssemblyCandidatePredicate predicate
= NULL
;
2337 void* predicate_ud
= NULL
;
2338 #if !defined(DISABLE_DESKTOP_LOADER)
2339 if (G_LIKELY (mono_loader_get_strict_strong_names ())) {
2340 predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
2341 predicate_ud
= aname
;
2344 MonoAssemblyOpenRequest req
;
2345 mono_assembly_request_prepare_open (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
, alc
);
2346 req
.request
.predicate
= predicate
;
2347 req
.request
.predicate_ud
= predicate_ud
;
2349 if (domain
->search_path
&& domain
->search_path
[0] != NULL
) {
2350 if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
)) {
2351 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "Domain %s search path is:", domain
->friendly_name
);
2352 for (int i
= 0; domain
->search_path
[i
]; i
++) {
2353 const char *p
= domain
->search_path
[i
];
2354 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "\tpath[%d] = '%s'", i
, p
);
2356 mono_trace (G_LOG_LEVEL_DEBUG
, MONO_TRACE_ASSEMBLY
, "End of domain %s search path.", domain
->friendly_name
);
2358 result
= real_load (domain
->search_path
, aname
->culture
, aname
->name
, &req
);
2361 if (result
== NULL
&& assemblies_path
&& assemblies_path
[0] != NULL
) {
2362 result
= real_load (assemblies_path
, aname
->culture
, aname
->name
, &req
);
2369 * mono_assembly_load_from_assemblies_path:
2371 * \param assemblies_path directories to search for given assembly name, terminated by NULL
2372 * \param aname assembly name to look for
2373 * \param asmctx assembly load context for this load operation
2375 * Given a NULL-terminated array of paths, look for \c name.ext, \c name, \c
2376 * culture/name.ext, \c culture/name/name.ext where \c ext is \c dll and \c
2377 * exe and try to load it in the given assembly load context.
2379 * \returns A \c MonoAssembly if probing was successful, or NULL otherwise.
2382 mono_assembly_load_from_assemblies_path (gchar
**assemblies_path
, MonoAssemblyName
*aname
, MonoAssemblyContextKind asmctx
)
2384 MonoAssemblyCandidatePredicate predicate
= NULL
;
2385 void* predicate_ud
= NULL
;
2386 #if !defined(DISABLE_DESKTOP_LOADER)
2387 if (G_LIKELY (mono_loader_get_strict_strong_names ())) {
2388 predicate
= &mono_assembly_candidate_predicate_sn_same_name
;
2389 predicate_ud
= aname
;
2392 MonoAssemblyOpenRequest req
;
2393 mono_assembly_request_prepare_open (&req
, asmctx
, mono_domain_default_alc (mono_domain_get ()));
2394 req
.request
.predicate
= predicate
;
2395 req
.request
.predicate_ud
= predicate_ud
;
2396 MonoAssembly
*result
= NULL
;
2397 if (assemblies_path
&& assemblies_path
[0] != NULL
) {
2398 result
= real_load (assemblies_path
, aname
->culture
, aname
->name
, &req
);
2404 * Check whenever a given assembly was already loaded in the current appdomain.
2406 static MonoAssembly
*
2407 mono_domain_assembly_search (MonoAssemblyLoadContext
*alc
, MonoAssembly
*requesting
,
2408 MonoAssemblyName
*aname
,
2414 g_assert (aname
!= NULL
);
2417 const gboolean strong_name
= aname
->public_key_token
[0] != 0;
2418 /* If it's not a strong name, any version that has the right simple
2419 * name is good enough to satisfy the request. .NET Framework also
2420 * ignores case differences in this case. */
2421 const MonoAssemblyNameEqFlags eq_flags
= (MonoAssemblyNameEqFlags
)(strong_name
? MONO_ANAME_EQ_IGNORE_CASE
:
2422 (MONO_ANAME_EQ_IGNORE_PUBKEY
| MONO_ANAME_EQ_IGNORE_VERSION
| MONO_ANAME_EQ_IGNORE_CASE
));
2424 #ifdef ENABLE_NETCORE
2425 mono_alc_assemblies_lock (alc
);
2426 for (tmp
= alc
->loaded_assemblies
; tmp
; tmp
= tmp
->next
) {
2427 ass
= (MonoAssembly
*)tmp
->data
;
2428 g_assert (ass
!= NULL
);
2429 // TODO: Can dynamic assemblies match here for netcore? Also, this ignores case while exact_sn_match does not.
2430 if (assembly_is_dynamic (ass
) || !mono_assembly_names_equal_flags (aname
, &ass
->aname
, eq_flags
))
2433 mono_alc_assemblies_unlock (alc
);
2436 mono_alc_assemblies_unlock (alc
);
2438 MonoDomain
*domain
= mono_alc_domain (alc
);
2439 mono_domain_assemblies_lock (domain
);
2440 for (tmp
= domain
->domain_assemblies
; tmp
; tmp
= tmp
->next
) {
2441 ass
= (MonoAssembly
*)tmp
->data
;
2442 g_assert (ass
!= NULL
);
2443 /* Dynamic assemblies can't match here in MS.NET */
2444 gboolean ass_ref_only
= mono_asmctx_get_kind (&ass
->context
) == MONO_ASMCTX_REFONLY
;
2445 if (assembly_is_dynamic (ass
) || refonly
!= ass_ref_only
|| !mono_assembly_names_equal_flags (aname
, &ass
->aname
, eq_flags
))
2448 mono_domain_assemblies_unlock (domain
);
2451 mono_domain_assemblies_unlock (domain
);
2458 MonoReflectionAssemblyHandle
2459 ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle
, MonoStackCrawlMark
*stack_mark
, gpointer load_Context
, MonoError
*error
)
2462 MonoAssembly
*ass
= NULL
;
2463 MonoAssemblyName aname
;
2464 MonoAssemblyByNameRequest req
;
2465 MonoAssemblyContextKind asmctx
;
2466 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2470 MonoAssembly
*requesting_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2471 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)load_Context
;
2474 alc
= mono_assembly_get_alc (requesting_assembly
);
2476 g_assert_not_reached ();
2478 MonoDomain
*domain
= mono_alc_domain (alc
);
2480 asmctx
= MONO_ASMCTX_DEFAULT
;
2481 mono_assembly_request_prepare_byname (&req
, asmctx
, alc
);
2483 /* Everything currently goes through this function, and the postload hook (aka the AppDomain.AssemblyResolve event)
2484 * is triggered under some scenarios. It's not completely obvious to me in what situations (if any) this should be disabled,
2485 * other than for corlib satellite assemblies (which I've dealt with further down the call stack).
2487 //req.no_postload_search = TRUE;
2488 req
.requesting_assembly
= requesting_assembly
;
2490 name
= mono_string_handle_to_utf8 (name_handle
, error
);
2491 goto_if_nok (error
, fail
);
2492 parsed
= mono_assembly_name_parse (name
, &aname
);
2497 ass
= mono_assembly_request_byname (&aname
, &req
, &status
);
2501 MonoReflectionAssemblyHandle refass
;
2502 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2503 goto_if_nok (error
, fail
);
2507 return MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2511 #ifndef ENABLE_NETCORE
2512 MonoReflectionAssemblyHandle
2513 ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname
, MonoBoolean refOnly
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2516 MonoDomain
*domain
= mono_domain_get ();
2517 char *name
, *filename
;
2518 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2519 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2523 if (MONO_HANDLE_IS_NULL (fname
)) {
2524 mono_error_set_argument_null (error
, "assemblyFile", "");
2528 name
= filename
= mono_string_handle_to_utf8 (fname
, error
);
2529 goto_if_nok (error
, leave
);
2531 MonoAssembly
*requesting_assembly
;
2532 requesting_assembly
= NULL
;
2534 requesting_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2537 MonoAssemblyOpenRequest req
;
2538 mono_assembly_request_prepare_open (&req
, refOnly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_LOADFROM
, mono_domain_default_alc (domain
));
2539 req
.requesting_assembly
= requesting_assembly
;
2540 ass
= mono_assembly_request_open (filename
, &req
, &status
);
2543 if (status
== MONO_IMAGE_IMAGE_INVALID
)
2544 mono_error_set_bad_image_by_name (error
, name
, "Invalid Image");
2546 mono_error_set_file_not_found (error
, name
, "Invalid Image");
2550 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2560 mono_alc_load_file (MonoAssemblyLoadContext
*alc
, MonoStringHandle fname
, MonoAssembly
*executing_assembly
, MonoAssemblyContextKind asmctx
, MonoError
*error
)
2562 MonoAssembly
*ass
= NULL
;
2563 HANDLE_FUNCTION_ENTER ();
2564 char *filename
= NULL
;
2565 if (MONO_HANDLE_IS_NULL (fname
)) {
2566 mono_error_set_argument_null (error
, "assemblyFile", "");
2570 filename
= mono_string_handle_to_utf8 (fname
, error
);
2571 goto_if_nok (error
, leave
);
2573 if (!g_path_is_absolute (filename
)) {
2574 mono_error_set_argument (error
, "assemblyFile", "Absolute path information is required.");
2578 MonoImageOpenStatus status
;
2579 MonoAssemblyOpenRequest req
;
2580 mono_assembly_request_prepare_open (&req
, asmctx
, alc
);
2581 req
.requesting_assembly
= executing_assembly
;
2582 ass
= mono_assembly_request_open (filename
, &req
, &status
);
2584 if (status
== MONO_IMAGE_IMAGE_INVALID
)
2585 mono_error_set_bad_image_by_name (error
, filename
, "Invalid Image");
2587 mono_error_set_file_not_found (error
, filename
, "Invalid Image");
2592 HANDLE_FUNCTION_RETURN_VAL (ass
);
2595 #ifndef ENABLE_NETCORE
2596 MonoReflectionAssemblyHandle
2597 ves_icall_System_Reflection_Assembly_LoadFile_internal (MonoStringHandle fname
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2599 MonoDomain
*domain
= mono_domain_get ();
2600 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2601 MonoAssembly
*executing_assembly
;
2602 executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2603 MonoAssembly
*ass
= mono_alc_load_file (mono_domain_default_alc (domain
), fname
, executing_assembly
, MONO_ASMCTX_INDIVIDUAL
, error
);
2604 goto_if_nok (error
, leave
);
2606 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2611 MonoReflectionAssemblyHandle
2612 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr
, MonoStringHandle fname
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2614 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2615 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)alc_ptr
;
2616 MonoDomain
*domain
= mono_alc_domain (alc
);
2618 MonoAssembly
*executing_assembly
;
2619 executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2620 MonoAssembly
*ass
= mono_alc_load_file (alc
, fname
, executing_assembly
, mono_alc_is_default (alc
) ? MONO_ASMCTX_LOADFROM
: MONO_ASMCTX_INDIVIDUAL
, error
);
2621 goto_if_nok (error
, leave
);
2623 result
= mono_assembly_get_object_handle (domain
, ass
, error
);
2630 static MonoAssembly
*
2631 mono_alc_load_raw_bytes (MonoAssemblyLoadContext
*alc
, guint8
*raw_assembly
, guint32 raw_assembly_len
, guint8
*raw_symbol_data
, guint32 raw_symbol_len
, gboolean refonly
, MonoError
*error
);
2633 #ifdef ENABLE_NETCORE
2634 MonoReflectionAssemblyHandle
2635 ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpointer native_alc
, gpointer raw_assembly_ptr
, gint32 raw_assembly_len
, gpointer raw_symbols_ptr
, gint32 raw_symbols_len
, MonoError
*error
)
2637 MonoAssemblyLoadContext
*alc
= (MonoAssemblyLoadContext
*)native_alc
;
2638 MonoDomain
*domain
= mono_alc_domain (alc
);
2639 MonoReflectionAssemblyHandle result
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2640 MonoAssembly
*assm
= NULL
;
2641 assm
= mono_alc_load_raw_bytes (alc
, (guint8
*)raw_assembly_ptr
, raw_assembly_len
, (guint8
*)raw_symbols_ptr
, raw_symbols_len
, FALSE
, error
);
2642 goto_if_nok (error
, leave
);
2644 result
= mono_assembly_get_object_handle (domain
, assm
, error
);
2650 MonoReflectionAssemblyHandle
2651 ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad
,
2652 MonoArrayHandle raw_assembly
,
2653 MonoArrayHandle raw_symbol_store
, MonoObjectHandle evidence
,
2654 MonoBoolean refonly
,
2658 MonoReflectionAssemblyHandle refass
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2659 MonoDomain
*domain
= MONO_HANDLE_GETVAL(ad
, data
);
2660 guint32 raw_assembly_len
= mono_array_handle_length (raw_assembly
);
2662 /* Copy the data ourselves to unpin the raw assembly byte array as soon as possible */
2663 guint8
*assembly_data
= (guint8
*) g_try_malloc (raw_assembly_len
);
2664 if (!assembly_data
) {
2665 mono_error_set_out_of_memory (error
, "Could not allocate %ud bytes to copy raw assembly data", raw_assembly_len
);
2669 mono_byte
*raw_data
= (mono_byte
*) MONO_ARRAY_HANDLE_PIN (raw_assembly
, gchar
, 0, &gchandle
);
2670 memcpy (assembly_data
, raw_data
, raw_assembly_len
);
2671 mono_gchandle_free_internal (gchandle
); /* unpin */
2672 MONO_HANDLE_ASSIGN (raw_assembly
, NULL_HANDLE
); /* don't reference the data anymore */
2674 MonoAssemblyLoadContext
*alc
= mono_domain_default_alc (domain
);
2676 mono_byte
*raw_symbol_data
= NULL
;
2677 guint32 symbol_len
= 0;
2678 uint32_t symbol_gchandle
= 0;
2679 if (!MONO_HANDLE_IS_NULL (raw_symbol_store
)) {
2680 symbol_len
= mono_array_handle_length (raw_symbol_store
);
2681 raw_symbol_data
= (mono_byte
*) MONO_ARRAY_HANDLE_PIN (raw_symbol_store
, mono_byte
, 0, &symbol_gchandle
);
2684 ass
= mono_alc_load_raw_bytes (alc
, assembly_data
, raw_assembly_len
, raw_symbol_data
, symbol_len
, refonly
, error
);
2685 mono_gchandle_free_internal (symbol_gchandle
);
2686 goto_if_nok (error
, leave
);
2688 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2689 if (!MONO_HANDLE_IS_NULL (refass
))
2690 MONO_HANDLE_SET (refass
, evidence
, evidence
);
2695 #endif /* ENABLE_NETCORE */
2697 static MonoAssembly
*
2698 mono_alc_load_raw_bytes (MonoAssemblyLoadContext
*alc
, guint8
*assembly_data
, guint32 raw_assembly_len
, guint8
*raw_symbol_data
, guint32 raw_symbol_len
, gboolean refonly
, MonoError
*error
)
2700 MonoAssembly
*ass
= NULL
;
2701 MonoImageOpenStatus status
;
2702 MonoImage
*image
= mono_image_open_from_data_internal (alc
, (char*)assembly_data
, raw_assembly_len
, FALSE
, NULL
, refonly
, FALSE
, NULL
);
2705 mono_error_set_bad_image_by_name (error
, "In memory assembly", "0x%p", assembly_data
);
2709 if (raw_symbol_data
)
2710 mono_debug_open_image_from_memory (image
, raw_symbol_data
, raw_symbol_len
);
2712 MonoAssembly
* redirected_asm
= NULL
;
2713 MonoImageOpenStatus new_status
= MONO_IMAGE_OK
;
2714 if ((redirected_asm
= mono_assembly_binding_applies_to_image (alc
, image
, &new_status
))) {
2715 mono_image_close (image
);
2716 image
= redirected_asm
->image
;
2717 mono_image_addref (image
); /* so that mono_image close, below, has something to do */
2718 } else if (new_status
!= MONO_IMAGE_OK
) {
2719 mono_image_close (image
);
2720 mono_error_set_bad_image_by_name (error
, "In Memory assembly", "0x%p was assembly binding redirected to another assembly that failed to load", assembly_data
);
2724 MonoAssemblyLoadRequest req
;
2725 mono_assembly_request_prepare_load (&req
, refonly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_INDIVIDUAL
, alc
);
2726 ass
= mono_assembly_request_load_from (image
, "", &req
, &status
);
2729 mono_image_close (image
);
2730 mono_error_set_bad_image_by_name (error
, "In Memory assembly", "0x%p", assembly_data
);
2734 /* Clear the reference added by mono_image_open_from_data_internal above */
2735 mono_image_close (image
);
2740 #ifndef ENABLE_NETCORE
2741 MonoReflectionAssemblyHandle
2742 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad
, MonoStringHandle assRef
, MonoObjectHandle evidence
, MonoBoolean refOnly
, MonoStackCrawlMark
*stack_mark
, MonoError
*error
)
2744 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
2745 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
2747 MonoAssemblyName aname
;
2751 g_assert (!MONO_HANDLE_IS_NULL (assRef
));
2753 name
= mono_string_handle_to_utf8 (assRef
, error
);
2754 goto_if_nok (error
, fail
);
2755 parsed
= mono_assembly_name_parse (name
, &aname
);
2759 MonoReflectionAssemblyHandle refass
= MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2760 /* This is a parse error... */
2762 MonoAssembly
*assm
= mono_try_assembly_resolve_handle (mono_domain_default_alc (domain
), assRef
, NULL
, refOnly
, error
);
2763 goto_if_nok (error
, fail
);
2765 refass
= mono_assembly_get_object_handle (domain
, assm
, error
);
2766 goto_if_nok (error
, fail
);
2772 MonoAssemblyContextKind asmctx
;
2773 asmctx
= refOnly
? MONO_ASMCTX_REFONLY
: MONO_ASMCTX_DEFAULT
;
2774 const char *basedir
;
2777 /* Determine if the current assembly is in LoadFrom context.
2778 * If it is, we must include the executing assembly's basedir
2779 * when probing for the given assembly name, and also load the
2780 * requested assembly in LoadFrom context.
2782 MonoAssembly
*executing_assembly
= mono_runtime_get_caller_from_stack_mark (stack_mark
);
2783 if (executing_assembly
&& mono_asmctx_get_kind (&executing_assembly
->context
) == MONO_ASMCTX_LOADFROM
) {
2784 asmctx
= MONO_ASMCTX_LOADFROM
;
2785 basedir
= executing_assembly
->basedir
;
2790 MonoAssemblyByNameRequest req
;
2791 mono_assembly_request_prepare_byname (&req
, asmctx
, mono_domain_default_alc (domain
));
2792 req
.basedir
= basedir
;
2793 req
.no_postload_search
= TRUE
;
2794 ass
= mono_assembly_request_byname (&aname
, &req
, &status
);
2795 mono_assembly_name_free (&aname
);
2798 /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
2800 ass
= mono_try_assembly_resolve_handle (mono_domain_default_alc (domain
), assRef
, NULL
, refOnly
, error
);
2801 goto_if_nok (error
, fail
);
2808 MonoReflectionAssemblyHandle refass
;
2809 refass
= mono_assembly_get_object_handle (domain
, ass
, error
);
2810 goto_if_nok (error
, fail
);
2812 MONO_HANDLE_SET (refass
, evidence
, evidence
);
2816 return MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
);
2820 ves_icall_System_AppDomain_InternalUnload (gint32 domain_id
, MonoError
*error
)
2822 MonoDomain
* domain
= mono_domain_get_by_id (domain_id
);
2824 if (NULL
== domain
) {
2825 mono_error_set_execution_engine (error
, "Failed to unload domain, domain id not found");
2829 if (domain
== mono_get_root_domain ()) {
2830 mono_error_set_generic_error (error
, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded.");
2835 * Unloading seems to cause problems when running NUnit/NAnt, hence
2838 if (g_hasenv ("MONO_NO_UNLOAD"))
2841 MonoException
*exc
= NULL
;
2842 mono_domain_try_unload (domain
, (MonoObject
**)&exc
);
2844 mono_error_set_exception_instance (error
, exc
);
2848 ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id
, MonoError
*error
)
2850 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
2855 return mono_domain_is_unloading (domain
);
2859 ves_icall_System_AppDomain_DoUnhandledException (MonoAppDomainHandle ad
, MonoExceptionHandle exc
, MonoError
*error
)
2861 mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject
, exc
), error
);
2862 mono_error_assert_ok (error
);
2866 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad
,
2867 MonoReflectionAssemblyHandle refass
, MonoArrayHandle args
,
2873 g_assert (!MONO_HANDLE_IS_NULL (refass
));
2874 MonoAssembly
*assembly
= MONO_HANDLE_GETVAL (refass
, assembly
);
2875 image
= assembly
->image
;
2878 method
= mono_get_method_checked (image
, mono_image_get_entry_point (image
), NULL
, NULL
, error
);
2881 g_error ("No entry point method found in %s due to %s", image
->name
, mono_error_get_message (error
));
2883 if (MONO_HANDLE_IS_NULL (args
)) {
2884 MonoDomain
*domain
= MONO_HANDLE_GETVAL (ad
, data
);
2885 MONO_HANDLE_ASSIGN (args
, mono_array_new_handle (domain
, mono_defaults
.string_class
, 0, error
));
2886 mono_error_assert_ok (error
);
2889 int res
= mono_runtime_exec_main_checked (method
, MONO_HANDLE_RAW (args
), error
);
2894 ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad
, MonoError
* error
)
2897 MonoDomain
*old_domain
= mono_domain_get ();
2899 if (!mono_domain_set_fast (MONO_HANDLE_GETVAL (ad
, data
), FALSE
)) {
2900 mono_error_set_appdomain_unloaded (error
);
2901 return MONO_HANDLE_CAST (MonoAppDomain
, NULL_HANDLE
);
2904 return MONO_HANDLE_NEW (MonoAppDomain
, old_domain
->domain
);
2908 ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid
, MonoError
*error
)
2910 MonoDomain
*current_domain
= mono_domain_get ();
2911 MonoDomain
*domain
= mono_domain_get_by_id (domainid
);
2913 if (!domain
|| !mono_domain_set_fast (domain
, FALSE
)) {
2914 mono_error_set_appdomain_unloaded (error
);
2915 return MONO_HANDLE_CAST (MonoAppDomain
, NULL_HANDLE
);
2918 return MONO_HANDLE_NEW (MonoAppDomain
, current_domain
->domain
);
2922 ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad
, MonoError
*error
)
2925 mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad
, data
));
2929 ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id
, MonoError
*error
)
2932 MonoDomain
*domain
= mono_domain_get_by_id (domain_id
);
2936 * Raise an exception to prevent the managed code from executing a pop
2939 mono_error_set_appdomain_unloaded (error
);
2943 mono_thread_push_appdomain_ref (domain
);
2947 ves_icall_System_AppDomain_InternalPopDomainRef (MonoError
*error
)
2950 mono_thread_pop_appdomain_ref ();
2953 MonoAppContextHandle
2954 ves_icall_System_AppDomain_InternalGetContext (MonoError
*error
)
2957 return mono_context_get_handle ();
2960 MonoAppContextHandle
2961 ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError
*error
)
2964 return MONO_HANDLE_NEW (MonoAppContext
, mono_domain_get ()->default_context
);
2967 MonoAppContextHandle
2968 ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc
, MonoError
*error
)
2971 MonoAppContextHandle old_context
= mono_context_get_handle ();
2973 mono_context_set_handle (mc
);
2979 ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid
, MonoError
*error
)
2982 MonoDomain
* mono_root_domain
= mono_get_root_domain ();
2983 mono_domain_lock (mono_root_domain
);
2984 if (process_guid_set
) {
2985 mono_domain_unlock (mono_root_domain
);
2986 return mono_string_new_utf16_handle (mono_domain_get (), process_guid
, sizeof(process_guid
)/2, error
);
2988 uint32_t gchandle
= mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject
, newguid
), TRUE
);
2989 memcpy (process_guid
, mono_string_chars_internal (MONO_HANDLE_RAW (newguid
)), sizeof(process_guid
));
2990 mono_gchandle_free_internal (gchandle
);
2991 process_guid_set
= TRUE
;
2992 mono_domain_unlock (mono_root_domain
);
2998 * mono_domain_is_unloading:
3001 mono_domain_is_unloading (MonoDomain
*domain
)
3003 if (domain
->state
== MONO_APPDOMAIN_UNLOADING
|| domain
->state
== MONO_APPDOMAIN_UNLOADED
)
3010 clear_cached_vtable (MonoVTable
*vtable
)
3012 MonoClass
*klass
= vtable
->klass
;
3013 MonoDomain
*domain
= vtable
->domain
;
3014 MonoClassRuntimeInfo
*runtime_info
;
3017 runtime_info
= m_class_get_runtime_info (klass
);
3018 if (runtime_info
&& runtime_info
->max_domain
>= domain
->domain_id
)
3019 runtime_info
->domain_vtables
[domain
->domain_id
] = NULL
;
3020 if (m_class_has_static_refs (klass
) && (data
= mono_vtable_get_static_field_data (vtable
)))
3021 mono_gc_free_fixed (data
);
3024 static G_GNUC_UNUSED
void
3025 zero_static_data (MonoVTable
*vtable
)
3027 MonoClass
*klass
= vtable
->klass
;
3030 if (m_class_has_static_refs (klass
) && (data
= mono_vtable_get_static_field_data (vtable
)))
3031 mono_gc_bzero_aligned (data
, mono_class_data_size (klass
));
3034 typedef struct unload_data
{
3037 char *failure_reason
;
3042 unload_data_unref (unload_data
*data
)
3048 mono_atomic_load_acquire (count
, gint32
, &data
->refcount
);
3049 g_assert (count
>= 1 && count
<= 2);
3054 } while (mono_atomic_cas_i32 (&data
->refcount
, count
- 1, count
) != count
);
3058 deregister_reflection_info_roots_from_list (MonoImage
*image
)
3060 GSList
*list
= image
->reflection_info_unregister_classes
;
3063 MonoClass
*klass
= (MonoClass
*)list
->data
;
3065 mono_class_free_ref_info (klass
);
3070 image
->reflection_info_unregister_classes
= NULL
;
3074 deregister_reflection_info_roots (MonoDomain
*domain
)
3078 mono_domain_assemblies_lock (domain
);
3079 for (list
= domain
->domain_assemblies
; list
; list
= list
->next
) {
3080 MonoAssembly
*assembly
= (MonoAssembly
*)list
->data
;
3081 MonoImage
*image
= assembly
->image
;
3085 * No need to take the image lock here since dynamic images are appdomain bound and
3086 * at this point the mutator is gone. Taking the image lock here would mean
3087 * promoting it from a simple lock to a complex lock, which we better avoid if
3090 if (image_is_dynamic (image
))
3091 deregister_reflection_info_roots_from_list (image
);
3093 for (i
= 0; i
< image
->module_count
; ++i
) {
3094 MonoImage
*module
= image
->modules
[i
];
3095 if (module
&& image_is_dynamic (module
))
3096 deregister_reflection_info_roots_from_list (module
);
3099 mono_domain_assemblies_unlock (domain
);
3103 unload_thread_main (void *arg
)
3105 unload_data
*data
= (unload_data
*)arg
;
3106 MonoDomain
*domain
= data
->domain
;
3108 gsize result
= 1; // failure
3110 mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Domain unloader", MonoSetThreadNameFlag_Permanent
);
3113 * FIXME: Abort our parent thread last, so we can return a failure
3114 * indication if aborting times out.
3116 if (!mono_threads_abort_appdomain_threads (domain
, -1)) {
3117 data
->failure_reason
= g_strdup_printf ("Aborting of threads in domain %s timed out.", domain
->friendly_name
);
3121 if (!mono_threadpool_remove_domain_jobs (domain
, -1)) {
3122 data
->failure_reason
= g_strdup_printf ("Cleanup of threadpool jobs of domain %s timed out.", domain
->friendly_name
);
3126 /* Finalize all finalizable objects in the doomed appdomain */
3127 if (!mono_domain_finalize (domain
, -1)) {
3128 data
->failure_reason
= g_strdup_printf ("Finalization of domain %s timed out.", domain
->friendly_name
);
3132 /* Clear references to our vtables in class->runtime_info.
3133 * We also hold the loader lock because we're going to change
3134 * class->runtime_info.
3137 mono_loader_lock ();
3138 mono_domain_lock (domain
);
3140 * We need to make sure that we don't have any remsets
3141 * pointing into static data of the to-be-freed domain because
3142 * at the next collections they would be invalid. So what we
3143 * do is we first zero all static data and then do a minor
3144 * collection. Because all references in the static data will
3145 * now be null we won't do any unnecessary copies and after
3146 * the collection there won't be any more remsets.
3148 for (i
= 0; i
< domain
->class_vtable_array
->len
; ++i
)
3149 zero_static_data ((MonoVTable
*)g_ptr_array_index (domain
->class_vtable_array
, i
));
3150 mono_gc_collect (0);
3151 for (i
= 0; i
< domain
->class_vtable_array
->len
; ++i
)
3152 clear_cached_vtable ((MonoVTable
*)g_ptr_array_index (domain
->class_vtable_array
, i
));
3153 deregister_reflection_info_roots (domain
);
3155 mono_assembly_cleanup_domain_bindings (domain
->domain_id
);
3157 mono_domain_unlock (domain
);
3158 mono_loader_unlock ();
3160 domain
->state
= MONO_APPDOMAIN_UNLOADED
;
3162 /* printf ("UNLOADED %s.\n", domain->friendly_name); */
3164 /* remove from the handle table the items related to this domain */
3165 mono_gchandle_free_domain (domain
);
3167 mono_domain_free (domain
, FALSE
);
3169 mono_gc_collect (mono_gc_max_generation ());
3171 result
= 0; // success
3173 mono_atomic_store_release (&data
->done
, TRUE
);
3174 unload_data_unref (data
);
3183 * mono_domain_unload:
3184 * \param domain The domain to unload
3186 * Unloads an appdomain. Follows the process outlined in the comment
3187 * for \c mono_domain_try_unload.
3190 mono_domain_unload (MonoDomain
*domain
)
3192 MONO_ENTER_GC_UNSAFE
;
3193 MonoObject
*exc
= NULL
;
3194 mono_domain_try_unload (domain
, &exc
);
3195 MONO_EXIT_GC_UNSAFE
;
3198 static MonoThreadInfoWaitRet
3199 guarded_wait (MonoThreadHandle
*thread_handle
, guint32 timeout
, gboolean alertable
)
3201 MonoThreadInfoWaitRet result
;
3204 result
= mono_thread_info_wait_one_handle (thread_handle
, timeout
, alertable
);
3211 * mono_domain_unload:
3212 * \param domain The domain to unload
3213 * \param exc Exception information
3215 * Unloads an appdomain. Follows the process outlined in:
3216 * http://blogs.gotdotnet.com/cbrumme
3218 * If doing things the 'right' way is too hard or complex, we do it the
3219 * 'simple' way, which means do everything needed to avoid crashes and
3220 * memory leaks, but not much else.
3222 * It is required to pass a valid reference to the exc argument, upon return
3223 * from this function *exc will be set to the exception thrown, if any.
3225 * If this method is not called from an icall (embedded scenario for instance),
3226 * it must not be called with any managed frames on the stack, since the unload
3227 * process could end up trying to abort the current thread.
3230 mono_domain_try_unload (MonoDomain
*domain
, MonoObject
**exc
)
3232 HANDLE_FUNCTION_ENTER ();
3234 MonoThreadHandle
*thread_handle
= NULL
;
3235 MonoAppDomainState prev_state
;
3237 unload_data
*thread_data
= NULL
;
3238 MonoInternalThreadHandle internal
;
3239 MonoDomain
*caller_domain
= mono_domain_get ();
3241 /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
3243 /* Atomically change our state to UNLOADING */
3244 prev_state
= (MonoAppDomainState
)mono_atomic_cas_i32 ((gint32
*)&domain
->state
,
3245 MONO_APPDOMAIN_UNLOADING_START
,
3246 MONO_APPDOMAIN_CREATED
);
3247 if (prev_state
!= MONO_APPDOMAIN_CREATED
) {
3248 switch (prev_state
) {
3249 case MONO_APPDOMAIN_UNLOADING_START
:
3250 case MONO_APPDOMAIN_UNLOADING
:
3251 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded.");
3253 case MONO_APPDOMAIN_UNLOADED
:
3254 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded.");
3257 g_warning ("Invalid appdomain state %d", prev_state
);
3258 g_assert_not_reached ();
3262 mono_domain_set_fast (domain
, FALSE
);
3263 /* Notify OnDomainUnload listeners */
3264 method
= mono_class_get_method_from_name_checked (domain
->domain
->mbr
.obj
.vtable
->klass
, "DoDomainUnload", -1, 0, error
);
3267 mono_runtime_try_invoke (method
, domain
->domain
, NULL
, exc
, error
);
3269 if (!is_ok (error
)) {
3271 mono_error_cleanup (error
);
3273 *exc
= (MonoObject
*)mono_error_convert_to_exception (error
);
3277 /* Roll back the state change */
3278 domain
->state
= MONO_APPDOMAIN_CREATED
;
3279 mono_domain_set_fast (caller_domain
, FALSE
);
3282 mono_domain_set_fast (caller_domain
, FALSE
);
3284 thread_data
= g_new0 (unload_data
, 1);
3285 thread_data
->domain
= domain
;
3286 thread_data
->failure_reason
= NULL
;
3287 thread_data
->done
= FALSE
;
3288 thread_data
->refcount
= 2; /*Must be 2: unload thread + initiator */
3290 /*The managed callback finished successfully, now we start tearing down the appdomain*/
3291 domain
->state
= MONO_APPDOMAIN_UNLOADING
;
3293 * First we create a separate thread for unloading, since
3294 * we might have to abort some threads, including the current one.
3296 * Have to attach to the runtime so shutdown can wait for this thread.
3298 * Force it to be attached to avoid racing during shutdown.
3300 internal
= mono_thread_create_internal_handle (mono_get_root_domain (), unload_thread_main
, thread_data
, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE
, error
);
3301 mono_error_assert_ok (error
);
3303 thread_handle
= mono_threads_open_thread_handle (MONO_HANDLE_GETVAL (internal
, handle
));
3305 /* Wait for the thread */
3306 while (!thread_data
->done
&& guarded_wait (thread_handle
, MONO_INFINITE_WAIT
, TRUE
) == MONO_THREAD_INFO_WAIT_RET_ALERTED
) {
3307 if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain
) && (mono_thread_interruption_requested ())) {
3308 /* The unload thread tries to abort us */
3309 /* The icall wrapper will execute the abort */
3314 if (thread_data
->failure_reason
) {
3315 /* Roll back the state change */
3316 domain
->state
= MONO_APPDOMAIN_CREATED
;
3318 g_warning ("%s", thread_data
->failure_reason
);
3320 *exc
= (MonoObject
*) mono_get_exception_cannot_unload_appdomain (thread_data
->failure_reason
);
3322 g_free (thread_data
->failure_reason
);
3323 thread_data
->failure_reason
= NULL
;
3327 mono_threads_close_thread_handle (thread_handle
);
3328 unload_data_unref (thread_data
);
3329 HANDLE_FUNCTION_RETURN ();
3332 #ifdef ENABLE_NETCORE
3334 /* Remember properties so they can be be installed in AppContext during runtime init */
3336 mono_runtime_register_appctx_properties (int nprops
, const char **keys
, const char **values
)
3338 n_appctx_props
= nprops
;
3339 appctx_keys
= g_new0 (char*, nprops
);
3340 appctx_values
= g_new0 (char*, nprops
);
3342 for (int i
= 0; i
< nprops
; ++i
) {
3343 appctx_keys
[i
] = g_strdup (keys
[i
]);
3344 appctx_values
[i
] = g_strdup (values
[i
]);
3348 static GENERATE_GET_CLASS_WITH_CACHE (appctx
, "System", "AppContext")
3350 /* Install properties into AppContext */
3352 mono_runtime_install_appctx_properties (void)
3357 MonoMethod
*setup
= mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error
);
3360 // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large
3362 /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */
3363 args
[0] = appctx_keys
;
3364 args
[1] = appctx_values
;
3365 args
[2] = &n_appctx_props
;
3367 mono_runtime_invoke_checked (setup
, NULL
, args
, error
);
3368 mono_error_assert_ok (error
);
3370 /* No longer needed */
3371 for (int i
= 0; i
< n_appctx_props
; ++i
) {
3372 g_free (appctx_keys
[i
]);
3373 g_free (appctx_values
[i
]);
3375 g_free (appctx_keys
);
3376 g_free (appctx_values
);
3378 appctx_values
= NULL
;