2 * assembly.c: Routines for loading assemblies.
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc. http://www.ximian.com
19 #include "rawbuffer.h"
20 #include <mono/metadata/loader.h>
21 #include <mono/metadata/tabledefs.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/domain-internals.h>
24 #include <mono/io-layer/io-layer.h>
25 #include <mono/utils/mono-uri.h>
26 #include <mono/metadata/mono-config.h>
27 #include <mono/utils/mono-digest.h>
28 #include <mono/utils/mono-logger.h>
30 #include <mono/os/util.h>
33 /* the default search path is just MONO_ASSEMBLIES */
40 /* Contains the list of directories to be searched for assemblies (MONO_PATH) */
41 static char **assemblies_path = NULL;
43 /* Contains the list of directories that point to auxiliary GACs */
44 static char **extra_gac_paths = NULL;
47 * keeps track of loaded assemblies
49 static GList *loaded_assemblies = NULL;
50 static MonoAssembly *corlib;
52 /* This protects loaded_assemblies and image->references */
53 static CRITICAL_SECTION assemblies_mutex;
55 /* A hastable of thread->assembly list mappings */
56 static GHashTable *assemblies_loading;
58 /* If defined, points to the bundled assembly information */
59 const MonoBundledAssembly **bundles;
62 encode_public_tok (const guchar *token, gint32 len)
64 const static gchar allowed [] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
68 res = g_malloc (len * 2 + 1);
69 for (i = 0; i < len; i++) {
70 res [i * 2] = allowed [token [i] >> 4];
71 res [i * 2 + 1] = allowed [token [i] & 0xF];
83 path = g_getenv ("MONO_PATH");
87 splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000);
89 g_strfreev (assemblies_path);
90 assemblies_path = splitted;
91 if (g_getenv ("MONO_DEBUG") == NULL)
95 if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR))
96 g_warning ("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *splitted);
103 check_extra_gac_path_env (void) {
107 path = g_getenv ("MONO_GAC_PREFIX");
111 splitted = g_strsplit (path, G_SEARCHPATH_SEPARATOR_S, 1000);
113 g_strfreev (extra_gac_paths);
114 extra_gac_paths = splitted;
115 if (g_getenv ("MONO_DEBUG") == NULL)
119 if (**splitted && !g_file_test (*splitted, G_FILE_TEST_IS_DIR))
120 g_warning ("'%s' in MONO_GAC_PATH doesn't exist or has wrong permissions.", *splitted);
127 mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r)
129 if (!l->name || !r->name)
132 if (strcmp (l->name, r->name))
135 if (l->culture && r->culture && strcmp (l->culture, r->culture))
138 if (l->major != r->major || l->minor != r->minor ||
139 l->build != r->build || l->revision != r->revision)
140 if (! ((l->major == 0 && l->minor == 0 && l->build == 0 && l->revision == 0) || (r->major == 0 && r->minor == 0 && r->build == 0 && r->revision == 0)))
143 if (!l->public_key_token [0] || !r->public_key_token [0])
146 if (strcmp (l->public_key_token, r->public_key_token))
153 search_loaded (MonoAssemblyName* aname)
159 ass = mono_assembly_invoke_search_hook (aname);
164 * The assembly might be under load by this thread. In this case, it is
165 * safe to return an incomplete instance to prevent loops.
167 loading = g_hash_table_lookup (assemblies_loading, GetCurrentThread ());
168 for (tmp = loading; tmp; tmp = tmp->next) {
170 if (!mono_assembly_names_equal (aname, &ass->aname))
179 static MonoAssembly *
180 load_in_path (const char *basename, const char** search_path, MonoImageOpenStatus *status)
184 MonoAssembly *result;
186 for (i = 0; search_path [i]; ++i) {
187 fullpath = g_build_filename (search_path [i], basename, NULL);
188 result = mono_assembly_open (fullpath, status);
197 * mono_assembly_setrootdir:
198 * @root_dir: The pathname of the root directory where we will locate assemblies
200 * This routine sets the internal default root directory for looking up
201 * assemblies. This is used by Windows installations to compute dynamically
202 * the place where the Mono assemblies are located.
206 mono_assembly_setrootdir (const char *root_dir)
209 * Override the MONO_ASSEMBLIES directory configured at compile time.
211 /* Leak if called more than once */
212 default_path [0] = g_strdup (root_dir);
215 G_CONST_RETURN gchar *
216 mono_assembly_getrootdir (void)
218 return default_path [0];
222 * mono_assemblies_init:
224 * Initialize global variables used by this module.
227 mono_assemblies_init (void)
229 #ifdef PLATFORM_WIN32
234 check_extra_gac_path_env ();
236 InitializeCriticalSection (&assemblies_mutex);
238 assemblies_loading = g_hash_table_new (NULL, NULL);
242 mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
244 MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLY];
245 guint32 cols [MONO_ASSEMBLY_SIZE];
250 mono_metadata_decode_row (t, 0, cols, MONO_ASSEMBLY_SIZE);
253 aname->hash_value = NULL;
254 aname->name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_NAME]);
255 aname->culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLY_CULTURE]);
256 aname->flags = cols [MONO_ASSEMBLY_FLAGS];
257 aname->major = cols [MONO_ASSEMBLY_MAJOR_VERSION];
258 aname->minor = cols [MONO_ASSEMBLY_MINOR_VERSION];
259 aname->build = cols [MONO_ASSEMBLY_BUILD_NUMBER];
260 aname->revision = cols [MONO_ASSEMBLY_REV_NUMBER];
261 aname->hash_alg = cols [MONO_ASSEMBLY_HASH_ALG];
262 if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) {
263 gchar* token = g_malloc (8);
267 aname->public_key = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]);
268 len = mono_metadata_decode_blob_size (aname->public_key, (const char**)&aname->public_key);
270 mono_digest_get_public_token (token, aname->public_key, len);
271 encoded = encode_public_tok (token, 8);
272 g_strlcpy (aname->public_key_token, encoded, MONO_PUBLIC_KEY_TOKEN_LENGTH);
278 aname->public_key = NULL;
279 memset (aname->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
282 if (cols [MONO_ASSEMBLY_PUBLIC_KEY]) {
283 aname->public_key = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLY_PUBLIC_KEY]);
286 aname->public_key = 0;
292 assemblyref_public_tok (MonoImage *image, guint32 key_index, guint32 flags)
294 const gchar *public_tok;
297 public_tok = mono_metadata_blob_heap (image, key_index);
298 len = mono_metadata_decode_blob_size (public_tok, &public_tok);
300 if (flags & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG) {
302 mono_digest_get_public_token (token, public_tok, len);
303 return encode_public_tok (token, 8);
306 return encode_public_tok (public_tok, len);
310 mono_assembly_load_reference (MonoImage *image, int index)
313 guint32 cols [MONO_ASSEMBLYREF_SIZE];
315 MonoAssembly *reference;
316 MonoAssemblyName aname;
317 MonoImageOpenStatus status;
320 * image->references is shared between threads, so we need to access
321 * it inside a critical section.
323 EnterCriticalSection (&assemblies_mutex);
324 reference = image->references [index];
325 LeaveCriticalSection (&assemblies_mutex);
329 t = &image->tables [MONO_TABLE_ASSEMBLYREF];
331 mono_metadata_decode_row (t, index, cols, MONO_ASSEMBLYREF_SIZE);
333 hash = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_HASH_VALUE]);
334 aname.hash_len = mono_metadata_decode_blob_size (hash, &hash);
335 aname.hash_value = hash;
336 aname.name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME]);
337 aname.culture = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]);
338 aname.flags = cols [MONO_ASSEMBLYREF_FLAGS];
339 aname.major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
340 aname.minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
341 aname.build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
342 aname.revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
344 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
345 gchar *token = assemblyref_public_tok (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY], aname.flags);
346 g_strlcpy (aname.public_key_token, token, MONO_PUBLIC_KEY_TOKEN_LENGTH);
349 memset (aname.public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
352 reference = mono_assembly_load (&aname, image->assembly->basedir, &status);
354 if (reference == NULL){
356 ** Temporary work around: any System.* which are 3300 build, will get
357 ** remapped, this is to keep old applications running that might have
358 ** been linked against our 5000 API, before we were strongnamed, and
359 ** hence were labeled as 3300 builds by reflection.c
361 if (aname.build == 3300 && strncmp (aname.name, "System", 6) == 0){
364 reference = mono_assembly_load (&aname, image->assembly->basedir, &status);
366 if (reference != NULL){
367 if (g_getenv ("MONO_SILENT_WARNING") == NULL)
368 g_printerr ("Compat mode: the request from %s to load %s was remapped (http://www.go-mono.com/remap.html)\n",
369 image->name, aname.name);
372 char *extra_msg = g_strdup ("");
374 if (status == MONO_IMAGE_ERROR_ERRNO) {
375 extra_msg = g_strdup_printf ("System error: %s\n", strerror (errno));
376 } else if (status == MONO_IMAGE_MISSING_ASSEMBLYREF) {
377 extra_msg = g_strdup ("Cannot find an assembly referenced from this one.\n");
378 } else if (status == MONO_IMAGE_IMAGE_INVALID) {
379 extra_msg = g_strdup ("The file exists but is not a valid assembly.\n");
382 g_warning ("Could not find assembly %s, references from %s (assemblyref_index=%d)\n"
383 " Major/Minor: %d,%d\n"
386 aname.name, image->name, index,
387 aname.major, aname.minor, aname.build, aname.revision,
388 aname.public_key_token, extra_msg);
393 if (reference == NULL)
394 /* Flag as not found */
395 reference = (gpointer)-1;
397 EnterCriticalSection (&assemblies_mutex);
398 if (!image->references [index])
399 image->references [index] = reference;
400 LeaveCriticalSection (&assemblies_mutex);
402 if (image->references [index] != reference) {
403 /* Somebody loaded it before us */
404 mono_assembly_close (reference);
409 mono_assembly_load_references (MonoImage *image, MonoImageOpenStatus *status)
414 *status = MONO_IMAGE_OK;
416 t = &image->tables [MONO_TABLE_ASSEMBLYREF];
418 image->references = g_new0 (MonoAssembly *, t->rows + 1);
420 /* resolve assembly references for modules */
421 for (i = 0; i < image->module_count; i++){
422 if (image->modules [i]) {
423 image->modules [i]->assembly = image->assembly;
424 mono_assembly_load_references (image->modules [i], status);
429 typedef struct AssemblyLoadHook AssemblyLoadHook;
430 struct AssemblyLoadHook {
431 AssemblyLoadHook *next;
432 MonoAssemblyLoadFunc func;
436 AssemblyLoadHook *assembly_load_hook = NULL;
439 mono_assembly_invoke_load_hook (MonoAssembly *ass)
441 AssemblyLoadHook *hook;
443 for (hook = assembly_load_hook; hook; hook = hook->next) {
444 hook->func (ass, hook->user_data);
449 mono_install_assembly_load_hook (MonoAssemblyLoadFunc func, gpointer user_data)
451 AssemblyLoadHook *hook;
453 g_return_if_fail (func != NULL);
455 hook = g_new0 (AssemblyLoadHook, 1);
457 hook->user_data = user_data;
458 hook->next = assembly_load_hook;
459 assembly_load_hook = hook;
462 typedef struct AssemblySearchHook AssemblySearchHook;
463 struct AssemblySearchHook {
464 AssemblySearchHook *next;
465 MonoAssemblySearchFunc func;
469 AssemblySearchHook *assembly_search_hook = NULL;
472 mono_assembly_invoke_search_hook (MonoAssemblyName *aname)
474 AssemblySearchHook *hook;
476 for (hook = assembly_search_hook; hook; hook = hook->next) {
477 MonoAssembly *ass = hook->func (aname, hook->user_data);
486 mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
488 AssemblySearchHook *hook;
490 g_return_if_fail (func != NULL);
492 hook = g_new0 (AssemblySearchHook, 1);
494 hook->user_data = user_data;
495 hook->next = assembly_search_hook;
496 assembly_search_hook = hook;
499 typedef struct AssemblyPreLoadHook AssemblyPreLoadHook;
500 struct AssemblyPreLoadHook {
501 AssemblyPreLoadHook *next;
502 MonoAssemblyPreLoadFunc func;
506 AssemblyPreLoadHook *assembly_preload_hook = NULL;
508 static MonoAssembly *
509 invoke_assembly_preload_hook (MonoAssemblyName *aname, gchar **assemblies_path)
511 AssemblyPreLoadHook *hook;
512 MonoAssembly *assembly;
514 for (hook = assembly_preload_hook; hook; hook = hook->next) {
515 assembly = hook->func (aname, assemblies_path, hook->user_data);
516 if (assembly != NULL)
524 mono_install_assembly_preload_hook (MonoAssemblyPreLoadFunc func, gpointer user_data)
526 AssemblyPreLoadHook *hook;
528 g_return_if_fail (func != NULL);
530 hook = g_new0 (AssemblyPreLoadHook, 1);
532 hook->user_data = user_data;
533 hook->next = assembly_preload_hook;
534 assembly_preload_hook = hook;
538 absolute_dir (const gchar *filename)
549 if (g_path_is_absolute (filename))
550 return g_path_get_dirname (filename);
552 cwd = g_get_current_dir ();
553 mixed = g_build_filename (cwd, filename, NULL);
554 parts = g_strsplit (mixed, G_DIR_SEPARATOR_S, 0);
559 for (i = 0; (part = parts [i]) != NULL; i++) {
560 if (!strcmp (part, "."))
563 if (!strcmp (part, "..")) {
564 if (list && list->next) /* Don't remove root */
565 list = g_list_delete_link (list, list);
567 list = g_list_prepend (list, part);
571 result = g_string_new ("");
572 list = g_list_reverse (list);
574 /* Ignores last data pointer, which should be the filename */
575 for (tmp = list; tmp && tmp->next != NULL; tmp = tmp->next)
577 g_string_append_printf (result, "%s%c", (char *) tmp->data,
581 g_string_free (result, FALSE);
586 return g_strdup (".");
593 * mono_assembly_open_from_bundle:
594 * @filename: Filename requested
595 * @status: return value
597 * This routine tries to open the assembly specified by `filename' from the
598 * defined bundles, if found, returns the MonoImage for it, if not found
602 mono_assembly_open_from_bundle (const char *filename, MonoImageOpenStatus *status)
605 char *name = g_path_get_basename (filename);
606 char *dot = strrchr (name, '.');
607 MonoImage *image = NULL;
610 * we do a very simple search for bundled assemblies: it's not a general
611 * purpose assembly loading mechanism.
613 EnterCriticalSection (&assemblies_mutex);
614 for (i = 0; !image && bundles [i]; ++i) {
615 if (strcmp (bundles [i]->name, name) == 0) {
616 image = mono_image_open_from_data ((char*)bundles [i]->data, bundles [i]->size, FALSE, status);
620 LeaveCriticalSection (&assemblies_mutex);
623 mono_image_addref (image);
630 do_mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
632 MonoImage *image = NULL;
634 if (bundles != NULL){
635 image = mono_assembly_open_from_bundle (filename, status);
640 EnterCriticalSection (&assemblies_mutex);
641 image = mono_image_open (filename, status);
642 LeaveCriticalSection (&assemblies_mutex);
648 * mono_assembly_open:
649 * @filename: Opens the assembly pointed out by this name
650 * @status: where a status code can be returned
652 * mono_assembly_open opens the PE-image pointed by @filename, and
653 * loads any external assemblies referenced by it.
655 * NOTE: we could do lazy loading of the assemblies. Or maybe not worth
659 mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
663 MonoImageOpenStatus def_status;
666 g_return_val_if_fail (filename != NULL, NULL);
669 status = &def_status;
670 *status = MONO_IMAGE_OK;
672 if (strncmp (filename, "file://", 7) == 0) {
673 GError *error = NULL;
674 gchar *uri = (gchar *) filename;
678 * MS allows file://c:/... and fails on file://localhost/c:/...
679 * They also throw an IndexOutOfRangeException if "file://"
682 uri = g_strdup_printf ("file:///%s", uri + 7);
685 uri = mono_escape_uri_string (tmpuri);
686 fname = g_filename_from_uri (uri, NULL, &error);
689 if (tmpuri != filename)
693 g_warning ("%s\n", error->message);
694 g_error_free (error);
695 fname = g_strdup (filename);
698 fname = g_strdup (filename);
701 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY,
702 "Assembly Loader probing location: '%s'.", filename);
703 image = do_mono_assembly_open (fname, status);
706 *status = MONO_IMAGE_ERROR_ERRNO;
711 ass = mono_assembly_load_from (image, fname, status);
714 mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY,
715 "Assembly Loader loaded assembly from location: '%s'.", filename);
716 mono_config_for_assembly (ass->image);
725 mono_assembly_load_from (MonoImage *image, const char*fname,
726 MonoImageOpenStatus *status)
728 MonoAssembly *ass, *ass2;
732 #if defined (PLATFORM_WIN32)
737 tmp_fn = g_strdup (fname);
738 for (i = strlen (tmp_fn) - 1; i >= 0; i--) {
739 if (tmp_fn [i] == '/')
743 base_dir = absolute_dir (tmp_fn);
747 base_dir = absolute_dir (fname);
751 * To avoid deadlocks and scalability problems, we load assemblies outside
752 * the assembly lock. This means that multiple threads might try to load
753 * the same assembly at the same time. The first one to load it completely
754 * "wins", the other threads free their copy and use the one loaded by
755 * the winning thread.
759 * Create assembly struct, and enter it into the assembly cache
761 ass = g_new0 (MonoAssembly, 1);
762 ass->basedir = base_dir;
765 mono_assembly_fill_assembly_name (image, &ass->aname);
768 * Atomically search the loaded list and add ourselves to it if necessary.
770 EnterCriticalSection (&assemblies_mutex);
772 /* avoid loading the same assembly twice for now... */
773 if ((ass2 = search_loaded (&ass->aname))) {
776 mono_image_close (image);
777 *status = MONO_IMAGE_OK;
778 LeaveCriticalSection (&assemblies_mutex);
781 loading = g_hash_table_lookup (assemblies_loading, GetCurrentThread ());
782 loading = g_list_prepend (loading, ass);
783 g_hash_table_insert (assemblies_loading, GetCurrentThread (), loading);
784 LeaveCriticalSection (&assemblies_mutex);
786 image->assembly = ass;
788 mono_assembly_load_references (image, status);
790 EnterCriticalSection (&assemblies_mutex);
792 loading = g_hash_table_lookup (assemblies_loading, GetCurrentThread ());
793 loading = g_list_remove (loading, ass);
795 /* Prevent memory leaks */
796 g_hash_table_remove (assemblies_loading, GetCurrentThread ());
798 g_hash_table_insert (assemblies_loading, GetCurrentThread (), loading);
799 if (*status != MONO_IMAGE_OK) {
800 LeaveCriticalSection (&assemblies_mutex);
801 mono_assembly_close (ass);
805 if (ass->aname.name) {
806 ass2 = search_loaded (&ass->aname);
808 /* Somebody else has loaded the assembly before us */
809 LeaveCriticalSection (&assemblies_mutex);
810 mono_assembly_close (ass);
815 loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
816 LeaveCriticalSection (&assemblies_mutex);
818 mono_assembly_invoke_load_hook (ass);
824 probe_for_partial_name (const char *basepath, const char *fullname, MonoImageOpenStatus *status)
826 MonoAssembly *res = NULL;
829 const char* direntry;
831 dirhandle = g_dir_open (basepath, 0, NULL);
835 while ((direntry = g_dir_read_name (dirhandle))) {
836 fullpath = g_build_path (G_DIR_SEPARATOR_S, basepath, direntry, fullname, NULL);
837 res = mono_assembly_open (fullpath, status);
842 g_dir_close (dirhandle);
848 mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *status)
851 MonoAssemblyName aname;
852 gchar *fullname, *gacpath;
855 memset (&aname, 0, sizeof (MonoAssemblyName));
858 res = invoke_assembly_preload_hook (&aname, assemblies_path);
864 res = mono_assembly_loaded (&aname);
868 fullname = g_strdup_printf ("%s.dll", name);
870 if (extra_gac_paths) {
871 paths = extra_gac_paths;
872 while (!res && *paths) {
873 gacpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", name, NULL);
874 res = probe_for_partial_name (gacpath, fullname, status);
887 gacpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (), "mono", "gac", name, NULL);
888 res = probe_for_partial_name (gacpath, fullname, status);
900 * mono_assembly_load_from_gac
902 * @aname: The assembly name object
905 mono_assembly_load_from_gac (MonoAssemblyName *aname, gchar *filename, MonoImageOpenStatus *status)
907 MonoAssembly *result = NULL;
908 gchar *name, *version, *culture, *fullpath, *subpath;
912 if (aname->public_key_token [0] == 0) {
916 if (strstr (aname->name, ".dll")) {
917 len = strlen (filename) - 4;
918 name = g_malloc (len);
919 strncpy (name, aname->name, len);
921 name = g_strdup (aname->name);
924 if (aname->culture) {
925 culture = g_strdup (aname->culture);
928 culture = g_strdup ("");
931 version = g_strdup_printf ("%d.%d.%d.%d_%s_%s", aname->major,
932 aname->minor, aname->build, aname->revision,
933 culture, aname->public_key_token);
935 subpath = g_build_path (G_DIR_SEPARATOR_S, name, version, filename, NULL);
940 if (extra_gac_paths) {
941 paths = extra_gac_paths;
942 while (!result && *paths) {
943 fullpath = g_build_path (G_DIR_SEPARATOR_S, *paths, "lib", "mono", "gac", subpath, NULL);
944 result = mono_assembly_open (fullpath, status);
951 result->in_gac = TRUE;
956 fullpath = g_build_path (G_DIR_SEPARATOR_S, mono_assembly_getrootdir (),
957 "mono", "gac", subpath, NULL);
958 result = mono_assembly_open (fullpath, status);
962 result->in_gac = TRUE;
971 mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenStatus *status)
973 MonoAssembly *result;
974 char *fullpath, *filename;
976 result = invoke_assembly_preload_hook (aname, assemblies_path);
978 result->in_gac = FALSE;
982 result = mono_assembly_loaded (aname);
986 /* g_print ("loading %s\n", aname->name); */
987 /* special case corlib */
988 if (strcmp (aname->name, "mscorlib") == 0) {
991 /* g_print ("corlib already loaded\n"); */
994 /* g_print ("corlib load\n"); */
995 if (assemblies_path) {
996 corlib = load_in_path ("mscorlib.dll", (const char**)assemblies_path, status);
1000 corlib = load_in_path ("mscorlib.dll", default_path, status);
1005 /* Load corlib from mono/<version> */
1007 corlib_file = g_build_filename ("mono", mono_get_framework_version (), "mscorlib.dll", NULL);
1008 if (assemblies_path) {
1009 corlib = load_in_path (corlib_file, (const char**)assemblies_path, status);
1011 g_free (corlib_file);
1015 corlib = load_in_path (corlib_file, default_path, status);
1016 g_free (corlib_file);
1021 if (strstr (aname->name, ".dll"))
1022 filename = g_strdup (aname->name);
1024 filename = g_strconcat (aname->name, ".dll", NULL);
1026 result = mono_assembly_load_from_gac (aname, filename, status);
1033 fullpath = g_build_filename (basedir, filename, NULL);
1034 result = mono_assembly_open (fullpath, status);
1037 result->in_gac = FALSE;
1043 result = load_in_path (filename, default_path, status);
1045 result->in_gac = FALSE;
1051 mono_assembly_loaded (MonoAssemblyName *aname)
1055 EnterCriticalSection (&assemblies_mutex);
1056 res = search_loaded (aname);
1057 LeaveCriticalSection (&assemblies_mutex);
1063 mono_assembly_close (MonoAssembly *assembly)
1068 g_return_if_fail (assembly != NULL);
1070 EnterCriticalSection (&assemblies_mutex);
1071 if (--assembly->ref_count != 0) {
1072 LeaveCriticalSection (&assemblies_mutex);
1075 loaded_assemblies = g_list_remove (loaded_assemblies, assembly);
1076 LeaveCriticalSection (&assemblies_mutex);
1077 image = assembly->image;
1078 if (image->references) {
1079 for (i = 0; image->references [i] != NULL; i++)
1080 if (image->references [i] && (image->references [i] != (gpointer)-1))
1081 mono_image_close (image->references [i]->image);
1082 g_free (image->references);
1085 mono_image_close (assembly->image);
1087 g_free (assembly->basedir);
1092 mono_assembly_load_module (MonoAssembly *assembly, guint32 idx)
1094 MonoImageOpenStatus status;
1097 module = mono_image_load_file_for_image (assembly->image, idx);
1099 mono_assembly_load_references (module, &status);
1105 mono_assembly_foreach (GFunc func, gpointer user_data)
1110 * We make a copy of the list to avoid calling the callback inside the
1111 * lock, which could lead to deadlocks.
1113 EnterCriticalSection (&assemblies_mutex);
1114 copy = g_list_copy (loaded_assemblies);
1115 LeaveCriticalSection (&assemblies_mutex);
1117 g_list_foreach (loaded_assemblies, func, user_data);
1123 * Holds the assembly of the application, for
1124 * System.Diagnostics.Process::MainModule
1126 static MonoAssembly *main_assembly=NULL;
1129 mono_assembly_set_main (MonoAssembly *assembly)
1131 main_assembly=assembly;
1135 mono_assembly_get_main (void)
1137 return(main_assembly);
1141 mono_assembly_get_image (MonoAssembly *assembly)
1143 return assembly->image;
1147 mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies)
1149 bundles = assemblies;