2 * loader.c: Image Loader
5 * Paolo Molaro (lupus@ximian.com)
6 * Miguel de Icaza (miguel@ximian.com)
8 * (C) 2001 Ximian, Inc.
10 * This file is used by the interpreter and the JIT engine to locate
11 * assemblies. Used to load AssemblyRef and later to resolve various
15 * This should keep track of the assembly versions that we are loading.
23 #include <mono/metadata/metadata.h>
24 #include <mono/metadata/image.h>
25 #include <mono/metadata/assembly.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/cil-coff.h>
28 #include <mono/metadata/tabledefs.h>
32 static char *dll_map[] = {
35 "cygwin1.dll", "libc.so.6",
40 mono_map_dll (const char *name)
45 if (!strcmp (dll_map [i], name))
46 return dll_map [i + 1];
54 mono_typedef_from_name (MonoImage *image, const char *name,
55 const char *nspace, guint32 *mlist)
57 MonoMetadata *m = &image->metadata;
58 MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
60 guint32 cols [MONO_TYPEDEF_SIZE];
62 for (i=0; i < t->rows; ++i) {
63 mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
64 if (strcmp (name, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME])) == 0
65 && strcmp (nspace, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE])) == 0) {
67 *mlist = cols [MONO_TYPEDEF_METHOD_LIST];
71 g_assert_not_reached ();
76 * mono_get_string_class_info:
77 * @ttoken: pointer to location to store type definition token
78 * @cl: pointer where image will be stored
80 * This routine locates information about the System.String class. A reference
81 * to the image containing the class is returned in @cl. The type definition
82 * token is returned in @ttoken.
84 * Returns: the method definition token for System.String::.ctor (char *)
88 mono_get_string_class_info (guint *ttoken, MonoImage **cl)
90 static guint32 ctor = 0, tt = 0;
91 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
93 static MonoImage *corlib;
96 guint32 cols [MAX (MONO_TYPEDEF_SIZE, MONO_METHOD_SIZE)];
97 guint32 ncols [MONO_TYPEDEF_SIZE];
98 guint32 i, first = 0, last = 0;
99 const char *name, *nspace;
107 ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
108 g_assert (status == MONO_IMAGE_OK);
109 g_assert (ass != NULL);
111 *cl = corlib = ass->image;
112 g_assert (corlib != NULL);
114 m = &corlib->metadata;
115 t = &m->tables [MONO_TABLE_TYPEDEF];
117 for (i = 0; i < t->rows; i++) {
118 mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
119 name = mono_metadata_string_heap (m, cols[1]);
120 nspace = mono_metadata_string_heap (m, cols[2]);
122 if (((cols [0] & TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK) == TYPE_ATTRIBUTE_CLASS) &&
123 !strcmp (nspace, "System") && !strcmp (name, "String")) {
125 *ttoken = tt = MONO_TOKEN_TYPE_DEF | (i + 1);
127 first = cols [5] - 1;
129 if (i + 1 < t->rows) {
130 mono_metadata_decode_row (t, i + 1, ncols,
132 last = ncols [5] - 1;
134 last = m->tables [MONO_TABLE_METHOD].rows;
139 g_assert (last - first > 0);
141 t = &m->tables [MONO_TABLE_METHOD];
142 g_assert (last < t->rows);
144 for (i = first; i < last; i++) {
147 guint8 sig[] = { 0x20, 0x01, 0x01, 0x0f, 0x03 };
148 mono_metadata_decode_row (t, i, cols, MONO_METHOD_SIZE);
150 if (!strcmp (mono_metadata_string_heap (m, cols [3]),
152 (cols [2] & METHOD_ATTRIBUTE_SPECIAL_NAME)) {
154 ptr = mono_metadata_blob_heap (m, cols [4]);
155 len = mono_metadata_decode_value (ptr, &ptr);
157 if (len == 5 && !memcmp (ptr, sig, len)) {
158 ctor = MONO_TOKEN_METHOD_DEF | (i + 1);
169 methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, guint32 *rindex)
171 MonoMetadata *m = &image->metadata;
172 MonoTableInfo *tables = m->tables;
174 guint32 nindex, sig_len, msig_len, class, i;
175 const char *sig, *msig, *mname, *name, *nspace;
177 mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], index-1, cols, 3);
178 nindex = cols [MONO_MEMBERREF_CLASS] >> MEMBERREF_PARENT_BITS;
179 class = cols [MONO_MEMBERREF_CLASS] & MEMBERREF_PARENT_MASK;
180 /*g_print ("methodref: 0x%x 0x%x %s\n", class, nindex,
181 mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));*/
182 sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
183 sig_len = mono_metadata_decode_blob_size (sig, &sig);
184 mname = mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]);
187 case MEMBERREF_PARENT_TYPEREF: {
188 guint32 scopeindex, scopetable;
190 mono_metadata_decode_row (&tables [MONO_TABLE_TYPEREF], nindex-1, cols, MONO_TYPEREF_SIZE);
191 scopeindex = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
192 scopetable = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
193 /*g_print ("typeref: 0x%x 0x%x %s.%s\n", scopetable, scopeindex,
194 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]),
195 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]));*/
196 switch (scopetable) {
197 case RESOLTION_SCOPE_ASSEMBLYREF:
199 * To find the method we have the following info:
200 * *) name and namespace of the class from the TYPEREF table
201 * *) name and signature of the method from the MEMBERREF table
203 nspace = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
204 name = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
206 /* this will triggered by references to mscorlib */
207 g_assert (image->references [scopeindex-1] != NULL);
209 image = image->references [scopeindex-1]->image;
211 m = &image->metadata;
212 tables = &m->tables [MONO_TABLE_METHOD];
213 mono_typedef_from_name (image, name, nspace, &i);
214 /* mostly dumb search for now */
215 for (;i < tables->rows; ++i) {
216 mono_metadata_decode_row (tables, i, cols, MONO_METHOD_SIZE);
217 msig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
218 msig_len = mono_metadata_decode_blob_size (msig, &msig);
220 if (strcmp (mname, mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0
221 && sig_len == msig_len
222 && strncmp (sig, msig, sig_len) == 0) {
228 g_assert_not_reached ();
231 g_assert_not_reached ();
236 g_assert_not_reached ();
241 ves_map_ffi_type (MonoType *type)
246 return &ffi_type_void;
248 switch (type->type) {
250 rettype = &ffi_type_sint8;
252 case MONO_TYPE_BOOLEAN:
254 rettype = &ffi_type_uint8;
257 rettype = &ffi_type_sint16;
261 rettype = &ffi_type_uint16;
264 rettype = &ffi_type_sint32;
267 rettype = &ffi_type_sint32;
270 rettype = &ffi_type_float;
273 rettype = &ffi_type_double;
275 case MONO_TYPE_STRING:
276 rettype = &ffi_type_pointer;
279 g_warning ("not implemented");
280 g_assert_not_reached ();
287 fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
289 MonoMethod *mh = &piinfo->method;
290 MonoTableInfo *tables = image->metadata.tables;
291 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
292 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
295 const char *import = NULL;
296 const char *scope = NULL;
299 ffi_type **args, *rettype;
302 for (i = 0; i < im->rows; i++) {
304 mono_metadata_decode_row (im, i, im_cols, 4);
306 if ((im_cols[1] >> 1) == index + 1) {
308 import = mono_metadata_string_heap (&image->metadata,
311 mono_metadata_decode_row (mr, im_cols [3] - 1, mr_cols,
314 scope = mono_metadata_string_heap (&image->metadata,
319 g_assert (import && scope);
321 scope = mono_map_dll (scope);
322 full_name = g_module_build_path (NULL, scope);
323 gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY);
328 piinfo->cif = g_new (ffi_cif , 1);
329 piinfo->piflags = im_cols [0];
331 g_module_symbol (gmodule, import, &mh->addr);
335 acount = mh->signature->param_count;
337 args = g_new (ffi_type *, acount);
339 for (i = 0; i < acount; i++)
340 args[i] = ves_map_ffi_type (mh->signature->params [i]->type);
342 rettype = ves_map_ffi_type (mh->signature->ret->type);
344 if (!ffi_prep_cif (piinfo->cif, FFI_DEFAULT_ABI, acount, rettype,
346 g_warning ("prepare pinvoke failed");
347 g_assert_not_reached ();
352 mono_get_method (MonoImage *image, guint32 token)
355 MonoMetadata *m = &image->metadata;
356 int table = mono_metadata_token_table (token);
357 int index = mono_metadata_token_index (token);
358 MonoTableInfo *tables = m->tables;
359 const char *loc, *name;
360 const char *sig = NULL;
364 if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
367 if (table != MONO_TABLE_METHOD) {
368 g_assert (table == MONO_TABLE_MEMBERREF);
369 methoddef_from_memberref (image, index, &image, &token);
370 return mono_get_method (image, MONO_TOKEN_METHOD_DEF | token);
373 mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
375 if (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
376 MonoAssembly *corlib;
378 corlib = mono_assembly_open (CORLIB_NAME, NULL, NULL);
380 name = mono_metadata_string_heap (m, cols[3]);
382 /* all internal calls must be inside corlib */
383 g_assert (corlib->image == image);
385 result = (MonoMethod *)g_new0 (MonoMethod, 1);
387 result->addr = mono_lookup_internal_call (name);
389 g_assert (result->addr != NULL);
391 } else if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
393 result = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
396 result = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
399 result->image = image;
400 result->flags = cols [2];
401 result->iflags = cols [1];
402 result->name = mono_metadata_string_heap (m, cols [3]);
404 if (!sig) /* already taken from the methodref */
405 sig = mono_metadata_blob_heap (m, cols [4]);
406 size = mono_metadata_decode_blob_size (sig, &sig);
407 result->signature = mono_metadata_parse_method_signature (m, 0, sig,
411 if (result->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
412 fill_pinvoke_info (image, (MonoMethodPInvoke *)result,
414 } else if (!(result->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
415 /* if this is a methodref from another module/assembly, this fails */
416 loc = mono_cli_rva_map ((MonoCLIImageInfo *)image->image_info, cols [0]);
418 ((MonoMethodNormal *)result)->header =
419 mono_metadata_parse_mh (m, loc);
422 g_hash_table_insert (image->method_cache, GINT_TO_POINTER (token), result);
428 mono_free_method (MonoMethod *method)
430 mono_metadata_free_method_signature (method->signature);
431 if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
432 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
433 g_free (piinfo->cif->arg_types);
434 g_free (piinfo->cif);
435 } else if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
436 mono_metadata_free_mh (((MonoMethodNormal *)method)->header);