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_get_string_class_info:
55 * @ttoken: pointer to location to store type definition token
56 * @cl: pointer where image will be stored
58 * This routine locates information about the System.String class. A reference
59 * to the image containing the class is returned in @cl. The type definition
60 * token is returned in @ttoken.
62 * Returns: the method definition token for System.String::.ctor (char *)
66 mono_get_string_class_info (guint *ttoken, MonoImage **cl)
68 static guint32 ctor = 0, tt = 0;
69 enum MonoImageOpenStatus status = MONO_IMAGE_OK;
71 static MonoImage *corlib;
74 guint32 cols [MAX (MONO_TYPEDEF_SIZE, MONO_METHOD_SIZE)];
75 guint32 ncols [MONO_TYPEDEF_SIZE];
76 guint32 i, first = 0, last = 0;
77 const char *name, *nspace;
85 ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
86 g_assert (status == MONO_IMAGE_OK);
87 g_assert (ass != NULL);
89 *cl = corlib = ass->image;
90 g_assert (corlib != NULL);
92 m = &corlib->metadata;
93 t = &m->tables [MONO_TABLE_TYPEDEF];
95 for (i = 0; i < t->rows; i++) {
96 mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
97 name = mono_metadata_string_heap (m, cols[1]);
98 nspace = mono_metadata_string_heap (m, cols[2]);
100 if (((cols [0] & TYPE_ATTRIBUTE_CLASS_SEMANTIC_MASK) == TYPE_ATTRIBUTE_CLASS) &&
101 !strcmp (nspace, "System") && !strcmp (name, "String")) {
103 *ttoken = tt = MONO_TOKEN_TYPE_DEF | (i + 1);
105 first = cols [5] - 1;
107 if (i + 1 < t->rows) {
108 mono_metadata_decode_row (t, i + 1, ncols,
110 last = ncols [5] - 1;
112 last = m->tables [MONO_TABLE_METHOD].rows;
117 g_assert (last - first > 0);
119 t = &m->tables [MONO_TABLE_METHOD];
120 g_assert (last < t->rows);
122 for (i = first; i < last; i++) {
125 guint8 sig[] = { 0x20, 0x01, 0x01, 0x0f, 0x03 };
126 mono_metadata_decode_row (t, i, cols, MONO_METHOD_SIZE);
128 if (!strcmp (mono_metadata_string_heap (m, cols [3]),
130 (cols [2] & METHOD_ATTRIBUTE_SPECIAL_NAME)) {
132 ptr = mono_metadata_blob_heap (m, cols [4]);
133 len = mono_metadata_decode_value (ptr, &ptr);
135 if (len == 5 && !memcmp (ptr, sig, len)) {
136 ctor = MONO_TOKEN_METHOD_DEF | (i + 1);
147 typedef_from_name (MonoImage *image, const char *name, const char *nspace, guint32 *mlist)
149 MonoMetadata *m = &image->metadata;
150 MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
152 guint32 cols [MONO_TYPEDEF_SIZE];
154 for (i=0; i < t->rows; ++i) {
155 mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
156 if (strcmp (name, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME])) == 0
157 && strcmp (nspace, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE])) == 0) {
158 *mlist = cols [MONO_TYPEDEF_METHOD_LIST];
162 g_assert_not_reached ();
167 methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, guint32 *rindex)
169 MonoMetadata *m = &image->metadata;
170 MonoTableInfo *tables = m->tables;
172 guint32 nindex, sig_len, msig_len, class, i;
173 const char *sig, *msig, *mname, *name, *nspace;
175 mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], index-1, cols, 3);
176 nindex = cols [MONO_MEMBERREF_CLASS] >> MEMBERREF_PARENT_BITS;
177 class = cols [MONO_MEMBERREF_CLASS] & MEMBERREF_PARENT_MASK;
178 /*g_print ("methodref: 0x%x 0x%x %s\n", class, nindex,
179 mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));*/
180 sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
181 sig_len = mono_metadata_decode_blob_size (sig, &sig);
182 mname = mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]);
185 case MEMBERREF_PARENT_TYPEREF: {
186 guint32 scopeindex, scopetable;
188 mono_metadata_decode_row (&tables [MONO_TABLE_TYPEREF], nindex-1, cols, MONO_TYPEREF_SIZE);
189 scopeindex = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
190 scopetable = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
191 /*g_print ("typeref: 0x%x 0x%x %s.%s\n", scopetable, scopeindex,
192 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]),
193 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]));*/
194 switch (scopetable) {
195 case RESOLTION_SCOPE_ASSEMBLYREF:
197 * To find the method we have the following info:
198 * *) name and namespace of the class from the TYPEREF table
199 * *) name and signature of the method from the MEMBERREF table
201 nspace = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
202 name = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
204 /* this will triggered by references to mscorlib */
205 g_assert (image->references [scopeindex-1] != NULL);
207 image = image->references [scopeindex-1]->image;
209 m = &image->metadata;
210 tables = &m->tables [MONO_TABLE_METHOD];
211 typedef_from_name (image, name, nspace, &i);
212 /* mostly dumb search for now */
213 for (;i < tables->rows; ++i) {
214 mono_metadata_decode_row (tables, i, cols, MONO_METHOD_SIZE);
215 msig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
216 msig_len = mono_metadata_decode_blob_size (msig, &msig);
218 if (strcmp (mname, mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0
219 && sig_len == msig_len
220 && strncmp (sig, msig, sig_len) == 0) {
226 g_assert_not_reached ();
229 g_assert_not_reached ();
234 g_assert_not_reached ();
239 ves_map_ffi_type (MonoType *type)
244 return &ffi_type_void;
246 switch (type->type) {
248 rettype = &ffi_type_sint8;
250 case MONO_TYPE_BOOLEAN:
252 rettype = &ffi_type_uint8;
255 rettype = &ffi_type_sint16;
259 rettype = &ffi_type_uint16;
262 rettype = &ffi_type_sint32;
265 rettype = &ffi_type_sint32;
268 rettype = &ffi_type_float;
271 rettype = &ffi_type_double;
273 case MONO_TYPE_STRING:
274 rettype = &ffi_type_pointer;
277 g_warning ("not implemented");
278 g_assert_not_reached ();
286 fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
288 MonoMethod *mh = &piinfo->method;
289 MonoTableInfo *tables = image->metadata.tables;
290 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
291 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
294 const char *import = NULL;
295 const char *scope = NULL;
298 ffi_type **args, *rettype;
301 for (i = 0; i < im->rows; i++) {
303 mono_metadata_decode_row (im, i, im_cols, 4);
305 if ((im_cols[1] >> 1) == index + 1) {
307 import = mono_metadata_string_heap (&image->metadata,
310 mono_metadata_decode_row (mr, im_cols [3] - 1, mr_cols,
313 scope = mono_metadata_string_heap (&image->metadata,
318 g_assert (import && scope);
320 scope = mono_map_dll (scope);
321 full_name = g_module_build_path (NULL, scope);
322 gmodule = g_module_open (full_name, G_MODULE_BIND_LAZY);
327 piinfo->cif = g_new (ffi_cif , 1);
328 piinfo->piflags = im_cols [0];
330 g_module_symbol (gmodule, import, &piinfo->addr);
332 g_assert (piinfo->addr);
334 acount = mh->signature->param_count;
336 args = g_new (ffi_type *, acount);
338 for (i = 0; i < acount; i++)
339 args[i] = ves_map_ffi_type (mh->signature->params [i]->type);
341 rettype = ves_map_ffi_type (mh->signature->ret->type);
343 if (!ffi_prep_cif (piinfo->cif, FFI_DEFAULT_ABI, acount, rettype,
345 g_warning ("prepare pinvoke failed");
346 g_assert_not_reached ();
351 mono_get_method (MonoImage *image, guint32 token)
354 int table = mono_metadata_token_table (token);
355 int index = mono_metadata_token_index (token);
356 MonoTableInfo *tables = image->metadata.tables;
358 const char *sig = NULL;
362 if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
365 if (table != MONO_TABLE_METHOD) {
366 g_assert (table == MONO_TABLE_MEMBERREF);
367 methoddef_from_memberref (image, index, &image, &token);
368 return mono_get_method (image, MONO_TOKEN_METHOD_DEF | token);
371 mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
373 if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL)
374 result = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
376 result = (MonoMethod *)g_new0 (MonoMethodManaged, 1);
378 result->image = image;
379 result->flags = cols [2];
380 result->iflags = cols [1];
381 result->name = mono_metadata_string_heap (&image->metadata, cols [3]);
383 if (!sig) /* already taken from the methodref */
384 sig = mono_metadata_blob_heap (&image->metadata, cols [4]);
385 size = mono_metadata_decode_blob_size (sig, &sig);
386 result->signature = mono_metadata_parse_method_signature (&image->metadata, 0, sig, NULL);
389 if (result->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
390 fill_pinvoke_info (image, (MonoMethodPInvoke *)result,
393 /* if this is a methodref from another module/assembly, this fails */
394 loc = mono_cli_rva_map ((MonoCLIImageInfo *)image->image_info, cols [0]);
396 ((MonoMethodManaged *)result)->header =
397 mono_metadata_parse_mh (&image->metadata, loc);
400 g_hash_table_insert (image->method_cache, GINT_TO_POINTER (token), result);
406 mono_free_method (MonoMethod *method)
408 mono_metadata_free_method_signature (method->signature);
409 if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
410 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
411 g_free (piinfo->cif->arg_types);
412 g_free (piinfo->cif);
414 mono_metadata_free_mh (((MonoMethodManaged *)method)->header);