2 * loader.c: Image Loader
5 * Paolo Molaro (lupus@ximian.com)
6 * Miguel de Icaza (miguel@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * (C) 2001 Ximian, Inc.
11 * This file is used by the interpreter and the JIT engine to locate
12 * assemblies. Used to load AssemblyRef and later to resolve various
16 * This should keep track of the assembly versions that we are loading.
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/image.h>
27 #include <mono/metadata/assembly.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/cil-coff.h>
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/metadata-internals.h>
32 #include <mono/metadata/loader.h>
33 #include <mono/metadata/class-internals.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/utils/mono-logger.h>
38 MonoDefaults mono_defaults
;
41 * This lock protects the hash tables inside MonoImage used by the metadata
42 * loading functions in class.c and loader.c.
44 static CRITICAL_SECTION loader_mutex
;
49 InitializeCriticalSection (&loader_mutex
);
52 static MonoClassField
*
53 field_from_memberref (MonoImage
*image
, guint32 token
, MonoClass
**retklass
,
54 MonoGenericContext
*context
)
57 MonoTableInfo
*tables
= image
->tables
;
59 guint32 nindex
, class;
62 guint32 idx
= mono_metadata_token_index (token
);
65 MonoClassField
*result
= mono_lookup_dynamic_token (image
, token
);
66 *retklass
= result
->parent
;
70 mono_metadata_decode_row (&tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, MONO_MEMBERREF_SIZE
);
71 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
72 class = cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
74 fname
= mono_metadata_string_heap (image
, cols
[MONO_MEMBERREF_NAME
]);
76 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
77 mono_metadata_decode_blob_size (ptr
, &ptr
);
78 /* we may want to check the signature here... */
81 case MONO_MEMBERREF_PARENT_TYPEREF
:
82 klass
= mono_class_from_typeref (image
, MONO_TOKEN_TYPE_REF
| nindex
);
84 g_warning ("Missing field %s in typeref index %d", fname
, nindex
);
87 mono_class_init (klass
);
90 return mono_class_get_field_from_name (klass
, fname
);
91 case MONO_MEMBERREF_PARENT_TYPESPEC
: {
92 /*guint32 bcols [MONO_TYPESPEC_SIZE];
96 mono_metadata_decode_row (&tables [MONO_TABLE_TYPESPEC], nindex - 1,
97 bcols, MONO_TYPESPEC_SIZE);
98 ptr = mono_metadata_blob_heap (image, bcols [MONO_TYPESPEC_SIGNATURE]);
99 len = mono_metadata_decode_value (ptr, &ptr);
100 type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
102 klass = mono_class_from_mono_type (type);
103 mono_class_init (klass);
104 g_print ("type in sig: %s\n", klass->name);*/
105 klass
= mono_class_get_full (image
, MONO_TOKEN_TYPE_SPEC
| nindex
, context
);
106 mono_class_init (klass
);
109 return mono_class_get_field_from_name (klass
, fname
);
112 g_warning ("field load from %x", class);
118 mono_field_from_token (MonoImage
*image
, guint32 token
, MonoClass
**retklass
,
119 MonoGenericContext
*context
)
123 MonoClassField
*field
;
125 if (image
->dynamic
) {
126 MonoClassField
*result
= mono_lookup_dynamic_token (image
, token
);
127 *retklass
= result
->parent
;
132 if ((field
= g_hash_table_lookup (image
->field_cache
, GUINT_TO_POINTER (token
)))) {
133 *retklass
= field
->parent
;
134 mono_loader_unlock ();
137 mono_loader_unlock ();
139 if (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
)
140 field
= field_from_memberref (image
, token
, retklass
, context
);
142 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
145 k
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| type
);
151 field
= mono_class_get_field (k
, token
);
155 if (!field
->parent
->generic_inst
)
156 g_hash_table_insert (image
->field_cache
, GUINT_TO_POINTER (token
), field
);
157 mono_loader_unlock ();
162 mono_metadata_signature_vararg_match (MonoMethodSignature
*sig1
, MonoMethodSignature
*sig2
)
166 if (sig1
->hasthis
!= sig2
->hasthis
||
167 sig1
->sentinelpos
!= sig2
->sentinelpos
)
170 for (i
= 0; i
< sig1
->sentinelpos
; i
++) {
171 MonoType
*p1
= sig1
->params
[i
];
172 MonoType
*p2
= sig2
->params
[i
];
174 /*if (p1->attrs != p2->attrs)
177 if (!mono_metadata_type_equal (p1
, p2
))
181 if (!mono_metadata_type_equal (sig1
->ret
, sig2
->ret
))
187 find_method (MonoClass
*klass
, MonoClass
*ic
, const char* name
, MonoMethodSignature
*sig
)
190 MonoClass
*sclass
= klass
;
191 char *qname
, *fqname
;
194 qname
= g_strconcat (ic
->name
, ".", name
, NULL
);
195 if (ic
->name_space
&& ic
->name_space
[0])
196 fqname
= g_strconcat (ic
->name_space
, ".", ic
->name
, ".", name
, NULL
);
200 qname
= fqname
= NULL
;
203 for (i
= 0; i
< klass
->method
.count
; ++i
) {
204 MonoMethod
*m
= klass
->methods
[i
];
206 if (!((fqname
&& !strcmp (m
->name
, fqname
)) ||
207 (qname
&& !strcmp (m
->name
, qname
)) || !strcmp (m
->name
, name
)))
210 if (sig
->call_convention
== MONO_CALL_VARARG
) {
211 if (mono_metadata_signature_vararg_match (sig
, m
->signature
))
214 if (mono_metadata_signature_equal (sig
, m
->signature
))
219 if (name
[0] == '.' && (strcmp (name
, ".ctor") == 0 || strcmp (name
, ".cctor") == 0))
222 klass
= klass
->parent
;
225 if (sclass
->generic_inst
) {
229 gclass
= mono_class_from_mono_type (sclass
->generic_inst
->generic_type
);
230 mono_class_init (gclass
);
232 res
= find_method (gclass
, ic
, name
, sig
);
235 for (i
= 0; i
< res
->klass
->method
.count
; ++i
) {
236 if (res
== res
->klass
->methods
[i
]) {
237 return sclass
->methods
[i
];
246 * token is the method_ref or method_def token used in a call IL instruction.
249 mono_method_get_signature (MonoMethod
*method
, MonoImage
*image
, guint32 token
)
251 int table
= mono_metadata_token_table (token
);
252 int idx
= mono_metadata_token_index (token
);
253 guint32 cols
[MONO_MEMBERREF_SIZE
];
254 MonoMethodSignature
*sig
;
257 /* !table is for wrappers: we should really assign their own token to them */
258 if (!table
|| table
== MONO_TABLE_METHOD
)
259 return method
->signature
;
261 if (table
== MONO_TABLE_METHODSPEC
) {
262 g_assert (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) &&
263 !(method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) &&
265 g_assert (method
->signature
->is_inflated
);
267 return method
->signature
;
270 if (method
->klass
->generic_inst
)
271 return method
->signature
;
274 /* FIXME: This might be incorrect for vararg methods */
275 return method
->signature
;
277 if (!(sig
= g_hash_table_lookup (image
->memberref_signatures
, GUINT_TO_POINTER (token
)))) {
278 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, MONO_MEMBERREF_SIZE
);
280 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
281 mono_metadata_decode_blob_size (ptr
, &ptr
);
282 sig
= mono_metadata_parse_method_signature (image
, 0, ptr
, NULL
);
283 g_hash_table_insert (image
->memberref_signatures
, GUINT_TO_POINTER (token
), sig
);
290 method_from_memberref (MonoImage
*image
, guint32 idx
, MonoGenericContext
*context
)
292 MonoClass
*klass
= NULL
;
294 MonoTableInfo
*tables
= image
->tables
;
296 guint32 nindex
, class;
297 MonoGenericContainer
*container
= NULL
;
299 MonoMethodSignature
*sig
;
302 mono_metadata_decode_row (&tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, 3);
303 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
304 class = cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
305 /*g_print ("methodref: 0x%x 0x%x %s\n", class, nindex,
306 mono_metadata_string_heap (m, cols [MONO_MEMBERREF_NAME]));*/
308 mname
= mono_metadata_string_heap (image
, cols
[MONO_MEMBERREF_NAME
]);
311 case MONO_MEMBERREF_PARENT_TYPEREF
:
312 klass
= mono_class_from_typeref (image
, MONO_TOKEN_TYPE_REF
| nindex
);
314 g_warning ("Missing method %s in assembly %s typeref index %d", mname
, image
->name
, nindex
);
318 case MONO_MEMBERREF_PARENT_TYPESPEC
:
319 klass
= mono_class_get_full (image
, MONO_TOKEN_TYPE_SPEC
| nindex
, context
);
321 g_warning ("Missing method %s in assembly %s typespec index %d", mname
, image
->name
, nindex
);
325 case MONO_MEMBERREF_PARENT_TYPEDEF
:
326 klass
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| nindex
);
328 g_warning ("Missing method %s in assembly %s typedef index %d", mname
, image
->name
, nindex
);
332 case MONO_MEMBERREF_PARENT_METHODDEF
:
333 return mono_get_method (image
, MONO_TOKEN_METHOD_DEF
| nindex
, NULL
);
335 g_error ("Memberref parent unknown: class: %d, index %d", class, nindex
);
336 g_assert_not_reached ();
339 mono_class_init (klass
);
341 if (klass
->generic_container
)
342 container
= klass
->generic_container
;
343 else if (klass
->generic_inst
) {
344 g_assert (klass
->generic_inst
->container
);
345 container
= klass
->generic_inst
->container
;
348 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
349 mono_metadata_decode_blob_size (ptr
, &ptr
);
350 sig
= mono_metadata_parse_method_signature_full (image
, container
, 0, ptr
, NULL
);
353 case MONO_MEMBERREF_PARENT_TYPEREF
:
354 method
= find_method (klass
, NULL
, mname
, sig
);
356 g_warning ("Missing method %s in assembly %s typeref index %d", mname
, image
->name
, nindex
);
357 mono_metadata_free_method_signature (sig
);
359 case MONO_MEMBERREF_PARENT_TYPESPEC
: {
363 type
= &klass
->byval_arg
;
365 if (type
->type
!= MONO_TYPE_ARRAY
&& type
->type
!= MONO_TYPE_SZARRAY
) {
366 method
= find_method (klass
, NULL
, mname
, sig
);
368 g_warning ("Missing method %s in assembly %s typeref index %d", mname
, image
->name
, nindex
);
369 else if (klass
->generic_inst
&& (klass
!= method
->klass
))
370 method
= mono_class_inflate_generic_method (
371 method
, klass
->generic_inst
->context
, klass
);
372 mono_metadata_free_method_signature (sig
);
376 result
= (MonoMethod
*)g_new0 (MonoMethodPInvoke
, 1);
377 result
->klass
= mono_class_get (image
, MONO_TOKEN_TYPE_SPEC
| nindex
);
378 result
->iflags
= METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
;
379 result
->signature
= sig
;
380 result
->name
= mname
;
382 if (!strcmp (mname
, ".ctor")) {
383 /* we special-case this in the runtime. */
388 if (!strcmp (mname
, "Set")) {
389 g_assert (sig
->hasthis
);
390 g_assert (type
->data
.array
->rank
+ 1 == sig
->param_count
);
391 result
->iflags
|= METHOD_IMPL_ATTRIBUTE_RUNTIME
;
396 if (!strcmp (mname
, "Get")) {
397 g_assert (sig
->hasthis
);
398 g_assert (type
->data
.array
->rank
== sig
->param_count
);
399 result
->iflags
|= METHOD_IMPL_ATTRIBUTE_RUNTIME
;
404 if (!strcmp (mname
, "Address")) {
405 g_assert (sig
->hasthis
);
406 g_assert (type
->data
.array
->rank
== sig
->param_count
);
407 result
->iflags
|= METHOD_IMPL_ATTRIBUTE_RUNTIME
;
412 g_assert_not_reached ();
415 case MONO_MEMBERREF_PARENT_TYPEDEF
:
416 method
= find_method (klass
, NULL
, mname
, sig
);
418 g_warning ("Missing method %s in assembly %s typeref index %d", mname
, image
->name
, nindex
);
419 mono_metadata_free_method_signature (sig
);
422 g_error ("Memberref parent unknown: class: %d, index %d", class, nindex
);
423 g_assert_not_reached ();
430 method_from_methodspec (MonoImage
*image
, MonoGenericContainer
*generic_container
, guint32 idx
)
432 MonoMethod
*method
, *inflated
;
433 MonoTableInfo
*tables
= image
->tables
;
434 MonoGenericContext
*context
;
435 MonoGenericMethod
*gmethod
;
436 MonoGenericContainer
*container
= NULL
;
438 guint32 cols
[MONO_METHODSPEC_SIZE
];
439 guint32 token
, param_count
, i
;
441 mono_metadata_decode_row (&tables
[MONO_TABLE_METHODSPEC
], idx
- 1, cols
, MONO_METHODSPEC_SIZE
);
442 token
= cols
[MONO_METHODSPEC_METHOD
];
443 if ((token
& MONO_METHODDEFORREF_MASK
) == MONO_METHODDEFORREF_METHODDEF
)
444 token
= MONO_TOKEN_METHOD_DEF
| (token
>> MONO_METHODDEFORREF_BITS
);
446 token
= MONO_TOKEN_MEMBER_REF
| (token
>> MONO_METHODDEFORREF_BITS
);
448 method
= mono_get_method (image
, token
, NULL
);
450 ptr
= mono_metadata_blob_heap (image
, cols
[MONO_METHODSPEC_SIGNATURE
]);
452 mono_metadata_decode_value (ptr
, &ptr
);
454 param_count
= mono_metadata_decode_value (ptr
, &ptr
);
456 g_assert (param_count
);
457 if (method
->signature
->is_inflated
)
458 container
= ((MonoMethodNormal
*) ((MonoMethodInflated
*) method
)->declaring
)->generic_container
;
460 container
= ((MonoMethodNormal
*) method
)->generic_container
;
461 g_assert (container
&& container
->method
);
462 if (generic_container
)
463 container
->parent
= generic_container
;
465 gmethod
= g_new0 (MonoGenericMethod
, 1);
466 gmethod
->container
= container
;
467 gmethod
->mtype_argc
= param_count
;
468 gmethod
->mtype_argv
= g_new0 (MonoType
*, param_count
);
470 for (i
= 0; i
< param_count
; i
++) {
471 gmethod
->mtype_argv
[i
] = mono_metadata_parse_type_full (
472 image
, container
, MONO_PARSE_TYPE
, 0, ptr
, &ptr
);
474 if (!gmethod
->is_open
)
475 gmethod
->is_open
= mono_class_is_open_constructed_type (gmethod
->mtype_argv
[i
]);
478 context
= g_new0 (MonoGenericContext
, 1);
479 context
->gmethod
= gmethod
;
481 mono_stats
.generics_metadata_size
+= sizeof (MonoGenericMethod
) +
482 sizeof (MonoGenericContext
) + param_count
* sizeof (MonoType
);
484 inflated
= mono_class_inflate_generic_method (method
, context
, NULL
);
486 context
->ginst
= inflated
->klass
->generic_inst
;
490 typedef struct MonoDllMap MonoDllMap
;
499 static GHashTable
*global_dll_map
;
502 mono_dllmap_lookup_hash (GHashTable
*dll_map
, const char *dll
, const char* func
, const char **rdll
, const char **rfunc
) {
503 MonoDllMap
*map
, *tmp
;
512 map
= g_hash_table_lookup (dll_map
, dll
);
514 mono_loader_unlock ();
517 *rdll
= map
->target
? map
->target
: dll
;
519 for (tmp
= map
->next
; tmp
; tmp
= tmp
->next
) {
520 if (strcmp (func
, tmp
->name
) == 0) {
524 mono_loader_unlock ();
529 mono_loader_unlock ();
534 mono_dllmap_lookup (MonoImage
*assembly
, const char *dll
, const char* func
, const char **rdll
, const char **rfunc
)
537 if (assembly
&& assembly
->dll_map
) {
538 res
= mono_dllmap_lookup_hash (assembly
->dll_map
, dll
, func
, rdll
, rfunc
);
542 return mono_dllmap_lookup_hash (global_dll_map
, dll
, func
, rdll
, rfunc
);
546 mono_dllmap_insert (MonoImage
*assembly
, const char *dll
, const char *func
, const char *tdll
, const char *tfunc
) {
547 MonoDllMap
*map
, *entry
;
548 GHashTable
*dll_map
= NULL
;
554 global_dll_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
555 dll_map
= global_dll_map
;
557 if (!assembly
->dll_map
)
558 assembly
->dll_map
= g_hash_table_new (g_str_hash
, g_str_equal
);
559 dll_map
= assembly
->dll_map
;
562 map
= g_hash_table_lookup (dll_map
, dll
);
564 map
= g_new0 (MonoDllMap
, 1);
565 map
->dll
= g_strdup (dll
);
567 map
->target
= g_strdup (tdll
);
568 g_hash_table_insert (dll_map
, map
->dll
, map
);
571 entry
= g_new0 (MonoDllMap
, 1);
572 entry
->name
= g_strdup (func
);
574 entry
->target
= g_strdup (tfunc
);
575 if (tdll
&& map
->target
&& strcmp (map
->target
, tdll
))
576 entry
->dll
= g_strdup (tdll
);
577 entry
->next
= map
->next
;
581 mono_loader_unlock ();
585 mono_lookup_pinvoke_call (MonoMethod
*method
, const char **exc_class
, const char **exc_arg
)
587 MonoImage
*image
= method
->klass
->image
;
588 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
589 MonoTableInfo
*tables
= image
->tables
;
590 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
591 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
592 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
594 const char *import
= NULL
;
595 const char *orig_scope
;
596 const char *new_scope
;
597 char *full_name
, *file_name
;
599 GModule
*gmodule
= NULL
;
601 g_assert (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
);
606 if (method
->klass
->image
->dynamic
) {
607 MonoReflectionMethodAux
*method_aux
=
608 mono_g_hash_table_lookup (
609 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
613 import
= method_aux
->dllentry
;
614 orig_scope
= method_aux
->dll
;
617 if (!piinfo
->implmap_idx
)
620 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
622 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
623 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
624 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
625 orig_scope
= mono_metadata_string_heap (image
, scope_token
);
628 mono_dllmap_lookup (image
, orig_scope
, import
, &new_scope
, &import
);
630 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
631 "DllImport attempting to load: '%s'.", new_scope
);
639 * Try loading the module using a variety of names
641 for (i
= 0; i
< 3; ++i
) {
644 /* Try the original name */
645 file_name
= g_strdup (new_scope
);
648 /* Try trimming the .dll extension */
649 if (strstr (new_scope
, ".dll") == (new_scope
+ strlen (new_scope
) - 4)) {
650 file_name
= g_strdup (new_scope
);
651 file_name
[strlen (new_scope
) - 4] = '\0';
657 if (strstr (new_scope
, "lib") != new_scope
) {
658 file_name
= g_strdup_printf ("lib%s", new_scope
);
666 full_name
= g_module_build_path (NULL
, file_name
);
667 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
668 "DllImport loading location: '%s'.", full_name
);
669 gmodule
= g_module_open (full_name
, G_MODULE_BIND_LAZY
);
671 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
672 "DllImport error loading library: '%s'.",
679 full_name
= g_module_build_path (".", file_name
);
680 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
681 "DllImport loading library: '%s'.", full_name
);
682 gmodule
= g_module_open (full_name
, G_MODULE_BIND_LAZY
);
684 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
685 "DllImport error loading library '%s'.",
692 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
693 "DllImport loading: '%s'.", file_name
);
694 gmodule
=g_module_open (file_name
, G_MODULE_BIND_LAZY
);
696 mono_trace (G_LOG_LEVEL_INFO
, MONO_TRACE_DLLIMPORT
,
697 "DllImport error loading library '%s'.",
709 mono_trace (G_LOG_LEVEL_WARNING
, MONO_TRACE_DLLIMPORT
,
710 "DllImport unable to load library '%s'.",
714 *exc_class
= "DllNotFoundException";
715 *exc_arg
= orig_scope
;
720 if (piinfo
->piflags
& PINVOKE_ATTRIBUTE_NO_MANGLE
) {
721 g_module_symbol (gmodule
, import
, &method
->addr
);
725 switch (piinfo
->piflags
& PINVOKE_ATTRIBUTE_CHAR_SET_MASK
) {
726 case PINVOKE_ATTRIBUTE_CHAR_SET_UNICODE
:
727 mangled_name
= g_strconcat (import
, "W", NULL
);
728 g_module_symbol (gmodule
, mangled_name
, &method
->addr
);
729 g_free (mangled_name
);
732 g_module_symbol (gmodule
, import
, &method
->addr
);
734 case PINVOKE_ATTRIBUTE_CHAR_SET_AUTO
:
735 g_module_symbol (gmodule
, import
, &method
->addr
);
737 case PINVOKE_ATTRIBUTE_CHAR_SET_ANSI
:
739 mangled_name
= g_strconcat (import
, "A", NULL
);
740 g_module_symbol (gmodule
, mangled_name
, &method
->addr
);
741 g_free (mangled_name
);
744 g_module_symbol (gmodule
, import
, &method
->addr
);
749 #ifdef PLATFORM_WIN32
750 /* Try the stdcall mangled name */
752 /* FIX: Compute this correctly */
753 mangled_name
= g_strdup_printf ("%s@%d", import
, method
->signature
->param_count
* sizeof (gpointer
));
754 g_module_symbol (gmodule
, mangled_name
, &method
->addr
);
755 g_free (mangled_name
);
758 mangled_name
= g_strdup_printf ("_%s@%d", import
, method
->signature
->param_count
* sizeof (gpointer
));
759 g_module_symbol (gmodule
, mangled_name
, &method
->addr
);
760 g_free (mangled_name
);
767 *exc_class
= "EntryPointNotFoundException";
776 mono_get_method_from_token (MonoImage
*image
, guint32 token
, MonoClass
*klass
,
777 MonoGenericContext
*context
)
780 int table
= mono_metadata_token_table (token
);
781 int idx
= mono_metadata_token_index (token
);
782 MonoTableInfo
*tables
= image
->tables
;
783 MonoGenericContainer
*generic_container
= NULL
, *container
= NULL
;
784 const char *loc
, *sig
= NULL
;
786 guint32 cols
[MONO_TYPEDEF_SIZE
];
789 return mono_lookup_dynamic_token (image
, token
);
791 if (table
!= MONO_TABLE_METHOD
) {
792 MonoGenericContainer
*generic_container
= NULL
;
794 if (context
->ginst
) {
795 g_assert (context
->ginst
->container
);
796 generic_container
= context
->ginst
->container
;
798 generic_container
= context
->container
;
800 if (table
== MONO_TABLE_METHODSPEC
)
801 return method_from_methodspec (image
, generic_container
, idx
);
802 if (table
!= MONO_TABLE_MEMBERREF
)
803 g_print("got wrong token: 0x%08x\n", token
);
804 g_assert (table
== MONO_TABLE_MEMBERREF
);
805 result
= method_from_memberref (image
, idx
, context
);
810 mono_metadata_decode_row (&tables
[table
], idx
- 1, cols
, 6);
812 if ((cols
[2] & METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
813 (cols
[1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
814 result
= (MonoMethod
*)g_new0 (MonoMethodPInvoke
, 1);
816 result
= (MonoMethod
*)g_new0 (MonoMethodNormal
, 1);
819 result
->klass
= klass
;
820 result
->flags
= cols
[2];
821 result
->iflags
= cols
[1];
822 result
->token
= token
;
823 result
->name
= mono_metadata_string_heap (image
, cols
[3]);
826 container
= klass
->generic_container
;
828 if (!(cols
[1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) &&
829 (!(cols
[2] & METHOD_ATTRIBUTE_PINVOKE_IMPL
) || cols
[1] & METHOD_IMPL_ATTRIBUTE_NATIVE
)) {
830 generic_container
= mono_metadata_load_generic_params (image
, token
);
831 if (generic_container
) {
832 generic_container
->parent
= container
;
833 generic_container
->method
= result
;
834 container
= generic_container
;
838 if (!sig
) /* already taken from the methodref */
839 sig
= mono_metadata_blob_heap (image
, cols
[4]);
840 size
= mono_metadata_decode_blob_size (sig
, &sig
);
841 result
->signature
= mono_metadata_parse_method_signature_full (image
, container
, idx
, sig
, NULL
);
843 if (!result
->klass
) {
844 guint32 type
= mono_metadata_typedef_from_method (image
, token
);
845 result
->klass
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| type
);
848 if (cols
[1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
849 if (result
->klass
== mono_defaults
.string_class
&& !strcmp (result
->name
, ".ctor"))
850 result
->string_ctor
= 1;
852 result
->signature
->pinvoke
= 1;
853 } else if ((cols
[2] & METHOD_ATTRIBUTE_PINVOKE_IMPL
) && (!(cols
[1] & METHOD_IMPL_ATTRIBUTE_NATIVE
))) {
854 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)result
;
855 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
856 MonoCallConvention conv
= 0;
858 result
->signature
->pinvoke
= 1;
859 piinfo
->implmap_idx
= mono_metadata_implmap_from_method (image
, idx
- 1);
860 piinfo
->piflags
= mono_metadata_decode_row_col (im
, piinfo
->implmap_idx
- 1, MONO_IMPLMAP_FLAGS
);
862 switch (piinfo
->piflags
& PINVOKE_ATTRIBUTE_CALL_CONV_MASK
) {
863 case PINVOKE_ATTRIBUTE_CALL_CONV_WINAPI
:
864 conv
= MONO_CALL_DEFAULT
;
866 case PINVOKE_ATTRIBUTE_CALL_CONV_CDECL
:
869 case PINVOKE_ATTRIBUTE_CALL_CONV_STDCALL
:
870 conv
= MONO_CALL_STDCALL
;
872 case PINVOKE_ATTRIBUTE_CALL_CONV_THISCALL
:
873 conv
= MONO_CALL_THISCALL
;
875 case PINVOKE_ATTRIBUTE_CALL_CONV_FASTCALL
:
876 conv
= MONO_CALL_FASTCALL
;
878 case PINVOKE_ATTRIBUTE_CALL_CONV_GENERIC
:
879 case PINVOKE_ATTRIBUTE_CALL_CONV_GENERICINST
:
881 g_warning ("unsupported calling convention");
882 g_assert_not_reached ();
884 result
->signature
->call_convention
= conv
;
886 MonoMethodNormal
*mn
= (MonoMethodNormal
*) result
;
888 /* if this is a methodref from another module/assembly, this fails */
889 loc
= mono_image_rva_map (image
, cols
[0]);
891 if (result
->signature
->generic_param_count
) {
892 MonoMethodSignature
*sig
= result
->signature
;
894 for (i
= 0; i
< sig
->generic_param_count
; i
++) {
895 generic_container
->type_params
[i
].method
= result
;
897 mono_class_from_generic_parameter (
898 &generic_container
->type_params
[i
], image
, TRUE
);
901 if (sig
->ret
->type
== MONO_TYPE_MVAR
) {
902 int num
= sig
->ret
->data
.generic_param
->num
;
903 sig
->ret
->data
.generic_param
= &generic_container
->type_params
[num
];
906 for (i
= 0; i
< sig
->param_count
; i
++) {
907 MonoType
*t
= sig
->params
[i
];
908 if (t
->type
== MONO_TYPE_MVAR
) {
909 int num
= t
->data
.generic_param
->num
;
910 sig
->params
[i
]->data
.generic_param
= &generic_container
->type_params
[num
];
915 if (!result
->klass
->dummy
&& !(result
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
916 !(result
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
918 mn
->header
= mono_metadata_parse_mh_full (image
, container
, loc
);
921 mn
->generic_container
= generic_container
;
928 mono_get_method (MonoImage
*image
, guint32 token
, MonoClass
*klass
)
930 return mono_get_method_full (image
, token
, klass
, NULL
);
934 mono_get_method_full (MonoImage
*image
, guint32 token
, MonoClass
*klass
,
935 MonoGenericContext
*context
)
939 /* We do everything inside the lock to prevent creation races */
943 if ((result
= g_hash_table_lookup (image
->method_cache
, GINT_TO_POINTER (token
)))) {
944 mono_loader_unlock ();
948 result
= mono_get_method_from_token (image
, token
, klass
, context
);
950 if (!(result
&& result
->signature
->is_inflated
))
951 g_hash_table_insert (image
->method_cache
, GINT_TO_POINTER (token
), result
);
953 mono_loader_unlock ();
959 mono_get_method_constrained (MonoImage
*image
, guint32 token
, MonoClass
*constrained_class
,
960 MonoGenericContext
*context
)
962 MonoMethod
*method
, *result
;
963 MonoClass
*ic
= NULL
;
967 method
= mono_get_method_from_token (image
, token
, NULL
, context
);
969 mono_loader_unlock ();
973 mono_class_init (constrained_class
);
975 if ((constrained_class
!= method
->klass
) && (method
->klass
->interface_id
!= 0))
978 result
= find_method (constrained_class
, ic
, method
->name
, method
->signature
);
980 g_warning ("Missing method %s in assembly %s token %x", method
->name
,
983 mono_loader_unlock ();
988 mono_free_method (MonoMethod
*method
)
990 mono_metadata_free_method_signature (method
->signature
);
991 if (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
992 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
993 g_free (piinfo
->code
);
994 } else if (!(method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
)) {
995 mono_metadata_free_mh (((MonoMethodNormal
*)method
)->header
);
1002 mono_method_get_param_names (MonoMethod
*method
, const char **names
)
1005 MonoClass
*klass
= method
->klass
;
1006 MonoTableInfo
*methodt
;
1007 MonoTableInfo
*paramt
;
1009 if (!method
->signature
->param_count
)
1011 for (i
= 0; i
< method
->signature
->param_count
; ++i
)
1014 if (klass
->generic_inst
) /* copy the names later */
1017 mono_class_init (klass
);
1019 if (klass
->image
->dynamic
) {
1020 MonoReflectionMethodAux
*method_aux
=
1021 mono_g_hash_table_lookup (
1022 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
1023 if (method_aux
&& method_aux
->param_names
) {
1024 for (i
= 0; i
< method
->signature
->param_count
; ++i
)
1025 if (method_aux
->param_names
[i
+ 1])
1026 names
[i
] = method_aux
->param_names
[i
+ 1];
1031 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
1032 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
1033 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1034 if (method
== klass
->methods
[i
]) {
1035 guint32 idx
= klass
->method
.first
+ i
;
1036 guint32 cols
[MONO_PARAM_SIZE
];
1037 guint param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
1039 if (idx
+ 1 < methodt
->rows
)
1040 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
1042 lastp
= paramt
->rows
+ 1;
1043 for (i
= param_index
; i
< lastp
; ++i
) {
1044 mono_metadata_decode_row (paramt
, i
-1, cols
, MONO_PARAM_SIZE
);
1045 if (cols
[MONO_PARAM_SEQUENCE
]) /* skip return param spec */
1046 names
[cols
[MONO_PARAM_SEQUENCE
] - 1] = mono_metadata_string_heap (klass
->image
, cols
[MONO_PARAM_NAME
]);
1054 mono_method_get_param_token (MonoMethod
*method
, int index
)
1057 MonoClass
*klass
= method
->klass
;
1058 MonoTableInfo
*methodt
;
1060 if (klass
->generic_inst
)
1061 g_assert_not_reached ();
1063 mono_class_init (klass
);
1065 if (klass
->image
->dynamic
) {
1066 g_assert_not_reached ();
1069 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
1070 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1071 if (method
== klass
->methods
[i
]) {
1072 guint32 idx
= klass
->method
.first
+ i
;
1073 guint param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
1075 return mono_metadata_make_token (MONO_TABLE_PARAM
, param_index
+ index
);
1083 mono_method_get_marshal_info (MonoMethod
*method
, MonoMarshalSpec
**mspecs
)
1086 MonoClass
*klass
= method
->klass
;
1087 MonoTableInfo
*methodt
;
1088 MonoTableInfo
*paramt
;
1090 for (i
= 0; i
< method
->signature
->param_count
+ 1; ++i
)
1093 if (method
->klass
->image
->dynamic
) {
1094 MonoReflectionMethodAux
*method_aux
=
1095 mono_g_hash_table_lookup (
1096 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
1097 if (method_aux
&& method_aux
->param_marshall
) {
1098 MonoMarshalSpec
**dyn_specs
= method_aux
->param_marshall
;
1099 for (i
= 0; i
< method
->signature
->param_count
+ 1; ++i
)
1100 if (dyn_specs
[i
]) {
1101 mspecs
[i
] = g_new0 (MonoMarshalSpec
, 1);
1102 memcpy (mspecs
[i
], dyn_specs
[i
], sizeof (MonoMarshalSpec
));
1108 mono_class_init (klass
);
1110 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
1111 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
1113 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1114 if (method
== klass
->methods
[i
]) {
1115 guint32 idx
= klass
->method
.first
+ i
;
1116 guint32 cols
[MONO_PARAM_SIZE
];
1117 guint param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
1119 if (idx
+ 1 < methodt
->rows
)
1120 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
1122 lastp
= paramt
->rows
+ 1;
1124 for (i
= param_index
; i
< lastp
; ++i
) {
1125 mono_metadata_decode_row (paramt
, i
-1, cols
, MONO_PARAM_SIZE
);
1127 if (cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL
) {
1129 tp
= mono_metadata_get_marshal_info (klass
->image
, i
- 1, FALSE
);
1131 mspecs
[cols
[MONO_PARAM_SEQUENCE
]]= mono_metadata_parse_marshal_spec (klass
->image
, tp
);
1141 mono_method_has_marshal_info (MonoMethod
*method
)
1144 MonoClass
*klass
= method
->klass
;
1145 MonoTableInfo
*methodt
;
1146 MonoTableInfo
*paramt
;
1148 if (method
->klass
->image
->dynamic
) {
1149 MonoReflectionMethodAux
*method_aux
=
1150 mono_g_hash_table_lookup (
1151 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
1152 MonoMarshalSpec
**dyn_specs
= method_aux
->param_marshall
;
1154 for (i
= 0; i
< method
->signature
->param_count
+ 1; ++i
)
1161 mono_class_init (klass
);
1163 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
1164 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
1166 for (i
= 0; i
< klass
->method
.count
; ++i
) {
1167 if (method
== klass
->methods
[i
]) {
1168 guint32 idx
= klass
->method
.first
+ i
;
1169 guint32 cols
[MONO_PARAM_SIZE
];
1170 guint param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
1172 if (idx
+ 1 < methodt
->rows
)
1173 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
1175 lastp
= paramt
->rows
+ 1;
1177 for (i
= param_index
; i
< lastp
; ++i
) {
1178 mono_metadata_decode_row (paramt
, i
-1, cols
, MONO_PARAM_SIZE
);
1180 if (cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL
)
1190 mono_method_get_wrapper_data (MonoMethod
*method
, guint32 id
)
1193 g_assert (method
!= NULL
);
1194 g_assert (method
->wrapper_type
!= MONO_WRAPPER_NONE
);
1196 if (!(l
= g_list_nth (((MonoMethodWrapper
*)method
)->data
, id
- 1)))
1197 g_assert_not_reached ();
1203 default_stack_walk (MonoStackWalk func
, gboolean do_il_offset
, gpointer user_data
) {
1204 g_error ("stack walk not installed");
1207 static MonoStackWalkImpl stack_walk
= default_stack_walk
;
1210 mono_stack_walk (MonoStackWalk func
, gpointer user_data
)
1212 stack_walk (func
, FALSE
, user_data
);
1216 mono_stack_walk_no_il (MonoStackWalk func
, gpointer user_data
)
1218 stack_walk (func
, TRUE
, user_data
);
1222 mono_install_stack_walk (MonoStackWalkImpl func
)
1228 last_managed (MonoMethod
*m
, gint no
, gint ilo
, gboolean managed
, gpointer data
)
1230 MonoMethod
**dest
= data
;
1232 /*g_print ("In %s::%s [%d] [%d]\n", m->klass->name, m->name, no, ilo);*/
1238 mono_method_get_last_managed (void)
1240 MonoMethod
*m
= NULL
;
1241 stack_walk (last_managed
, FALSE
, &m
);
1246 mono_loader_lock (void)
1248 EnterCriticalSection (&loader_mutex
);
1252 mono_loader_unlock (void)
1254 LeaveCriticalSection (&loader_mutex
);
1257 MonoMethodSignature
*
1258 mono_method_signature (MonoMethod
*method
)
1260 return method
->signature
;
1264 mono_method_get_name (MonoMethod
*method
)
1266 return method
->name
;
1270 mono_method_get_class (MonoMethod
*method
)
1272 return method
->klass
;
1276 mono_method_get_token (MonoMethod
*method
)
1278 return method
->token
;
1282 mono_method_get_flags (MonoMethod
*method
, guint32
*iflags
)
1285 *iflags
= method
->iflags
;
1286 return method
->flags
;