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/tokentype.h>
26 #include <mono/metadata/cil-coff.h>
27 #include <mono/metadata/tabledefs.h>
31 typedef_from_name (MonoImage *image, const char *name, const char *nspace, guint32 *mlist)
33 MonoMetadata *m = &image->metadata;
34 MonoTableInfo *t = &m->tables [MONO_TABLE_TYPEDEF];
36 guint32 cols [MONO_TYPEDEF_SIZE];
38 for (i=0; i < t->rows; ++i) {
39 mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
40 if (strcmp (name, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAME])) == 0
41 && strcmp (nspace, mono_metadata_string_heap (m, cols [MONO_TYPEDEF_NAMESPACE])) == 0) {
42 *mlist = cols [MONO_TYPEDEF_METHOD_LIST];
46 g_assert_not_reached ();
51 methoddef_from_memberref (MonoImage *image, guint32 index, MonoImage **rimage, guint32 *rindex)
53 MonoMetadata *m = &image->metadata;
54 MonoTableInfo *tables = m->tables;
56 guint32 nindex, sig_len, msig_len, class, i;
57 const char *sig, *msig, *mname, *name, *nspace;
59 mono_metadata_decode_row (&tables [MONO_TABLE_MEMBERREF], index-1, cols, 3);
60 nindex = cols [MONO_MEMBERREF_CLASS] >> MEMBERREF_PARENT_BITS;
61 class = cols [MONO_MEMBERREF_CLASS] & MEMBERREF_PARENT_MASK;
62 /*g_print ("methodref: 0x%x 0x%x %s\n", class, nindex,
63 mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));*/
64 sig = mono_metadata_blob_heap (m, cols [MONO_MEMBERREF_SIGNATURE]);
65 sig_len = mono_metadata_decode_blob_size (sig, &sig);
66 mname = mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]);
69 case MEMBERREF_PARENT_TYPEREF: {
70 guint32 scopeindex, scopetable;
72 mono_metadata_decode_row (&tables [MONO_TABLE_TYPEREF], nindex-1, cols, MONO_TYPEREF_SIZE);
73 scopeindex = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
74 scopetable = cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK;
75 /*g_print ("typeref: 0x%x 0x%x %s.%s\n", scopetable, scopeindex,
76 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]),
77 mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]));*/
79 case RESOLTION_SCOPE_ASSEMBLYREF:
81 * To find the method we have the following info:
82 * *) name and namespace of the class from the TYPEREF table
83 * *) name and signature of the method from the MEMBERREF table
85 nspace = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAMESPACE]);
86 name = mono_metadata_string_heap (m, cols [MONO_TYPEREF_NAME]);
88 image = image->references [scopeindex-1]->image;
90 tables = &m->tables [MONO_TABLE_METHOD];
91 typedef_from_name (image, name, nspace, &i);
92 /* mostly dumb search for now */
93 for (;i < tables->rows; ++i) {
94 mono_metadata_decode_row (tables, i, cols, MONO_METHOD_SIZE);
95 msig = mono_metadata_blob_heap (m, cols [MONO_METHOD_SIGNATURE]);
96 msig_len = mono_metadata_decode_blob_size (msig, &msig);
98 if (strcmp (mname, mono_metadata_string_heap (m, cols [MONO_METHOD_NAME])) == 0
99 && sig_len == msig_len
100 && strncmp (sig, msig, sig_len) == 0) {
106 g_assert_not_reached ();
109 g_assert_not_reached ();
114 g_assert_not_reached ();
119 ves_map_ffi_type (MonoType *type)
124 return &ffi_type_void;
126 switch (type->type) {
128 rettype = &ffi_type_sint8;
130 case MONO_TYPE_BOOLEAN:
132 rettype = &ffi_type_uint8;
135 rettype = &ffi_type_sint16;
139 rettype = &ffi_type_uint16;
142 rettype = &ffi_type_sint32;
145 rettype = &ffi_type_sint32;
148 rettype = &ffi_type_float;
151 rettype = &ffi_type_double;
153 case MONO_TYPE_STRING:
154 rettype = &ffi_type_pointer;
157 g_warning ("not implemented");
158 g_assert_not_reached ();
165 fill_pinvoke_info (MonoImage *image, MonoMethodPInvoke *piinfo, int index)
167 MonoMethod *mh = &piinfo->method;
168 MonoTableInfo *tables = image->metadata.tables;
169 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
170 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
173 const char *import = NULL;
174 const char *scope = NULL;
176 ffi_type **args, *rettype;
179 for (i = 0; i < im->rows; i++) {
181 mono_metadata_decode_row (im, i, im_cols, 4);
183 if ((im_cols[1] >> 1) == index + 1) {
185 import = mono_metadata_string_heap (&image->metadata,
188 mono_metadata_decode_row (mr, im_cols [3] - 1, mr_cols,
191 scope = mono_metadata_string_heap (&image->metadata,
196 g_assert (import && scope);
198 if (!strcmp (scope, "cygwin1.dll"))
201 gmodule = g_module_open (scope, G_MODULE_BIND_LAZY);
205 piinfo->cif = g_new (ffi_cif , 1);
206 piinfo->piflags = im_cols [0];
208 g_module_symbol (gmodule, import, &piinfo->addr);
210 g_assert (piinfo->addr);
212 acount = mh->signature->param_count;
214 args = g_new (ffi_type *, acount);
216 for (i = 0; i < acount; i++)
217 args[i] = ves_map_ffi_type (mh->signature->params [i]->type);
219 rettype = ves_map_ffi_type (mh->signature->ret->type);
221 if (!ffi_prep_cif (piinfo->cif, FFI_DEFAULT_ABI, acount, rettype,
223 g_warning ("prepare pinvoke failed");
224 g_assert_not_reached ();
229 mono_get_method (MonoImage *image, guint32 token)
232 int table = mono_metadata_token_table (token);
233 int index = mono_metadata_token_index (token);
234 MonoTableInfo *tables = image->metadata.tables;
236 const char *sig = NULL;
240 if (table == MONO_TABLE_METHOD && (result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (token))))
243 if (table != MONO_TABLE_METHOD) {
244 g_assert (table == MONO_TABLE_MEMBERREF);
245 methoddef_from_memberref (image, index, &image, &token);
246 return mono_get_method (image, MONO_TOKEN_METHOD_DEF | token);
250 mono_metadata_decode_row (&tables [table], index - 1, cols, 6);
252 if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL)
253 result = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
255 result = (MonoMethod *)g_new0 (MonoMethodManaged, 1);
257 result->image = image;
258 result->flags = cols [2];
259 result->iflags = cols [1];
260 result->name = mono_metadata_string_heap (&image->metadata, cols [3]);
262 if (!sig) /* already taken from the methodref */
263 sig = mono_metadata_blob_heap (&image->metadata, cols [4]);
264 size = mono_metadata_decode_blob_size (sig, &sig);
265 result->signature = mono_metadata_parse_method_signature (&image->metadata, 0, sig, NULL);
268 if (result->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
269 fill_pinvoke_info (image, (MonoMethodPInvoke *)result, index);
271 /* if this is a methodref from another module/assembly, this fails */
272 loc = mono_cli_rva_map ((MonoCLIImageInfo *)image->image_info, cols [0]);
274 ((MonoMethodManaged *)result)->header =
275 mono_metadata_parse_mh (&image->metadata, loc);
278 g_hash_table_insert (image->method_cache, GINT_TO_POINTER (token), result);
284 mono_free_method (MonoMethod *method)
286 mono_metadata_free_method_signature (method->signature);
287 if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
288 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
289 g_free (piinfo->cif->arg_types);
290 g_free (piinfo->cif);
292 mono_metadata_free_mh (((MonoMethodManaged *)method)->header);