2 * assembly.c: Routines for loading assemblies.
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
18 #include "object-internals.h"
19 #include <mono/metadata/loader.h>
20 #include <mono/metadata/tabledefs.h>
21 #include <mono/metadata/metadata-internals.h>
22 #include <mono/metadata/profiler-private.h>
23 #include <mono/metadata/class-internals.h>
24 #include <mono/metadata/domain-internals.h>
25 #include <mono/metadata/mono-endian.h>
26 #include <mono/metadata/mono-debug.h>
27 #include <mono/io-layer/io-layer.h>
28 #include <mono/utils/mono-uri.h>
29 #include <mono/metadata/mono-config.h>
30 #include <mono/utils/mono-digest.h>
31 #include <mono/utils/mono-logger.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/coree.h>
35 #ifndef PLATFORM_WIN32
36 #include <sys/types.h>
41 /* AssemblyVersionMap: an assembly name and the assembly version set on which it is based */
43 const char* assembly_name
;
44 guint8 version_set_index
;
47 /* the default search path is empty, the first slot is replaced with the computed value */
54 /* Contains the list of directories to be searched for assemblies (MONO_PATH) */
55 static char **assemblies_path
= NULL
;
57 /* Contains the list of directories that point to auxiliary GACs */
58 static char **extra_gac_paths
= NULL
;
60 /* The list of system assemblies what will be remapped to the running
61 * runtime version. WARNING: this list must be sorted.
63 static const AssemblyVersionMap framework_assemblies
[] = {
65 {"Commons.Xml.Relaxng", 0},
72 {"Microsoft.VisualBasic", 1},
73 {"Microsoft.VisualC", 1},
75 {"Mono.CompilerServices.SymbolWriter", 0},
77 {"Mono.Data.SybaseClient", 0},
79 {"Mono.Data.TdsClient", 0},
80 {"Mono.GetOptions", 0},
84 {"Mono.Security.Win32", 0},
86 {"Novell.Directory.Ldap", 0},
90 {"System.Configuration.Install", 0},
92 {"System.Data.OracleClient", 0},
93 {"System.Data.SqlXml", 0},
95 {"System.DirectoryServices", 0},
96 {"System.Drawing", 0},
97 {"System.Drawing.Design", 0},
98 {"System.EnterpriseServices", 0},
99 {"System.Management", 0},
100 {"System.Messaging", 0},
101 {"System.Runtime.Remoting", 0},
102 {"System.Runtime.Serialization.Formatters.Soap", 0},
103 {"System.Security", 0},
104 {"System.ServiceProcess", 0},
106 {"System.Web.Mobile", 0},
107 {"System.Web.Services", 0},
108 {"System.Windows.Forms", 0},
114 * keeps track of loaded assemblies
116 static GList
*loaded_assemblies
= NULL
;
117 static MonoAssembly
*corlib
;
119 /* This protects loaded_assemblies and image->references */
120 #define mono_assemblies_lock() EnterCriticalSection (&assemblies_mutex)
121 #define mono_assemblies_unlock() LeaveCriticalSection (&assemblies_mutex)
122 static CRITICAL_SECTION assemblies_mutex
;
124 /* If defined, points to the bundled assembly information */
125 const MonoBundledAssembly
**bundles
;
127 /* Loaded assembly binding info */
128 static GSList
*loaded_assembly_bindings
= NULL
;
131 mono_assembly_invoke_search_hook_internal (MonoAssemblyName
*aname
, gboolean refonly
, gboolean postload
);
134 encode_public_tok (const guchar
*token
, gint32 len
)
136 const static gchar allowed
[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
140 res
= g_malloc (len
* 2 + 1);
141 for (i
= 0; i
< len
; i
++) {
142 res
[i
* 2] = allowed
[token
[i
] >> 4];
143 res
[i
* 2 + 1] = allowed
[token
[i
] & 0xF];
150 * mono_public_tokens_are_equal:
151 * @pubt1: first public key token
152 * @pubt2: second public key token
154 * Compare two public key tokens and return #TRUE is they are equal and #FALSE
158 mono_public_tokens_are_equal (const unsigned char *pubt1
, const unsigned char *pubt2
)
160 return g_strcasecmp ((char*)pubt1
, (char*)pubt2
) == 0;
164 check_path_env (void)
167 char **splitted
, **dest
;
169 path
= g_getenv ("MONO_PATH");
173 splitted
= g_strsplit (path
, G_SEARCHPATH_SEPARATOR_S
, 1000);
175 g_strfreev (assemblies_path
);
176 assemblies_path
= dest
= splitted
;
184 if (g_getenv ("MONO_DEBUG") == NULL
)
188 if (**splitted
&& !g_file_test (*splitted
, G_FILE_TEST_IS_DIR
))
189 g_warning ("'%s' in MONO_PATH doesn't exist or has wrong permissions.", *splitted
);
196 check_extra_gac_path_env (void) {
198 char **splitted
, **dest
;
200 path
= g_getenv ("MONO_GAC_PREFIX");
204 splitted
= g_strsplit (path
, G_SEARCHPATH_SEPARATOR_S
, 1000);
206 g_strfreev (extra_gac_paths
);
207 extra_gac_paths
= dest
= splitted
;
215 if (g_getenv ("MONO_DEBUG") == NULL
)
219 if (**splitted
&& !g_file_test (*splitted
, G_FILE_TEST_IS_DIR
))
220 g_warning ("'%s' in MONO_GAC_PATH doesn't exist or has wrong permissions.", *splitted
);
227 assembly_binding_maps_name (MonoAssemblyBindingInfo
*info
, MonoAssemblyName
*aname
)
229 if (strcmp (info
->name
, aname
->name
))
232 if (info
->major
!= aname
->major
|| info
->minor
!= aname
->minor
)
235 if ((info
->culture
!= NULL
) != (aname
->culture
!= NULL
))
238 if (info
->culture
&& strcmp (info
->culture
, aname
->culture
))
241 if (!mono_public_tokens_are_equal (info
->public_key_token
, aname
->public_key_token
))
248 mono_assembly_binding_info_free (MonoAssemblyBindingInfo
*info
)
251 g_free (info
->culture
);
255 get_publisher_policy_info (MonoImage
*image
, MonoAssemblyName
*aname
, MonoAssemblyBindingInfo
*binding_info
)
258 guint32 cols
[MONO_MANIFEST_SIZE
];
259 const gchar
*filename
;
260 gchar
*subpath
, *fullpath
;
262 t
= &image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
263 /* MS Impl. accepts policy assemblies with more than
264 * one manifest resource, and only takes the first one */
266 binding_info
->is_valid
= FALSE
;
270 mono_metadata_decode_row (t
, 0, cols
, MONO_MANIFEST_SIZE
);
271 if ((cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) != MONO_IMPLEMENTATION_FILE
) {
272 binding_info
->is_valid
= FALSE
;
276 filename
= mono_metadata_string_heap (image
, cols
[MONO_MANIFEST_NAME
]);
277 g_assert (filename
!= NULL
);
279 subpath
= g_path_get_dirname (image
->name
);
280 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, subpath
, filename
, NULL
);
281 mono_config_parse_publisher_policy (fullpath
, binding_info
);
285 /* Define the optional elements/attributes before checking */
286 if (!binding_info
->culture
)
287 binding_info
->culture
= g_strdup ("");
289 /* Check that the most important elements/attributes exist */
290 if (!binding_info
->name
|| !binding_info
->public_key_token
[0] || !binding_info
->has_old_version_bottom
||
291 !binding_info
->has_new_version
|| !assembly_binding_maps_name (binding_info
, aname
)) {
292 mono_assembly_binding_info_free (binding_info
);
293 binding_info
->is_valid
= FALSE
;
297 binding_info
->is_valid
= TRUE
;
301 compare_versions (AssemblyVersionSet
*v
, MonoAssemblyName
*aname
)
303 if (v
->major
> aname
->major
)
305 else if (v
->major
< aname
->major
)
308 if (v
->minor
> aname
->minor
)
310 else if (v
->minor
< aname
->minor
)
313 if (v
->build
> aname
->build
)
315 else if (v
->build
< aname
->build
)
318 if (v
->revision
> aname
->revision
)
320 else if (v
->revision
< aname
->revision
)
327 check_policy_versions (MonoAssemblyBindingInfo
*info
, MonoAssemblyName
*name
)
332 /* If has_old_version_top doesn't exist, we don't have an interval */
333 if (!info
->has_old_version_top
) {
334 if (compare_versions (&info
->old_version_bottom
, name
) == 0)
340 /* Check that the version defined by name is valid for the interval */
341 if (compare_versions (&info
->old_version_top
, name
) < 0)
344 /* We should be greater or equal than the small version */
345 if (compare_versions (&info
->old_version_bottom
, name
) > 0)
352 * mono_assembly_names_equal:
354 * @r: second assembly.
356 * Compares two MonoAssemblyNames and returns whether they are equal.
358 * This compares the names, the cultures, the release version and their
361 * Returns: TRUE if both assembly names are equal.
364 mono_assembly_names_equal (MonoAssemblyName
*l
, MonoAssemblyName
*r
)
366 if (!l
->name
|| !r
->name
)
369 if (strcmp (l
->name
, r
->name
))
372 if (l
->culture
&& r
->culture
&& strcmp (l
->culture
, r
->culture
))
375 if (l
->major
!= r
->major
|| l
->minor
!= r
->minor
||
376 l
->build
!= r
->build
|| l
->revision
!= r
->revision
)
377 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)))
380 if (!l
->public_key_token
[0] || !r
->public_key_token
[0])
383 if (!mono_public_tokens_are_equal (l
->public_key_token
, r
->public_key_token
))
389 static MonoAssembly
*
390 load_in_path (const char *basename
, const char** search_path
, MonoImageOpenStatus
*status
, MonoBoolean refonly
)
394 MonoAssembly
*result
;
396 for (i
= 0; search_path
[i
]; ++i
) {
397 fullpath
= g_build_filename (search_path
[i
], basename
, NULL
);
398 result
= mono_assembly_open_full (fullpath
, status
, refonly
);
407 * mono_assembly_setrootdir:
408 * @root_dir: The pathname of the root directory where we will locate assemblies
410 * This routine sets the internal default root directory for looking up
413 * This is used by Windows installations to compute dynamically the
414 * place where the Mono assemblies are located.
418 mono_assembly_setrootdir (const char *root_dir
)
421 * Override the MONO_ASSEMBLIES directory configured at compile time.
423 /* Leak if called more than once */
424 default_path
[0] = g_strdup (root_dir
);
428 * mono_assembly_getrootdir:
430 * Obtains the root directory used for looking up assemblies.
432 * Returns: a string with the directory, this string should not be freed.
434 G_CONST_RETURN gchar
*
435 mono_assembly_getrootdir (void)
437 return default_path
[0];
442 * @assembly_dir: the base directory for assemblies
443 * @config_dir: the base directory for configuration files
445 * This routine is used internally and by developers embedding
446 * the runtime into their own applications.
448 * There are a number of cases to consider: Mono as a system-installed
449 * package that is available on the location preconfigured or Mono in
450 * a relocated location.
452 * If you are using a system-installed Mono, you can pass NULL
453 * to both parameters. If you are not, you should compute both
454 * directory values and call this routine.
456 * The values for a given PREFIX are:
458 * assembly_dir: PREFIX/lib
459 * config_dir: PREFIX/etc
461 * Notice that embedders that use Mono in a relocated way must
462 * compute the location at runtime, as they will be in control
463 * of where Mono is installed.
466 mono_set_dirs (const char *assembly_dir
, const char *config_dir
)
468 #if defined (MONO_ASSEMBLIES)
469 if (assembly_dir
== NULL
)
470 assembly_dir
= MONO_ASSEMBLIES
;
472 #if defined (MONO_CFG_DIR)
473 if (config_dir
== NULL
)
474 config_dir
= MONO_CFG_DIR
;
476 mono_assembly_setrootdir (assembly_dir
);
477 mono_set_config_dir (config_dir
);
480 #ifndef PLATFORM_WIN32
483 compute_base (char *path
)
485 char *p
= strrchr (path
, '/');
489 /* Not a well known Mono executable, we are embedded, cant guess the base */
490 if (strcmp (p
, "/mono") && strcmp (p
, "/monodis") && strcmp (p
, "/mint") && strcmp (p
, "/monodiet"))
494 p
= strrchr (path
, '/');
498 if (strcmp (p
, "/bin") != 0)
507 mono_set_dirs (MONO_ASSEMBLIES
, MONO_CFG_DIR
);
514 char *config
, *lib
, *mono
;
518 * Only /usr prefix is treated specially
520 if (strncmp (exe
, MONO_BINDIR
, strlen (MONO_BINDIR
)) == 0 || (base
= compute_base (exe
)) == NULL
){
525 config
= g_build_filename (base
, "etc", NULL
);
526 lib
= g_build_filename (base
, "lib", NULL
);
527 mono
= g_build_filename (lib
, "mono/1.0", NULL
);
528 if (stat (mono
, &buf
) == -1)
531 mono_set_dirs (lib
, config
);
539 #endif /* PLATFORM_WIN32 */
544 * Registers the root directory for the Mono runtime, for Linux and Solaris 10,
545 * this auto-detects the prefix where Mono was installed.
548 mono_set_rootdir (void)
550 #ifdef PLATFORM_WIN32
551 gchar
*bindir
, *installdir
, *root
, *name
, *config
;
553 name
= mono_get_module_file_name ((HMODULE
) &__ImageBase
);
554 bindir
= g_path_get_dirname (name
);
555 installdir
= g_path_get_dirname (bindir
);
556 root
= g_build_path (G_DIR_SEPARATOR_S
, installdir
, "lib", NULL
);
558 config
= g_build_filename (root
, "..", "etc", NULL
);
559 mono_set_dirs (root
, config
);
566 #elif defined(DISABLE_MONO_AUTODETECTION)
574 s
= readlink ("/proc/self/exe", buf
, sizeof (buf
)-1);
582 /* Solaris 10 style */
583 str
= g_strdup_printf ("/proc/%d/path/a.out", getpid ());
584 s
= readlink (str
, buf
, sizeof (buf
)-1);
596 * mono_assemblies_init:
598 * Initialize global variables used by this module.
601 mono_assemblies_init (void)
604 * Initialize our internal paths if we have not been initialized yet.
605 * This happens when embedders use Mono.
607 if (mono_assembly_getrootdir () == NULL
)
611 check_extra_gac_path_env ();
613 InitializeCriticalSection (&assemblies_mutex
);
617 mono_assembly_fill_assembly_name (MonoImage
*image
, MonoAssemblyName
*aname
)
619 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_ASSEMBLY
];
620 guint32 cols
[MONO_ASSEMBLY_SIZE
];
625 mono_metadata_decode_row (t
, 0, cols
, MONO_ASSEMBLY_SIZE
);
628 aname
->hash_value
= NULL
;
629 aname
->name
= mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLY_NAME
]);
630 aname
->culture
= mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLY_CULTURE
]);
631 aname
->flags
= cols
[MONO_ASSEMBLY_FLAGS
];
632 aname
->major
= cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
633 aname
->minor
= cols
[MONO_ASSEMBLY_MINOR_VERSION
];
634 aname
->build
= cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
635 aname
->revision
= cols
[MONO_ASSEMBLY_REV_NUMBER
];
636 aname
->hash_alg
= cols
[MONO_ASSEMBLY_HASH_ALG
];
637 if (cols
[MONO_ASSEMBLY_PUBLIC_KEY
]) {
638 guchar
* token
= g_malloc (8);
643 pkey
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLY_PUBLIC_KEY
]);
644 len
= mono_metadata_decode_blob_size (pkey
, &pkey
);
645 aname
->public_key
= (guchar
*)pkey
;
647 mono_digest_get_public_token (token
, aname
->public_key
, len
);
648 encoded
= encode_public_tok (token
, 8);
649 g_strlcpy ((char*)aname
->public_key_token
, encoded
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
655 aname
->public_key
= NULL
;
656 memset (aname
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
659 if (cols
[MONO_ASSEMBLY_PUBLIC_KEY
]) {
660 aname
->public_key
= (guchar
*)mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLY_PUBLIC_KEY
]);
663 aname
->public_key
= 0;
669 * mono_stringify_assembly_name:
670 * @aname: the assembly name.
672 * Convert @aname into its string format. The returned string is dynamically
673 * allocated and should be freed by the caller.
675 * Returns: a newly allocated string with a string representation of
679 mono_stringify_assembly_name (MonoAssemblyName
*aname
)
681 return g_strdup_printf (
682 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
684 aname
->major
, aname
->minor
, aname
->build
, aname
->revision
,
685 aname
->culture
&& *aname
->culture
? aname
->culture
: "neutral",
686 aname
->public_key_token
[0] ? (char *)aname
->public_key_token
: "null",
687 (aname
->flags
& ASSEMBLYREF_RETARGETABLE_FLAG
) ? ", Retargetable=Yes" : "");
691 assemblyref_public_tok (MonoImage
*image
, guint32 key_index
, guint32 flags
)
693 const gchar
*public_tok
;
696 public_tok
= mono_metadata_blob_heap (image
, key_index
);
697 len
= mono_metadata_decode_blob_size (public_tok
, &public_tok
);
699 if (flags
& ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
) {
701 mono_digest_get_public_token (token
, (guchar
*)public_tok
, len
);
702 return encode_public_tok (token
, 8);
705 return encode_public_tok ((guchar
*)public_tok
, len
);
709 * mono_assembly_addref:
710 * @assemnly: the assembly to reference
712 * This routine increments the reference count on a MonoAssembly.
713 * The reference count is reduced every time the method mono_assembly_close() is
717 mono_assembly_addref (MonoAssembly
*assembly
)
719 InterlockedIncrement (&assembly
->ref_count
);
722 static MonoAssemblyName
*
723 mono_assembly_remap_version (MonoAssemblyName
*aname
, MonoAssemblyName
*dest_aname
)
725 const MonoRuntimeInfo
*current_runtime
;
726 int pos
, first
, last
;
728 if (aname
->name
== NULL
) return aname
;
729 current_runtime
= mono_get_runtime_info ();
732 last
= G_N_ELEMENTS (framework_assemblies
) - 1;
734 while (first
<= last
) {
736 pos
= first
+ (last
- first
) / 2;
737 res
= strcmp (aname
->name
, framework_assemblies
[pos
].assembly_name
);
739 const AssemblyVersionSet
* vset
;
740 int index
= framework_assemblies
[pos
].version_set_index
;
741 g_assert (index
< G_N_ELEMENTS (current_runtime
->version_sets
));
742 vset
= ¤t_runtime
->version_sets
[index
];
744 if (aname
->major
== vset
->major
&& aname
->minor
== vset
->minor
&&
745 aname
->build
== vset
->build
&& aname
->revision
== vset
->revision
)
748 if ((aname
->major
| aname
->minor
| aname
->build
| aname
->revision
) != 0)
749 mono_trace (G_LOG_LEVEL_WARNING
, MONO_TRACE_ASSEMBLY
,
750 "The request to load the assembly %s v%d.%d.%d.%d was remapped to v%d.%d.%d.%d",
752 aname
->major
, aname
->minor
, aname
->build
, aname
->revision
,
753 vset
->major
, vset
->minor
, vset
->build
, vset
->revision
756 memcpy (dest_aname
, aname
, sizeof(MonoAssemblyName
));
757 dest_aname
->major
= vset
->major
;
758 dest_aname
->minor
= vset
->minor
;
759 dest_aname
->build
= vset
->build
;
760 dest_aname
->revision
= vset
->revision
;
762 } else if (res
< 0) {
772 * mono_assembly_get_assemblyref:
774 * Fill out ANAME with the assembly name of the INDEXth assembly reference in IMAGE.
777 mono_assembly_get_assemblyref (MonoImage
*image
, int index
, MonoAssemblyName
*aname
)
780 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
783 t
= &image
->tables
[MONO_TABLE_ASSEMBLYREF
];
785 mono_metadata_decode_row (t
, index
, cols
, MONO_ASSEMBLYREF_SIZE
);
787 hash
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_HASH_VALUE
]);
788 aname
->hash_len
= mono_metadata_decode_blob_size (hash
, &hash
);
789 aname
->hash_value
= hash
;
790 aname
->name
= mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
]);
791 aname
->culture
= mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]);
792 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
793 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
794 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
795 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
796 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
798 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
799 gchar
*token
= assemblyref_public_tok (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
], aname
->flags
);
800 g_strlcpy ((char*)aname
->public_key_token
, token
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
803 memset (aname
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
808 mono_assembly_load_reference (MonoImage
*image
, int index
)
810 MonoAssembly
*reference
;
811 MonoAssemblyName aname
;
812 MonoImageOpenStatus status
;
815 * image->references is shared between threads, so we need to access
816 * it inside a critical section.
818 mono_assemblies_lock ();
819 if (!image
->references
) {
820 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_ASSEMBLYREF
];
822 image
->references
= g_new0 (MonoAssembly
*, t
->rows
+ 1);
824 reference
= image
->references
[index
];
825 mono_assemblies_unlock ();
829 mono_assembly_get_assemblyref (image
, index
, &aname
);
831 if (image
->assembly
&& image
->assembly
->ref_only
) {
832 /* We use the loaded corlib */
833 if (!strcmp (aname
.name
, "mscorlib"))
834 reference
= mono_assembly_load_full (&aname
, image
->assembly
->basedir
, &status
, FALSE
);
836 reference
= mono_assembly_loaded_full (&aname
, TRUE
);
838 /* Try a postload search hook */
839 reference
= mono_assembly_invoke_search_hook_internal (&aname
, TRUE
, TRUE
);
843 * Here we must advice that the error was due to
844 * a non loaded reference using the ReflectionOnly api
847 reference
= REFERENCE_MISSING
;
849 reference
= mono_assembly_load (&aname
, image
->assembly
? image
->assembly
->basedir
: NULL
, &status
);
851 if (reference
== NULL
){
852 char *extra_msg
= g_strdup ("");
854 if (status
== MONO_IMAGE_ERROR_ERRNO
&& errno
== ENOENT
) {
855 extra_msg
= g_strdup_printf ("The assembly was not found in the Global Assembly Cache, a path listed in the MONO_PATH environment variable, or in the location of the executing assembly (%s).\n", image
->assembly
!= NULL
? image
->assembly
->basedir
: "" );
856 } else if (status
== MONO_IMAGE_ERROR_ERRNO
) {
857 extra_msg
= g_strdup_printf ("System error: %s\n", strerror (errno
));
858 } else if (status
== MONO_IMAGE_MISSING_ASSEMBLYREF
) {
859 extra_msg
= g_strdup ("Cannot find an assembly referenced from this one.\n");
860 } else if (status
== MONO_IMAGE_IMAGE_INVALID
) {
861 extra_msg
= g_strdup ("The file exists but is not a valid assembly.\n");
864 g_warning ("The following assembly referenced from %s could not be loaded:\n"
865 " Assembly: %s (assemblyref_index=%d)\n"
866 " Version: %d.%d.%d.%d\n"
867 " Public Key: %s\n%s",
868 image
->name
, aname
.name
, index
,
869 aname
.major
, aname
.minor
, aname
.build
, aname
.revision
,
870 strlen ((char*)aname
.public_key_token
) == 0 ? "(none)" : (char*)aname
.public_key_token
, extra_msg
);
874 mono_assemblies_lock ();
875 if (reference
== NULL
) {
876 /* Flag as not found */
877 reference
= REFERENCE_MISSING
;
880 if (!image
->references
[index
]) {
881 if (reference
!= REFERENCE_MISSING
){
882 mono_assembly_addref (reference
);
884 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Assembly Ref addref %s %p -> %s %p: %d\n",
885 image
->assembly
->aname
.name
, image
->assembly
, reference
->aname
.name
, reference
, reference
->ref_count
);
888 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Failed to load assembly %s %p\n",
889 image
->assembly
->aname
.name
, image
->assembly
);
892 image
->references
[index
] = reference
;
894 mono_assemblies_unlock ();
896 if (image
->references
[index
] != reference
) {
897 /* Somebody loaded it before us */
898 mono_assembly_close (reference
);
903 mono_assembly_load_references (MonoImage
*image
, MonoImageOpenStatus
*status
)
905 /* This is a no-op now but it is part of the embedding API so we can't remove it */
906 *status
= MONO_IMAGE_OK
;
909 typedef struct AssemblyLoadHook AssemblyLoadHook
;
910 struct AssemblyLoadHook
{
911 AssemblyLoadHook
*next
;
912 MonoAssemblyLoadFunc func
;
916 AssemblyLoadHook
*assembly_load_hook
= NULL
;
919 mono_assembly_invoke_load_hook (MonoAssembly
*ass
)
921 AssemblyLoadHook
*hook
;
923 for (hook
= assembly_load_hook
; hook
; hook
= hook
->next
) {
924 hook
->func (ass
, hook
->user_data
);
929 mono_install_assembly_load_hook (MonoAssemblyLoadFunc func
, gpointer user_data
)
931 AssemblyLoadHook
*hook
;
933 g_return_if_fail (func
!= NULL
);
935 hook
= g_new0 (AssemblyLoadHook
, 1);
937 hook
->user_data
= user_data
;
938 hook
->next
= assembly_load_hook
;
939 assembly_load_hook
= hook
;
943 free_assembly_load_hooks (void)
945 AssemblyLoadHook
*hook
, *next
;
947 for (hook
= assembly_load_hook
; hook
; hook
= next
) {
953 typedef struct AssemblySearchHook AssemblySearchHook
;
954 struct AssemblySearchHook
{
955 AssemblySearchHook
*next
;
956 MonoAssemblySearchFunc func
;
962 AssemblySearchHook
*assembly_search_hook
= NULL
;
965 mono_assembly_invoke_search_hook_internal (MonoAssemblyName
*aname
, gboolean refonly
, gboolean postload
)
967 AssemblySearchHook
*hook
;
969 for (hook
= assembly_search_hook
; hook
; hook
= hook
->next
) {
970 if ((hook
->refonly
== refonly
) && (hook
->postload
== postload
)) {
971 MonoAssembly
*ass
= hook
->func (aname
, hook
->user_data
);
981 mono_assembly_invoke_search_hook (MonoAssemblyName
*aname
)
983 return mono_assembly_invoke_search_hook_internal (aname
, FALSE
, FALSE
);
987 mono_install_assembly_search_hook_internal (MonoAssemblySearchFunc func
, gpointer user_data
, gboolean refonly
, gboolean postload
)
989 AssemblySearchHook
*hook
;
991 g_return_if_fail (func
!= NULL
);
993 hook
= g_new0 (AssemblySearchHook
, 1);
995 hook
->user_data
= user_data
;
996 hook
->refonly
= refonly
;
997 hook
->postload
= postload
;
998 hook
->next
= assembly_search_hook
;
999 assembly_search_hook
= hook
;
1003 mono_install_assembly_search_hook (MonoAssemblySearchFunc func
, gpointer user_data
)
1005 mono_install_assembly_search_hook_internal (func
, user_data
, FALSE
, FALSE
);
1009 free_assembly_search_hooks (void)
1011 AssemblySearchHook
*hook
, *next
;
1013 for (hook
= assembly_search_hook
; hook
; hook
= next
) {
1020 mono_install_assembly_refonly_search_hook (MonoAssemblySearchFunc func
, gpointer user_data
)
1022 mono_install_assembly_search_hook_internal (func
, user_data
, TRUE
, FALSE
);
1026 mono_install_assembly_postload_search_hook (MonoAssemblySearchFunc func
, gpointer user_data
)
1028 mono_install_assembly_search_hook_internal (func
, user_data
, FALSE
, TRUE
);
1032 mono_install_assembly_postload_refonly_search_hook (MonoAssemblySearchFunc func
, gpointer user_data
)
1034 mono_install_assembly_search_hook_internal (func
, user_data
, TRUE
, TRUE
);
1037 typedef struct AssemblyPreLoadHook AssemblyPreLoadHook
;
1038 struct AssemblyPreLoadHook
{
1039 AssemblyPreLoadHook
*next
;
1040 MonoAssemblyPreLoadFunc func
;
1044 static AssemblyPreLoadHook
*assembly_preload_hook
= NULL
;
1045 static AssemblyPreLoadHook
*assembly_refonly_preload_hook
= NULL
;
1047 static MonoAssembly
*
1048 invoke_assembly_preload_hook (MonoAssemblyName
*aname
, gchar
**assemblies_path
)
1050 AssemblyPreLoadHook
*hook
;
1051 MonoAssembly
*assembly
;
1053 for (hook
= assembly_preload_hook
; hook
; hook
= hook
->next
) {
1054 assembly
= hook
->func (aname
, assemblies_path
, hook
->user_data
);
1055 if (assembly
!= NULL
)
1062 static MonoAssembly
*
1063 invoke_assembly_refonly_preload_hook (MonoAssemblyName
*aname
, gchar
**assemblies_path
)
1065 AssemblyPreLoadHook
*hook
;
1066 MonoAssembly
*assembly
;
1068 for (hook
= assembly_refonly_preload_hook
; hook
; hook
= hook
->next
) {
1069 assembly
= hook
->func (aname
, assemblies_path
, hook
->user_data
);
1070 if (assembly
!= NULL
)
1078 mono_install_assembly_preload_hook (MonoAssemblyPreLoadFunc func
, gpointer user_data
)
1080 AssemblyPreLoadHook
*hook
;
1082 g_return_if_fail (func
!= NULL
);
1084 hook
= g_new0 (AssemblyPreLoadHook
, 1);
1086 hook
->user_data
= user_data
;
1087 hook
->next
= assembly_preload_hook
;
1088 assembly_preload_hook
= hook
;
1092 mono_install_assembly_refonly_preload_hook (MonoAssemblyPreLoadFunc func
, gpointer user_data
)
1094 AssemblyPreLoadHook
*hook
;
1096 g_return_if_fail (func
!= NULL
);
1098 hook
= g_new0 (AssemblyPreLoadHook
, 1);
1100 hook
->user_data
= user_data
;
1101 hook
->next
= assembly_refonly_preload_hook
;
1102 assembly_refonly_preload_hook
= hook
;
1106 free_assembly_preload_hooks (void)
1108 AssemblyPreLoadHook
*hook
, *next
;
1110 for (hook
= assembly_preload_hook
; hook
; hook
= next
) {
1115 for (hook
= assembly_refonly_preload_hook
; hook
; hook
= next
) {
1122 absolute_dir (const gchar
*filename
)
1133 if (g_path_is_absolute (filename
)) {
1134 part
= g_path_get_dirname (filename
);
1135 res
= g_strconcat (part
, G_DIR_SEPARATOR_S
, NULL
);
1140 cwd
= g_get_current_dir ();
1141 mixed
= g_build_filename (cwd
, filename
, NULL
);
1142 parts
= g_strsplit (mixed
, G_DIR_SEPARATOR_S
, 0);
1147 for (i
= 0; (part
= parts
[i
]) != NULL
; i
++) {
1148 if (!strcmp (part
, "."))
1151 if (!strcmp (part
, "..")) {
1152 if (list
&& list
->next
) /* Don't remove root */
1153 list
= g_list_delete_link (list
, list
);
1155 list
= g_list_prepend (list
, part
);
1159 result
= g_string_new ("");
1160 list
= g_list_reverse (list
);
1162 /* Ignores last data pointer, which should be the filename */
1163 for (tmp
= list
; tmp
&& tmp
->next
!= NULL
; tmp
= tmp
->next
){
1165 g_string_append_printf (result
, "%s%c", (char *) tmp
->data
,
1170 g_string_free (result
, FALSE
);
1175 return g_strdup (".");
1182 * mono_assembly_open_from_bundle:
1183 * @filename: Filename requested
1184 * @status: return value
1186 * This routine tries to open the assembly specified by `filename' from the
1187 * defined bundles, if found, returns the MonoImage for it, if not found
1191 mono_assembly_open_from_bundle (const char *filename
, MonoImageOpenStatus
*status
, gboolean refonly
)
1195 MonoImage
*image
= NULL
;
1198 * we do a very simple search for bundled assemblies: it's not a general
1199 * purpose assembly loading mechanism.
1205 name
= g_path_get_basename (filename
);
1207 mono_assemblies_lock ();
1208 for (i
= 0; !image
&& bundles
[i
]; ++i
) {
1209 if (strcmp (bundles
[i
]->name
, name
) == 0) {
1210 image
= mono_image_open_from_data_full ((char*)bundles
[i
]->data
, bundles
[i
]->size
, FALSE
, status
, refonly
);
1214 mono_assemblies_unlock ();
1217 mono_image_addref (image
);
1224 mono_assembly_open_full (const char *filename
, MonoImageOpenStatus
*status
, gboolean refonly
)
1228 MonoImageOpenStatus def_status
;
1232 g_return_val_if_fail (filename
!= NULL
, NULL
);
1235 status
= &def_status
;
1236 *status
= MONO_IMAGE_OK
;
1238 if (strncmp (filename
, "file://", 7) == 0) {
1239 GError
*error
= NULL
;
1240 gchar
*uri
= (gchar
*) filename
;
1244 * MS allows file://c:/... and fails on file://localhost/c:/...
1245 * They also throw an IndexOutOfRangeException if "file://"
1248 uri
= g_strdup_printf ("file:///%s", uri
+ 7);
1251 uri
= mono_escape_uri_string (tmpuri
);
1252 fname
= g_filename_from_uri (uri
, NULL
, &error
);
1255 if (tmpuri
!= filename
)
1258 if (error
!= NULL
) {
1259 g_warning ("%s\n", error
->message
);
1260 g_error_free (error
);
1261 fname
= g_strdup (filename
);
1264 fname
= g_strdup (filename
);
1267 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
,
1268 "Assembly Loader probing location: '%s'.", fname
);
1269 new_fname
= mono_make_shadow_copy (fname
);
1270 if (new_fname
&& new_fname
!= fname
) {
1273 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
,
1274 "Assembly Loader shadow-copied assembly to: '%s'.", fname
);
1279 if (bundles
!= NULL
)
1280 image
= mono_assembly_open_from_bundle (fname
, status
, refonly
);
1283 image
= mono_image_open_full (fname
, status
, refonly
);
1286 if (*status
== MONO_IMAGE_OK
)
1287 *status
= MONO_IMAGE_ERROR_ERRNO
;
1292 if (image
->assembly
) {
1293 /* Already loaded by another appdomain */
1294 mono_assembly_invoke_load_hook (image
->assembly
);
1295 mono_image_close (image
);
1297 return image
->assembly
;
1300 ass
= mono_assembly_load_from_full (image
, fname
, status
, refonly
);
1303 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
,
1304 "Assembly Loader loaded assembly from location: '%s'.", filename
);
1306 mono_config_for_assembly (ass
->image
);
1309 /* Clear the reference added by mono_image_open */
1310 mono_image_close (image
);
1318 free_item (gpointer val
, gpointer user_data
)
1324 * mono_assembly_load_friends:
1327 * Load the list of friend assemblies that are allowed to access
1328 * the assembly's internal types and members. They are stored as assembly
1329 * names in custom attributes.
1331 * This is an internal method, we need this because when we load mscorlib
1332 * we do not have the mono_defaults.internals_visible_class loaded yet,
1333 * so we need to load these after we initialize the runtime.
1335 * LOCKING: Acquires the assemblies lock plus the loader lock.
1338 mono_assembly_load_friends (MonoAssembly
* ass
)
1341 MonoCustomAttrInfo
* attrs
;
1344 if (ass
->friend_assembly_names_inited
)
1347 attrs
= mono_custom_attrs_from_assembly (ass
);
1349 mono_assemblies_lock ();
1350 ass
->friend_assembly_names_inited
= TRUE
;
1351 mono_assemblies_unlock ();
1355 mono_assemblies_lock ();
1356 if (ass
->friend_assembly_names_inited
) {
1357 mono_assemblies_unlock ();
1360 mono_assemblies_unlock ();
1364 * We build the list outside the assemblies lock, the worse that can happen
1365 * is that we'll need to free the allocated list.
1367 for (i
= 0; i
< attrs
->num_attrs
; ++i
) {
1368 MonoCustomAttrEntry
*attr
= &attrs
->attrs
[i
];
1369 MonoAssemblyName
*aname
;
1372 /* Do some sanity checking */
1373 if (!attr
->ctor
|| attr
->ctor
->klass
!= mono_defaults
.internals_visible_class
)
1375 if (attr
->data_size
< 4)
1377 data
= (const char*)attr
->data
;
1378 /* 0xFF means null string, see custom attr format */
1379 if (data
[0] != 1 || data
[1] != 0 || (data
[2] & 0xFF) == 0xFF)
1381 slen
= mono_metadata_decode_value (data
+ 2, &data
);
1382 aname
= g_new0 (MonoAssemblyName
, 1);
1383 /*g_print ("friend ass: %s\n", data);*/
1384 if (mono_assembly_name_parse_full (data
, aname
, TRUE
, NULL
, NULL
)) {
1385 list
= g_slist_prepend (list
, aname
);
1390 mono_custom_attrs_free (attrs
);
1392 mono_assemblies_lock ();
1393 if (ass
->friend_assembly_names_inited
) {
1394 mono_assemblies_unlock ();
1395 g_slist_foreach (list
, free_item
, NULL
);
1396 g_slist_free (list
);
1399 ass
->friend_assembly_names
= list
;
1401 /* Because of the double checked locking pattern above */
1402 mono_memory_barrier ();
1403 ass
->friend_assembly_names_inited
= TRUE
;
1404 mono_assemblies_unlock ();
1408 * mono_assembly_open:
1409 * @filename: Opens the assembly pointed out by this name
1410 * @status: where a status code can be returned
1412 * mono_assembly_open opens the PE-image pointed by @filename, and
1413 * loads any external assemblies referenced by it.
1415 * Return: a pointer to the MonoAssembly if @filename contains a valid
1416 * assembly or NULL on error. Details about the error are stored in the
1420 mono_assembly_open (const char *filename
, MonoImageOpenStatus
*status
)
1422 return mono_assembly_open_full (filename
, status
, FALSE
);
1426 mono_assembly_load_from_full (MonoImage
*image
, const char*fname
,
1427 MonoImageOpenStatus
*status
, gboolean refonly
)
1429 MonoAssembly
*ass
, *ass2
;
1432 if (!image
->tables
[MONO_TABLE_ASSEMBLY
].rows
) {
1433 /* 'image' doesn't have a manifest -- maybe someone is trying to Assembly.Load a .netmodule */
1434 *status
= MONO_IMAGE_IMAGE_INVALID
;
1438 #if defined (PLATFORM_WIN32)
1443 tmp_fn
= g_strdup (fname
);
1444 for (i
= strlen (tmp_fn
) - 1; i
>= 0; i
--) {
1445 if (tmp_fn
[i
] == '/')
1449 base_dir
= absolute_dir (tmp_fn
);
1453 base_dir
= absolute_dir (fname
);
1457 * Create assembly struct, and enter it into the assembly cache
1459 ass
= g_new0 (MonoAssembly
, 1);
1460 ass
->basedir
= base_dir
;
1461 ass
->ref_only
= refonly
;
1464 mono_profiler_assembly_event (ass
, MONO_PROFILE_START_LOAD
);
1466 mono_assembly_fill_assembly_name (image
, &ass
->aname
);
1468 if (mono_defaults
.corlib
&& strcmp (ass
->aname
.name
, "mscorlib") == 0) {
1469 // MS.NET doesn't support loading other mscorlibs
1472 mono_image_addref (mono_defaults
.corlib
);
1473 *status
= MONO_IMAGE_OK
;
1474 return mono_defaults
.corlib
->assembly
;
1477 /* Add a non-temporary reference because of ass->image */
1478 mono_image_addref (image
);
1480 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Image addref %s %p -> %s %p: %d\n", ass
->aname
.name
, ass
, image
->name
, image
, image
->ref_count
);
1483 * The load hooks might take locks so we can't call them while holding the
1486 if (ass
->aname
.name
) {
1487 ass2
= mono_assembly_invoke_search_hook_internal (&ass
->aname
, refonly
, FALSE
);
1491 mono_image_close (image
);
1492 *status
= MONO_IMAGE_OK
;
1497 mono_assemblies_lock ();
1499 if (image
->assembly
) {
1501 * This means another thread has already loaded the assembly, but not yet
1502 * called the load hooks so the search hook can't find the assembly.
1504 mono_assemblies_unlock ();
1505 ass2
= image
->assembly
;
1508 mono_image_close (image
);
1509 *status
= MONO_IMAGE_OK
;
1513 image
->assembly
= ass
;
1515 loaded_assemblies
= g_list_prepend (loaded_assemblies
, ass
);
1516 mono_assemblies_unlock ();
1518 #ifdef PLATFORM_WIN32
1519 if (image
->is_module_handle
)
1520 mono_image_fixup_vtable (image
);
1523 mono_assembly_invoke_load_hook (ass
);
1525 mono_profiler_assembly_loaded (ass
, MONO_PROFILE_OK
);
1531 mono_assembly_load_from (MonoImage
*image
, const char *fname
,
1532 MonoImageOpenStatus
*status
)
1534 return mono_assembly_load_from_full (image
, fname
, status
, FALSE
);
1538 * mono_assembly_name_free:
1539 * @aname: assembly name to free
1541 * Frees the provided assembly name object.
1542 * (it does not frees the object itself, only the name members).
1545 mono_assembly_name_free (MonoAssemblyName
*aname
)
1550 g_free ((void *) aname
->name
);
1551 g_free ((void *) aname
->culture
);
1552 g_free ((void *) aname
->hash_value
);
1556 parse_public_key (const gchar
*key
, gchar
** pubkey
)
1559 gchar header
[16], val
, *arr
;
1560 gint i
, j
, offset
, bitlen
, keylen
, pkeylen
;
1562 keylen
= strlen (key
) >> 1;
1566 val
= g_ascii_xdigit_value (key
[0]) << 4;
1567 val
|= g_ascii_xdigit_value (key
[1]);
1572 val
= g_ascii_xdigit_value (key
[24]);
1573 val
|= g_ascii_xdigit_value (key
[25]);
1585 /* We need the first 16 bytes
1586 * to check whether this key is valid or not */
1587 pkeylen
= strlen (pkey
) >> 1;
1591 for (i
= 0, j
= 0; i
< 16; i
++) {
1592 header
[i
] = g_ascii_xdigit_value (pkey
[j
++]) << 4;
1593 header
[i
] |= g_ascii_xdigit_value (pkey
[j
++]);
1596 if (header
[0] != 0x06 || /* PUBLICKEYBLOB (0x06) */
1597 header
[1] != 0x02 || /* Version (0x02) */
1598 header
[2] != 0x00 || /* Reserved (word) */
1599 header
[3] != 0x00 ||
1600 (guint
)(read32 (header
+ 8)) != 0x31415352) /* DWORD magic = RSA1 */
1603 /* Based on this length, we _should_ be able to know if the length is right */
1604 bitlen
= read32 (header
+ 12) >> 3;
1605 if ((bitlen
+ 16 + 4) != pkeylen
)
1608 /* Encode the size of the blob */
1610 if (keylen
<= 127) {
1611 arr
= g_malloc (keylen
+ 1);
1612 arr
[offset
++] = keylen
;
1614 arr
= g_malloc (keylen
+ 2);
1615 arr
[offset
++] = 0x80; /* 10bs */
1616 arr
[offset
++] = keylen
;
1619 for (i
= offset
, j
= 0; i
< keylen
+ offset
; i
++) {
1620 arr
[i
] = g_ascii_xdigit_value (key
[j
++]) << 4;
1621 arr
[i
] |= g_ascii_xdigit_value (key
[j
++]);
1630 build_assembly_name (const char *name
, const char *version
, const char *culture
, const char *token
, const char *key
, guint32 flags
, MonoAssemblyName
*aname
, gboolean save_public_key
)
1632 gint major
, minor
, build
, revision
;
1635 gchar
*pkey
, *pkeyptr
, *encoded
, tok
[8];
1637 memset (aname
, 0, sizeof (MonoAssemblyName
));
1640 version_parts
= sscanf (version
, "%u.%u.%u.%u", &major
, &minor
, &build
, &revision
);
1641 if (version_parts
< 2 || version_parts
> 4)
1644 /* FIXME: we should set build & revision to -1 (instead of 0)
1645 if these are not set in the version string. That way, later on,
1646 we can still determine if these were specified. */
1647 aname
->major
= major
;
1648 aname
->minor
= minor
;
1649 if (version_parts
>= 3)
1650 aname
->build
= build
;
1653 if (version_parts
== 4)
1654 aname
->revision
= revision
;
1656 aname
->revision
= 0;
1659 aname
->flags
= flags
;
1660 aname
->name
= g_strdup (name
);
1663 if (g_ascii_strcasecmp (culture
, "neutral") == 0)
1664 aname
->culture
= g_strdup ("");
1666 aname
->culture
= g_strdup (culture
);
1669 if (token
&& strncmp (token
, "null", 4) != 0) {
1672 /* the constant includes the ending NULL, hence the -1 */
1673 if (strlen (token
) != (MONO_PUBLIC_KEY_TOKEN_LENGTH
- 1)) {
1674 mono_assembly_name_free (aname
);
1677 lower
= g_ascii_strdown (token
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
1678 g_strlcpy ((char*)aname
->public_key_token
, lower
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
1683 if (strcmp (key
, "null") == 0 || !parse_public_key (key
, &pkey
)) {
1684 mono_assembly_name_free (aname
);
1688 len
= mono_metadata_decode_blob_size ((const gchar
*) pkey
, (const gchar
**) &pkeyptr
);
1689 // We also need to generate the key token
1690 mono_digest_get_public_token ((guchar
*) tok
, (guint8
*) pkeyptr
, len
);
1691 encoded
= encode_public_tok ((guchar
*) tok
, 8);
1692 g_strlcpy ((gchar
*)aname
->public_key_token
, encoded
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
1695 if (save_public_key
)
1696 aname
->public_key
= (guint8
*) pkey
;
1705 parse_assembly_directory_name (const char *name
, const char *dirname
, MonoAssemblyName
*aname
)
1710 parts
= g_strsplit (dirname
, "_", 3);
1711 if (!parts
|| !parts
[0] || !parts
[1] || !parts
[2]) {
1716 res
= build_assembly_name (name
, parts
[0], parts
[1], parts
[2], NULL
, 0, aname
, FALSE
);
1722 mono_assembly_name_parse_full (const char *name
, MonoAssemblyName
*aname
, gboolean save_public_key
, gboolean
*is_version_defined
, gboolean
*is_token_defined
)
1725 gchar
*version
= NULL
;
1726 gchar
*culture
= NULL
;
1727 gchar
*token
= NULL
;
1729 gchar
*retargetable
= NULL
;
1734 gboolean version_defined
;
1735 gboolean token_defined
;
1738 if (!is_version_defined
)
1739 is_version_defined
= &version_defined
;
1740 *is_version_defined
= FALSE
;
1741 if (!is_token_defined
)
1742 is_token_defined
= &token_defined
;
1743 *is_token_defined
= FALSE
;
1745 parts
= tmp
= g_strsplit (name
, ",", 6);
1746 if (!tmp
|| !*tmp
) {
1751 dllname
= g_strstrip (*tmp
);
1756 value
= g_strstrip (*tmp
);
1757 if (!g_ascii_strncasecmp (value
, "Version=", 8)) {
1758 *is_version_defined
= TRUE
;
1759 version
= g_strstrip (value
+ 8);
1760 if (strlen (version
) == 0) {
1761 goto cleanup_and_fail
;
1767 if (!g_ascii_strncasecmp (value
, "Culture=", 8)) {
1768 culture
= g_strstrip (value
+ 8);
1769 if (strlen (culture
) == 0) {
1770 goto cleanup_and_fail
;
1776 if (!g_ascii_strncasecmp (value
, "PublicKeyToken=", 15)) {
1777 *is_token_defined
= TRUE
;
1778 token
= g_strstrip (value
+ 15);
1779 if (strlen (token
) == 0) {
1780 goto cleanup_and_fail
;
1786 if (!g_ascii_strncasecmp (value
, "PublicKey=", 10)) {
1787 key
= g_strstrip (value
+ 10);
1788 if (strlen (key
) == 0) {
1789 goto cleanup_and_fail
;
1795 if (!g_ascii_strncasecmp (value
, "Retargetable=", 13)) {
1796 retargetable
= g_strstrip (value
+ 13);
1797 if (strlen (retargetable
) == 0) {
1798 goto cleanup_and_fail
;
1800 if (!g_ascii_strcasecmp (retargetable
, "yes")) {
1801 flags
|= ASSEMBLYREF_RETARGETABLE_FLAG
;
1802 } else if (g_ascii_strcasecmp (retargetable
, "no")) {
1803 goto cleanup_and_fail
;
1809 if (!g_ascii_strncasecmp (value
, "ProcessorArchitecture=", 22)) {
1810 /* this is ignored for now, until we can change MonoAssemblyName */
1819 /* if retargetable flag is set, then we must have a fully qualified name */
1820 if (retargetable
!= NULL
&& (version
== NULL
|| culture
== NULL
|| (key
== NULL
&& token
== NULL
))) {
1821 goto cleanup_and_fail
;
1824 res
= build_assembly_name (dllname
, version
, culture
, token
, key
, flags
,
1825 aname
, save_public_key
);
1835 * mono_assembly_name_parse:
1836 * @name: name to parse
1837 * @aname: the destination assembly name
1839 * Parses an assembly qualified type name and assigns the name,
1840 * version, culture and token to the provided assembly name object.
1842 * Returns: true if the name could be parsed.
1845 mono_assembly_name_parse (const char *name
, MonoAssemblyName
*aname
)
1847 return mono_assembly_name_parse_full (name
, aname
, FALSE
, NULL
, NULL
);
1850 static MonoAssembly
*
1851 probe_for_partial_name (const char *basepath
, const char *fullname
, MonoAssemblyName
*aname
, MonoImageOpenStatus
*status
)
1853 gchar
*fullpath
= NULL
;
1855 const char* direntry
;
1856 MonoAssemblyName gac_aname
;
1857 gint major
=-1, minor
=0, build
=0, revision
=0;
1858 gboolean exact_version
;
1860 dirhandle
= g_dir_open (basepath
, 0, NULL
);
1864 exact_version
= (aname
->major
| aname
->minor
| aname
->build
| aname
->revision
) != 0;
1866 while ((direntry
= g_dir_read_name (dirhandle
))) {
1867 gboolean match
= TRUE
;
1869 if(!parse_assembly_directory_name (aname
->name
, direntry
, &gac_aname
))
1872 if (aname
->culture
!= NULL
&& strcmp (aname
->culture
, gac_aname
.culture
) != 0)
1875 if (match
&& strlen ((char*)aname
->public_key_token
) > 0 &&
1876 !mono_public_tokens_are_equal (aname
->public_key_token
, gac_aname
.public_key_token
))
1880 if (exact_version
) {
1881 match
= (aname
->major
== gac_aname
.major
&& aname
->minor
== gac_aname
.minor
&&
1882 aname
->build
== gac_aname
.build
&& aname
->revision
== gac_aname
.revision
);
1884 else if (gac_aname
.major
< major
)
1886 else if (gac_aname
.major
== major
) {
1887 if (gac_aname
.minor
< minor
)
1889 else if (gac_aname
.minor
== minor
) {
1890 if (gac_aname
.build
< build
)
1892 else if (gac_aname
.build
== build
&& gac_aname
.revision
<= revision
)
1899 major
= gac_aname
.major
;
1900 minor
= gac_aname
.minor
;
1901 build
= gac_aname
.build
;
1902 revision
= gac_aname
.revision
;
1904 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, basepath
, direntry
, fullname
, NULL
);
1907 mono_assembly_name_free (&gac_aname
);
1910 g_dir_close (dirhandle
);
1912 if (fullpath
== NULL
)
1915 MonoAssembly
*res
= mono_assembly_open (fullpath
, status
);
1922 mono_assembly_load_with_partial_name (const char *name
, MonoImageOpenStatus
*status
)
1925 MonoAssemblyName
*aname
, base_name
, maped_aname
;
1926 gchar
*fullname
, *gacpath
;
1929 memset (&base_name
, 0, sizeof (MonoAssemblyName
));
1932 if (!mono_assembly_name_parse (name
, aname
))
1936 * If no specific version has been requested, make sure we load the
1937 * correct version for system assemblies.
1939 if ((aname
->major
| aname
->minor
| aname
->build
| aname
->revision
) == 0)
1940 aname
= mono_assembly_remap_version (aname
, &maped_aname
);
1942 res
= mono_assembly_loaded (aname
);
1944 mono_assembly_name_free (aname
);
1948 res
= invoke_assembly_preload_hook (aname
, assemblies_path
);
1950 res
->in_gac
= FALSE
;
1951 mono_assembly_name_free (aname
);
1955 fullname
= g_strdup_printf ("%s.dll", aname
->name
);
1957 if (extra_gac_paths
) {
1958 paths
= extra_gac_paths
;
1959 while (!res
&& *paths
) {
1960 gacpath
= g_build_path (G_DIR_SEPARATOR_S
, *paths
, "lib", "mono", "gac", aname
->name
, NULL
);
1961 res
= probe_for_partial_name (gacpath
, fullname
, aname
, status
);
1970 mono_assembly_name_free (aname
);
1974 gacpath
= g_build_path (G_DIR_SEPARATOR_S
, mono_assembly_getrootdir (), "mono", "gac", aname
->name
, NULL
);
1975 res
= probe_for_partial_name (gacpath
, fullname
, aname
, status
);
1981 MonoDomain
*domain
= mono_domain_get ();
1982 MonoReflectionAssembly
*refasm
= mono_try_assembly_resolve (domain
, mono_string_new (domain
, name
), FALSE
);
1984 res
= refasm
->assembly
;
1988 mono_assembly_name_free (aname
);
1994 mono_assembly_load_publisher_policy (MonoAssemblyName
*aname
)
1997 gchar
*filename
, *pname
, *name
, *culture
, *version
, *fullpath
, *subpath
;
2001 if (strstr (aname
->name
, ".dll")) {
2002 len
= strlen (aname
->name
) - 4;
2003 name
= g_malloc (len
);
2004 strncpy (name
, aname
->name
, len
);
2006 name
= g_strdup (aname
->name
);
2009 culture
= g_utf8_strdown (aname
->culture
, -1);
2011 culture
= g_strdup ("");
2013 pname
= g_strdup_printf ("policy.%d.%d.%s", aname
->major
, aname
->minor
, name
);
2014 version
= g_strdup_printf ("0.0.0.0_%s_%s", culture
, aname
->public_key_token
);
2018 filename
= g_strconcat (pname
, ".dll", NULL
);
2019 subpath
= g_build_path (G_DIR_SEPARATOR_S
, pname
, version
, filename
, NULL
);
2025 if (extra_gac_paths
) {
2026 paths
= extra_gac_paths
;
2027 while (!image
&& *paths
) {
2028 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, *paths
,
2029 "lib", "mono", "gac", subpath
, NULL
);
2030 image
= mono_image_open (fullpath
, NULL
);
2041 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, mono_assembly_getrootdir (),
2042 "mono", "gac", subpath
, NULL
);
2043 image
= mono_image_open (fullpath
, NULL
);
2050 static MonoAssemblyName
*
2051 mono_assembly_bind_version (MonoAssemblyBindingInfo
*info
, MonoAssemblyName
*aname
, MonoAssemblyName
*dest_name
)
2053 memcpy (dest_name
, aname
, sizeof (MonoAssemblyName
));
2054 dest_name
->major
= info
->new_version
.major
;
2055 dest_name
->minor
= info
->new_version
.minor
;
2056 dest_name
->build
= info
->new_version
.build
;
2057 dest_name
->revision
= info
->new_version
.revision
;
2062 /* LOCKING: Assumes that we are already locked */
2063 static MonoAssemblyBindingInfo
*
2064 search_binding_loaded (MonoAssemblyName
*aname
)
2068 for (tmp
= loaded_assembly_bindings
; tmp
; tmp
= tmp
->next
) {
2069 MonoAssemblyBindingInfo
*info
= tmp
->data
;
2070 if (assembly_binding_maps_name (info
, aname
))
2077 static MonoAssemblyName
*
2078 mono_assembly_apply_binding (MonoAssemblyName
*aname
, MonoAssemblyName
*dest_name
)
2080 MonoAssemblyBindingInfo
*info
, *info2
;
2083 if (aname
->public_key_token
[0] == 0)
2086 mono_loader_lock ();
2087 info
= search_binding_loaded (aname
);
2088 mono_loader_unlock ();
2090 if (!check_policy_versions (info
, aname
))
2093 mono_assembly_bind_version (info
, aname
, dest_name
);
2097 info
= g_new0 (MonoAssemblyBindingInfo
, 1);
2098 info
->major
= aname
->major
;
2099 info
->minor
= aname
->minor
;
2101 ppimage
= mono_assembly_load_publisher_policy (aname
);
2103 get_publisher_policy_info (ppimage
, aname
, info
);
2104 mono_image_close (ppimage
);
2107 /* Define default error value if needed */
2108 if (!info
->is_valid
) {
2109 info
->name
= g_strdup (aname
->name
);
2110 info
->culture
= g_strdup (aname
->culture
);
2111 g_strlcpy ((char *)info
->public_key_token
, (const char *)aname
->public_key_token
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
2114 mono_loader_lock ();
2115 info2
= search_binding_loaded (aname
);
2117 /* This binding was added by another thread
2119 mono_assembly_binding_info_free (info
);
2124 loaded_assembly_bindings
= g_slist_prepend (loaded_assembly_bindings
, info
);
2126 mono_loader_unlock ();
2128 if (!info
->is_valid
|| !check_policy_versions (info
, aname
))
2131 mono_assembly_bind_version (info
, aname
, dest_name
);
2136 * mono_assembly_load_from_gac
2138 * @aname: The assembly name object
2140 static MonoAssembly
*
2141 mono_assembly_load_from_gac (MonoAssemblyName
*aname
, gchar
*filename
, MonoImageOpenStatus
*status
, MonoBoolean refonly
)
2143 MonoAssembly
*result
= NULL
;
2144 gchar
*name
, *version
, *culture
, *fullpath
, *subpath
;
2149 if (aname
->public_key_token
[0] == 0) {
2153 if (strstr (aname
->name
, ".dll")) {
2154 len
= strlen (filename
) - 4;
2155 name
= g_malloc (len
);
2156 strncpy (name
, aname
->name
, len
);
2158 name
= g_strdup (aname
->name
);
2161 if (aname
->culture
) {
2162 culture
= g_utf8_strdown (aname
->culture
, -1);
2164 culture
= g_strdup ("");
2167 pubtok
= g_ascii_strdown ((char*)aname
->public_key_token
, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
2168 version
= g_strdup_printf ("%d.%d.%d.%d_%s_%s", aname
->major
,
2169 aname
->minor
, aname
->build
, aname
->revision
,
2173 subpath
= g_build_path (G_DIR_SEPARATOR_S
, name
, version
, filename
, NULL
);
2178 if (extra_gac_paths
) {
2179 paths
= extra_gac_paths
;
2180 while (!result
&& *paths
) {
2181 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, *paths
, "lib", "mono", "gac", subpath
, NULL
);
2182 result
= mono_assembly_open_full (fullpath
, status
, refonly
);
2189 result
->in_gac
= TRUE
;
2194 fullpath
= g_build_path (G_DIR_SEPARATOR_S
, mono_assembly_getrootdir (),
2195 "mono", "gac", subpath
, NULL
);
2196 result
= mono_assembly_open_full (fullpath
, status
, refonly
);
2200 result
->in_gac
= TRUE
;
2209 mono_assembly_load_corlib (const MonoRuntimeInfo
*runtime
, MonoImageOpenStatus
*status
)
2214 /* g_print ("corlib already loaded\n"); */
2218 if (assemblies_path
) {
2219 corlib
= load_in_path ("mscorlib.dll", (const char**)assemblies_path
, status
, FALSE
);
2224 /* Load corlib from mono/<version> */
2226 corlib_file
= g_build_filename ("mono", runtime
->framework_version
, "mscorlib.dll", NULL
);
2227 if (assemblies_path
) {
2228 corlib
= load_in_path (corlib_file
, (const char**)assemblies_path
, status
, FALSE
);
2230 g_free (corlib_file
);
2234 corlib
= load_in_path (corlib_file
, default_path
, status
, FALSE
);
2235 g_free (corlib_file
);
2241 mono_assembly_load_full_nosearch (MonoAssemblyName
*aname
,
2242 const char *basedir
,
2243 MonoImageOpenStatus
*status
,
2246 MonoAssembly
*result
;
2247 char *fullpath
, *filename
;
2248 MonoAssemblyName maped_aname
, maped_name_pp
;
2253 aname
= mono_assembly_remap_version (aname
, &maped_aname
);
2255 /* Reflection only assemblies don't get assembly binding */
2257 aname
= mono_assembly_apply_binding (aname
, &maped_name_pp
);
2259 result
= mono_assembly_loaded_full (aname
, refonly
);
2263 result
= refonly
? invoke_assembly_refonly_preload_hook (aname
, assemblies_path
) : invoke_assembly_preload_hook (aname
, assemblies_path
);
2265 result
->in_gac
= FALSE
;
2269 /* Currently we retrieve the loaded corlib for reflection
2270 * only requests, like a common reflection only assembly
2272 if (strcmp (aname
->name
, "mscorlib") == 0 || strcmp (aname
->name
, "mscorlib.dll") == 0) {
2273 return mono_assembly_load_corlib (mono_get_runtime_info (), status
);
2276 len
= strlen (aname
->name
);
2277 for (ext_index
= 0; ext_index
< 2; ext_index
++) {
2278 ext
= ext_index
== 0 ? ".dll" : ".exe";
2279 if (len
> 4 && (!strcmp (aname
->name
+ len
- 4, ".dll") || !strcmp (aname
->name
+ len
- 4, ".exe"))) {
2280 filename
= g_strdup (aname
->name
);
2281 /* Don't try appending .dll/.exe if it already has one of those extensions */
2284 filename
= g_strconcat (aname
->name
, ext
, NULL
);
2287 result
= mono_assembly_load_from_gac (aname
, filename
, status
, refonly
);
2294 fullpath
= g_build_filename (basedir
, filename
, NULL
);
2295 result
= mono_assembly_open_full (fullpath
, status
, refonly
);
2298 result
->in_gac
= FALSE
;
2304 result
= load_in_path (filename
, default_path
, status
, refonly
);
2306 result
->in_gac
= FALSE
;
2316 * mono_assembly_load_full:
2317 * @aname: A MonoAssemblyName with the assembly name to load.
2318 * @basedir: A directory to look up the assembly at.
2319 * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation
2320 * @refonly: Whether this assembly is being opened in "reflection-only" mode.
2322 * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it
2323 * attempts to load the assembly from that directory before probing the standard locations.
2325 * If the assembly is being opened in reflection-only mode (@refonly set to TRUE) then no
2326 * assembly binding takes place.
2328 * Returns: the assembly referenced by @aname loaded or NULL on error. On error the
2329 * value pointed by status is updated with an error code.
2332 mono_assembly_load_full (MonoAssemblyName
*aname
, const char *basedir
, MonoImageOpenStatus
*status
, gboolean refonly
)
2334 MonoAssembly
*result
= mono_assembly_load_full_nosearch (aname
, basedir
, status
, refonly
);
2337 /* Try a postload search hook */
2338 result
= mono_assembly_invoke_search_hook_internal (aname
, refonly
, TRUE
);
2343 * mono_assembly_load:
2344 * @aname: A MonoAssemblyName with the assembly name to load.
2345 * @basedir: A directory to look up the assembly at.
2346 * @status: a pointer to a MonoImageOpenStatus to return the status of the load operation
2348 * Loads the assembly referenced by @aname, if the value of @basedir is not NULL, it
2349 * attempts to load the assembly from that directory before probing the standard locations.
2351 * Returns: the assembly referenced by @aname loaded or NULL on error. On error the
2352 * value pointed by status is updated with an error code.
2355 mono_assembly_load (MonoAssemblyName
*aname
, const char *basedir
, MonoImageOpenStatus
*status
)
2357 return mono_assembly_load_full (aname
, basedir
, status
, FALSE
);
2361 mono_assembly_loaded_full (MonoAssemblyName
*aname
, gboolean refonly
)
2364 MonoAssemblyName maped_aname
;
2366 aname
= mono_assembly_remap_version (aname
, &maped_aname
);
2368 res
= mono_assembly_invoke_search_hook_internal (aname
, refonly
, FALSE
);
2374 * mono_assembly_loaded:
2375 * @aname: an assembly to look for.
2377 * Returns: NULL If the given @aname assembly has not been loaded, or a pointer to
2378 * a MonoAssembly that matches the MonoAssemblyName specified.
2381 mono_assembly_loaded (MonoAssemblyName
*aname
)
2383 return mono_assembly_loaded_full (aname
, FALSE
);
2387 * mono_assembly_close:
2388 * @assembly: the assembly to release.
2390 * This method releases a reference to the @assembly. The assembly is
2391 * only released when all the outstanding references to it are released.
2394 mono_assembly_close (MonoAssembly
*assembly
)
2397 g_return_if_fail (assembly
!= NULL
);
2399 if (assembly
== REFERENCE_MISSING
)
2402 /* Might be 0 already */
2403 if (InterlockedDecrement (&assembly
->ref_count
) > 0)
2406 mono_profiler_assembly_event (assembly
, MONO_PROFILE_START_UNLOAD
);
2408 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_ASSEMBLY
, "Unloading assembly %s [%p].", assembly
->aname
.name
, assembly
);
2410 mono_debug_close_image (assembly
->image
);
2412 mono_assemblies_lock ();
2413 loaded_assemblies
= g_list_remove (loaded_assemblies
, assembly
);
2414 mono_assemblies_unlock ();
2416 assembly
->image
->assembly
= NULL
;
2418 mono_image_close (assembly
->image
);
2420 for (tmp
= assembly
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
2421 MonoAssemblyName
*fname
= tmp
->data
;
2422 mono_assembly_name_free (fname
);
2425 g_slist_free (assembly
->friend_assembly_names
);
2426 g_free (assembly
->basedir
);
2427 if (assembly
->dynamic
) {
2428 g_free ((char*)assembly
->aname
.culture
);
2433 mono_profiler_assembly_event (assembly
, MONO_PROFILE_END_UNLOAD
);
2437 mono_assembly_load_module (MonoAssembly
*assembly
, guint32 idx
)
2439 return mono_image_load_file_for_image (assembly
->image
, idx
);
2443 mono_assembly_foreach (GFunc func
, gpointer user_data
)
2448 * We make a copy of the list to avoid calling the callback inside the
2449 * lock, which could lead to deadlocks.
2451 mono_assemblies_lock ();
2452 copy
= g_list_copy (loaded_assemblies
);
2453 mono_assemblies_unlock ();
2455 g_list_foreach (loaded_assemblies
, func
, user_data
);
2461 * mono_assemblies_cleanup:
2463 * Free all resources used by this module.
2466 mono_assemblies_cleanup (void)
2470 DeleteCriticalSection (&assemblies_mutex
);
2472 for (l
= loaded_assembly_bindings
; l
; l
= l
->next
) {
2473 MonoAssemblyBindingInfo
*info
= l
->data
;
2475 mono_assembly_binding_info_free (info
);
2478 g_slist_free (loaded_assembly_bindings
);
2480 free_assembly_load_hooks ();
2481 free_assembly_search_hooks ();
2482 free_assembly_preload_hooks ();
2486 * Holds the assembly of the application, for
2487 * System.Diagnostics.Process::MainModule
2489 static MonoAssembly
*main_assembly
=NULL
;
2492 mono_assembly_set_main (MonoAssembly
*assembly
)
2494 main_assembly
= assembly
;
2498 * mono_assembly_get_main:
2500 * Returns: the assembly for the application, the first assembly that is loaded by the VM
2503 mono_assembly_get_main (void)
2505 return (main_assembly
);
2509 * mono_assembly_get_image:
2510 * @assembly: The assembly to retrieve the image from
2512 * Returns: the MonoImage associated with this assembly.
2515 mono_assembly_get_image (MonoAssembly
*assembly
)
2517 return assembly
->image
;
2521 mono_register_bundled_assemblies (const MonoBundledAssembly
**assemblies
)
2523 bundles
= assemblies
;
2526 #define MONO_DECLSEC_FORMAT_10 0x3C
2527 #define MONO_DECLSEC_FORMAT_20 0x2E
2528 #define MONO_DECLSEC_FIELD 0x53
2529 #define MONO_DECLSEC_PROPERTY 0x54
2531 #define SKIP_VISIBILITY_XML_ATTRIBUTE ("\"SkipVerification\"")
2532 #define SKIP_VISIBILITY_ATTRIBUTE_NAME ("System.Security.Permissions.SecurityPermissionAttribute")
2533 #define SKIP_VISIBILITY_ATTRIBUTE_SIZE (sizeof (SKIP_VISIBILITY_ATTRIBUTE_NAME) - 1)
2534 #define SKIP_VISIBILITY_PROPERTY_NAME ("SkipVerification")
2535 #define SKIP_VISIBILITY_PROPERTY_SIZE (sizeof (SKIP_VISIBILITY_PROPERTY_NAME) - 1)
2538 mono_assembly_try_decode_skip_verification_param (const char *p
, const char **resp
, gboolean
*abort_decoding
)
2542 case MONO_DECLSEC_PROPERTY
:
2544 case MONO_DECLSEC_FIELD
:
2546 *abort_decoding
= TRUE
;
2551 if (*p
++ != MONO_TYPE_BOOLEAN
) {
2552 *abort_decoding
= TRUE
;
2556 /* property name length */
2557 len
= mono_metadata_decode_value (p
, &p
);
2559 if (len
>= SKIP_VISIBILITY_PROPERTY_SIZE
&& !memcmp (p
, SKIP_VISIBILITY_PROPERTY_NAME
, SKIP_VISIBILITY_PROPERTY_SIZE
)) {
2570 mono_assembly_try_decode_skip_verification (const char *p
, const char *endn
)
2572 int i
, j
, num
, len
, params_len
;
2574 if (*p
== MONO_DECLSEC_FORMAT_10
) {
2575 gsize read
, written
;
2576 char *res
= g_convert (p
, endn
- p
, "UTF-8", "UTF-16LE", &read
, &written
, NULL
);
2578 gboolean found
= strstr (res
, SKIP_VISIBILITY_XML_ATTRIBUTE
) != NULL
;
2584 if (*p
++ != MONO_DECLSEC_FORMAT_20
)
2587 /* number of encoded permission attributes */
2588 num
= mono_metadata_decode_value (p
, &p
);
2589 for (i
= 0; i
< num
; ++i
) {
2590 gboolean is_valid
= FALSE
;
2591 gboolean abort_decoding
= FALSE
;
2593 /* attribute name length */
2594 len
= mono_metadata_decode_value (p
, &p
);
2596 /* We don't really need to fully decode the type. Comparing the name is enough */
2597 is_valid
= len
>= SKIP_VISIBILITY_ATTRIBUTE_SIZE
&& !memcmp (p
, SKIP_VISIBILITY_ATTRIBUTE_NAME
, SKIP_VISIBILITY_ATTRIBUTE_SIZE
);
2601 /*size of the params table*/
2602 params_len
= mono_metadata_decode_value (p
, &p
);
2604 const char *params_end
= p
+ params_len
;
2606 /* number of parameters */
2607 len
= mono_metadata_decode_value (p
, &p
);
2609 for (j
= 0; j
< len
; ++j
) {
2610 if (mono_assembly_try_decode_skip_verification_param (p
, &p
, &abort_decoding
))
2626 mono_assembly_has_skip_verification (MonoAssembly
*assembly
)
2629 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
2633 if (MONO_SECMAN_FLAG_INIT (assembly
->skipverification
))
2634 return MONO_SECMAN_FLAG_GET_VALUE (assembly
->skipverification
);
2636 t
= &assembly
->image
->tables
[MONO_TABLE_DECLSECURITY
];
2638 for (i
= 0; i
< t
->rows
; ++i
) {
2639 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
2640 if ((cols
[MONO_DECL_SECURITY_PARENT
] & MONO_HAS_DECL_SECURITY_MASK
) != MONO_HAS_DECL_SECURITY_ASSEMBLY
)
2642 if (cols
[MONO_DECL_SECURITY_ACTION
] != SECURITY_ACTION_REQMIN
)
2645 blob
= mono_metadata_blob_heap (assembly
->image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
2646 len
= mono_metadata_decode_blob_size (blob
, &blob
);
2650 if (mono_assembly_try_decode_skip_verification (blob
, blob
+ len
)) {
2651 MONO_SECMAN_FLAG_SET_VALUE (assembly
->skipverification
, TRUE
);
2656 MONO_SECMAN_FLAG_SET_VALUE (assembly
->skipverification
, FALSE
);