2 * assembly.c: Routines for loading assemblies.
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc. http://www.ximian.com
10 * Implement big-endian versions of the reading routines.
20 #include "rawbuffer.h"
22 #define CSIZE(x) (sizeof (x) / 4)
25 * keeps track of loaded assemblies
27 static GHashTable *assemblies;
30 * g_concat_dir_and_file:
31 * @dir: directory name
34 * returns a new allocated string that is the concatenation of dir and file,
35 * takes care of the exact details for concatenating them.
38 g_concat_dir_and_file (const char *dir, const char *file)
40 g_return_val_if_fail (dir != NULL, NULL);
41 g_return_val_if_fail (file != NULL, NULL);
44 * If the directory name doesn't have a / on the end, we need
45 * to add one so we get a proper path to the file
47 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
48 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
50 return g_strconcat (dir, file, NULL);
54 default_assembly_name_resolver (const char *base_dir, const char *name)
58 if ((strcmp (name, "mscorlib") == 0) ||
59 (strcmp (name, "mscorlib.dll") == 0) ||
60 (strcmp (name, "corlib.dll") == 0) ||
61 (strcmp (name, "corlib") == 0))
63 return g_concat_dir_and_file (MONO_ASSEMBLIES, CORLIB_NAME);
66 /* Full name already supplied */
67 path = g_strdup (name);
68 if (g_file_test (name, G_FILE_TEST_IS_REGULAR))
72 path = g_concat_dir_and_file (base_dir, name);
73 if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
77 path = g_strconcat (file, ".dll", NULL);
79 if (g_file_test (path, G_FILE_TEST_EXISTS))
83 path = g_concat_dir_and_file (MONO_ASSEMBLIES, name);
84 if (g_file_test (path, G_FILE_TEST_IS_REGULAR))
88 file = g_strconcat (name, ".dll", NULL);
89 path = g_concat_dir_and_file (MONO_ASSEMBLIES, file);
97 * @filename: Opens the assembly pointed out by this name
98 * @resolver: A user provided function to resolve assembly references
99 * @status: where a status code can be returned
101 * mono_assembly_open opens the PE-image pointed by @filename, and
102 * loads any external assemblies referenced by it.
104 * NOTE: we could do lazy loading of the assemblies. Or maybe not worth
108 mono_assembly_open (const char *filename, MonoAssemblyResolverFn resolver,
109 MonoImageOpenStatus *status)
115 char *fullname, *base_dir;
116 const char *base_name = strrchr (filename, G_DIR_SEPARATOR);
117 static MonoAssembly *corlib;
119 g_return_val_if_fail (filename != NULL, NULL);
121 if (assemblies == NULL)
122 assemblies = g_hash_table_new (g_str_hash, g_str_equal);
124 if ((ass = g_hash_table_lookup (assemblies, filename)) != NULL){
129 if (base_name == NULL)
130 base_name = filename;
134 if (resolver == NULL)
135 resolver = default_assembly_name_resolver;
137 base_dir = g_path_get_dirname (filename);
139 fullname = resolver (base_dir, filename);
140 image = mono_image_open (fullname, status);
144 *status = MONO_IMAGE_ERROR_ERRNO;
150 t = &image->tables [MONO_TABLE_ASSEMBLYREF];
152 image->references = g_new0 (MonoAssembly *, t->rows + 1);
155 * Create assembly struct, and enter it into the assembly cache
157 ass = g_new0 (MonoAssembly, 1);
158 ass->name = fullname;
161 image->assembly = ass;
163 g_hash_table_insert (assemblies, image->name, ass);
164 g_hash_table_insert (assemblies, ass->name, ass);
167 * Load any assemblies this image references
169 for (i = 0; i < t->rows; i++){
172 guint32 cols [MONO_ASSEMBLYREF_SIZE];
174 mono_metadata_decode_row (t, i, cols, CSIZE (cols));
175 name = mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME]);
178 * Special case until we have a passable corlib:
180 * ie, references to mscorlib from corlib.dll are ignored
181 * and we do not load corlib twice.
183 if (strcmp (base_name, CORLIB_NAME) == 0){
187 if (strcmp (name, "mscorlib") == 0)
191 assembly_ref = (*resolver) (base_dir, name);
193 image->references [i] = mono_assembly_open (assembly_ref, resolver, status);
195 if (image->references [i] == NULL){
198 for (j = 0; j < i; j++)
199 mono_assembly_close (image->references [j]);
200 g_free (image->references);
201 mono_image_close (image);
203 g_warning ("Could not find assembly %s %s", name, assembly_ref);
204 g_free (assembly_ref);
206 *status = MONO_IMAGE_MISSING_ASSEMBLYREF;
211 g_free (assembly_ref);
213 image->references [i] = NULL;
220 mono_assembly_close (MonoAssembly *assembly)
225 g_return_if_fail (assembly != NULL);
227 if (--assembly->ref_count != 0)
230 image = assembly->image;
231 for (i = 0; image->references [i] != NULL; i++)
232 mono_image_close (image->references [i]->image);
233 g_free (image->references);
235 g_hash_table_remove (assemblies, assembly->name);
237 mono_image_close (assembly->image);
239 g_free (assembly->name);
244 * Temporary hack until we get AppDomains
247 mono_get_assemblies ()