3 * System.Type icalls and related reflection queries.
6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2011 Rodrigo Kumpera
11 * Copyright 2016 Microsoft
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
16 #include "mono/utils/mono-membar.h"
17 #include "mono/metadata/reflection-internals.h"
18 #include "mono/metadata/tabledefs.h"
19 #include "mono/metadata/metadata-internals.h"
20 #include <mono/metadata/profiler-private.h>
21 #include "mono/metadata/class-internals.h"
22 #include "mono/metadata/class-init.h"
23 #include "mono/metadata/gc-internals.h"
24 #include "mono/metadata/domain-internals.h"
25 #include "mono/metadata/opcodes.h"
26 #include "mono/metadata/assembly.h"
27 #include "mono/metadata/object-internals.h"
28 #include <mono/metadata/exception.h>
29 #include <mono/metadata/marshal.h>
30 #include <mono/metadata/security-manager.h>
31 #include <mono/metadata/reflection-cache.h>
32 #include <mono/metadata/sre-internals.h>
41 #include "mono-endian.h"
42 #include <mono/metadata/gc-internals.h>
43 #include <mono/metadata/mempool-internals.h>
44 #include <mono/metadata/security-core-clr.h>
45 #include <mono/metadata/debug-helpers.h>
46 #include <mono/metadata/verify-internals.h>
47 #include <mono/metadata/mono-ptr-array.h>
48 #include <mono/metadata/mono-hash-internals.h>
49 #include <mono/utils/mono-string.h>
50 #include <mono/utils/mono-error-internals.h>
51 #include <mono/utils/checked-build.h>
52 #include <mono/utils/mono-counters.h>
53 #include "icall-decl.h"
55 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
56 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
);
58 /* Class lazy loading functions */
59 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly
, "System.Reflection", "RuntimeAssembly")
60 static GENERATE_GET_CLASS_WITH_CACHE (mono_module
, "System.Reflection", "RuntimeModule")
61 static GENERATE_GET_CLASS_WITH_CACHE (mono_method
, "System.Reflection", "RuntimeMethodInfo");
62 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod
, "System.Reflection", "RuntimeConstructorInfo");
63 static GENERATE_GET_CLASS_WITH_CACHE (mono_field
, "System.Reflection", "RuntimeFieldInfo");
64 static GENERATE_GET_CLASS_WITH_CACHE (mono_event
, "System.Reflection", "RuntimeEventInfo");
65 static GENERATE_GET_CLASS_WITH_CACHE (mono_property
, "System.Reflection", "RuntimePropertyInfo");
66 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info
, "System.Reflection", "RuntimeParameterInfo");
67 static GENERATE_GET_CLASS_WITH_CACHE (missing
, "System.Reflection", "Missing");
69 static GENERATE_GET_CLASS_WITH_CACHE (method_body
, "System.Reflection", "RuntimeMethodBody");
70 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info
, "System.Reflection", "RuntimeLocalVariableInfo");
71 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause
, "System.Reflection", "RuntimeExceptionHandlingClause");
73 static GENERATE_GET_CLASS_WITH_CACHE (method_body
, "System.Reflection", "MethodBody");
74 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info
, "System.Reflection", "LocalVariableInfo");
75 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause
, "System.Reflection", "ExceptionHandlingClause");
77 static GENERATE_GET_CLASS_WITH_CACHE (type_builder
, "System.Reflection.Emit", "TypeBuilder");
78 static GENERATE_GET_CLASS_WITH_CACHE (dbnull
, "System", "DBNull");
81 static int class_ref_info_handle_count
;
84 mono_reflection_init (void)
86 mono_reflection_emit_init ();
88 mono_counters_register ("MonoClass::ref_info_handle count",
89 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_ref_info_handle_count
);
94 * mono_class_get_ref_info:
96 * Return the type builder corresponding to KLASS, if it exists.
98 MonoReflectionTypeBuilderHandle
99 mono_class_get_ref_info (MonoClass
*klass
)
101 MONO_REQ_GC_UNSAFE_MODE
;
102 guint32 ref_info_handle
= mono_class_get_ref_info_handle (klass
);
104 if (ref_info_handle
== 0)
105 return MONO_HANDLE_NEW (MonoReflectionTypeBuilder
, NULL
);
106 return MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, mono_gchandle_get_target_handle (ref_info_handle
));
110 mono_class_has_ref_info (MonoClass
*klass
)
112 MONO_REQ_GC_UNSAFE_MODE
;
113 return 0 != mono_class_get_ref_info_handle (klass
);
116 MonoReflectionTypeBuilder
*
117 mono_class_get_ref_info_raw (MonoClass
*klass
)
119 /* FIXME callers of mono_class_get_ref_info_raw should use handles */
120 MONO_REQ_GC_UNSAFE_MODE
;
121 guint32 ref_info_handle
= mono_class_get_ref_info_handle (klass
);
123 if (ref_info_handle
== 0)
125 return (MonoReflectionTypeBuilder
*)mono_gchandle_get_target_internal (ref_info_handle
);
129 mono_class_set_ref_info (MonoClass
*klass
, MonoObjectHandle obj
)
131 MONO_REQ_GC_UNSAFE_MODE
;
133 guint32 candidate
= mono_gchandle_from_handle (obj
, FALSE
);
134 guint32 handle
= mono_class_set_ref_info_handle (klass
, candidate
);
135 ++class_ref_info_handle_count
;
137 if (handle
!= candidate
)
138 mono_gchandle_free_internal (candidate
);
142 mono_class_free_ref_info (MonoClass
*klass
)
144 MONO_REQ_GC_NEUTRAL_MODE
;
145 guint32 handle
= mono_class_get_ref_info_handle (klass
);
148 mono_gchandle_free_internal (handle
);
149 mono_class_set_ref_info_handle (klass
, 0);
154 * mono_custom_attrs_free:
157 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
159 MONO_REQ_GC_NEUTRAL_MODE
;
161 if (ainfo
&& !ainfo
->cached
)
166 mono_reflected_equal (gconstpointer a
, gconstpointer b
)
168 const ReflectedEntry
*ea
= (const ReflectedEntry
*)a
;
169 const ReflectedEntry
*eb
= (const ReflectedEntry
*)b
;
171 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
175 mono_reflected_hash (gconstpointer a
) {
176 const ReflectedEntry
*ea
= (const ReflectedEntry
*)a
;
177 /* Combine hashes for item and refclass. Identical to boost's hash_combine */
178 guint seed
= mono_aligned_addr_hash (ea
->item
) + 0x9e3779b9;
179 seed
^= mono_aligned_addr_hash (ea
->refclass
) + 0x9e3779b9 + (seed
<< 6) + (seed
>> 2);
184 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
186 mono_domain_lock (domain
);
187 if (domain
->refobject_hash
) {
189 gpointer orig_pe
, orig_value
;
194 if (mono_conc_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
195 mono_conc_g_hash_table_remove (domain
->refobject_hash
, &pe
);
196 free_reflected_entry ((ReflectedEntry
*)orig_pe
);
199 mono_domain_unlock (domain
);
203 cleanup_refobject_hash (gpointer key
, gpointer value
, gpointer user_data
)
205 free_reflected_entry ((ReflectedEntry
*)key
);
209 mono_reflection_cleanup_domain (MonoDomain
*domain
)
211 if (domain
->refobject_hash
) {
212 mono_conc_g_hash_table_foreach (domain
->refobject_hash
, cleanup_refobject_hash
, NULL
);
213 mono_conc_g_hash_table_destroy (domain
->refobject_hash
);
214 domain
->refobject_hash
= NULL
;
219 * mono_assembly_get_object:
220 * \param domain an app domain
221 * \param assembly an assembly
222 * \returns a \c System.Reflection.Assembly object representing the \c MonoAssembly \p assembly.
224 MonoReflectionAssembly
*
225 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
227 HANDLE_FUNCTION_ENTER ();
228 MonoReflectionAssemblyHandle result
;
229 MONO_ENTER_GC_UNSAFE
;
231 result
= mono_assembly_get_object_handle (domain
, assembly
, error
);
232 mono_error_cleanup (error
); /* FIXME new API that doesn't swallow the error */
234 HANDLE_FUNCTION_RETURN_OBJ (result
);
237 static MonoReflectionAssemblyHandle
238 assembly_object_construct (MonoDomain
*domain
, MonoClass
*unused_klass
, MonoAssembly
*assembly
, gpointer user_data
, MonoError
*error
)
241 MonoReflectionAssemblyHandle res
= MONO_HANDLE_CAST (MonoReflectionAssembly
, mono_object_new_handle (domain
, mono_class_get_mono_assembly_class (), error
));
242 return_val_if_nok (error
, MONO_HANDLE_CAST (MonoReflectionAssembly
, NULL_HANDLE
));
243 MONO_HANDLE_SETVAL (res
, assembly
, MonoAssembly
*, assembly
);
248 * mono_assembly_get_object_handle:
249 * @domain: an app domain
250 * @assembly: an assembly
252 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
254 MonoReflectionAssemblyHandle
255 mono_assembly_get_object_handle (MonoDomain
*domain
, MonoAssembly
*assembly
, MonoError
*error
)
258 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionAssembly
, assembly
, NULL
, assembly_object_construct
, NULL
);
262 * mono_module_get_object:
264 MonoReflectionModule
*
265 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
267 HANDLE_FUNCTION_ENTER ();
269 MonoReflectionModuleHandle result
= mono_module_get_object_handle (domain
, image
, error
);
270 mono_error_cleanup (error
);
271 HANDLE_FUNCTION_RETURN_OBJ (result
);
274 static MonoReflectionModuleHandle
275 module_object_construct (MonoDomain
*domain
, MonoClass
*unused_klass
, MonoImage
*image
, gpointer user_data
, MonoError
*error
)
280 MonoReflectionModuleHandle res
= MONO_HANDLE_CAST (MonoReflectionModule
, mono_object_new_handle (domain
, mono_class_get_mono_module_class (), error
));
281 goto_if_nok (error
, fail
);
283 MONO_HANDLE_SETVAL (res
, image
, MonoImage
*, image
);
284 MonoReflectionAssemblyHandle assm_obj
;
285 assm_obj
= mono_assembly_get_object_handle (domain
, image
->assembly
, error
);
286 goto_if_nok (error
, fail
);
287 MONO_HANDLE_SET (res
, assembly
, assm_obj
);
289 MONO_HANDLE_SET (res
, fqname
, mono_string_new_handle (domain
, image
->name
, error
));
290 goto_if_nok (error
, fail
);
291 basename
= g_path_get_basename (image
->name
);
292 MONO_HANDLE_SET (res
, name
, mono_string_new_handle (domain
, basename
, error
));
293 goto_if_nok (error
, fail
);
294 MONO_HANDLE_SET (res
, scopename
, mono_string_new_handle (domain
, image
->module_name
, error
));
295 goto_if_nok (error
, fail
);
301 if (image
->assembly
->image
== image
) {
302 token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
305 if (image
->assembly
->image
->modules
) {
306 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
307 if (image
->assembly
->image
->modules
[i
] == image
)
308 token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
310 g_assert (token
!= 0);
313 MONO_HANDLE_SETVAL (res
, token
, guint32
, token
);
317 return MONO_HANDLE_CAST (MonoReflectionModule
, NULL_HANDLE
);
320 MonoReflectionModuleHandle
321 mono_module_get_object_handle (MonoDomain
*domain
, MonoImage
*image
, MonoError
*error
)
324 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionModule
, image
, NULL
, module_object_construct
, NULL
);
328 * mono_module_file_get_object:
330 MonoReflectionModule
*
331 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
333 HANDLE_FUNCTION_ENTER ();
335 MonoReflectionModuleHandle result
= mono_module_file_get_object_handle (domain
, image
, table_index
, error
);
336 mono_error_cleanup (error
);
337 HANDLE_FUNCTION_RETURN_OBJ (result
);
340 MonoReflectionModuleHandle
341 mono_module_file_get_object_handle (MonoDomain
*domain
, MonoImage
*image
, int table_index
, MonoError
*error
)
343 MonoTableInfo
*table
;
344 guint32 cols
[MONO_FILE_SIZE
];
351 MonoReflectionModuleHandle res
= MONO_HANDLE_CAST (MonoReflectionModule
, mono_object_new_handle (domain
, mono_class_get_mono_module_class (), error
));
352 goto_if_nok (error
, fail
);
354 table
= &image
->tables
[MONO_TABLE_FILE
];
355 g_assert (table_index
< table
->rows
);
356 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
358 MONO_HANDLE_SETVAL (res
, image
, MonoImage
*, NULL
);
359 MonoReflectionAssemblyHandle assm_obj
;
360 assm_obj
= mono_assembly_get_object_handle (domain
, image
->assembly
, error
);
361 goto_if_nok (error
, fail
);
362 MONO_HANDLE_SET (res
, assembly
, assm_obj
);
363 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
365 /* Check whenever the row has a corresponding row in the moduleref table */
366 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
367 for (i
= 0; i
< table
->rows
; ++i
) {
368 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
369 val
= mono_metadata_string_heap (image
, name_idx
);
370 if (strcmp (val
, name
) == 0)
371 MONO_HANDLE_SETVAL (res
, image
, MonoImage
*, image
->modules
[i
]);
374 MONO_HANDLE_SET (res
, fqname
, mono_string_new_handle (domain
, name
, error
));
375 goto_if_nok (error
, fail
);
376 MONO_HANDLE_SET (res
, name
, mono_string_new_handle (domain
, name
, error
));
377 goto_if_nok (error
, fail
);
378 MONO_HANDLE_SET (res
, scopename
, mono_string_new_handle (domain
, name
, error
));
379 goto_if_nok (error
, fail
);
380 MONO_HANDLE_SETVAL (res
, is_resource
, MonoBoolean
, cols
[MONO_FILE_FLAGS
] & FILE_CONTAINS_NO_METADATA
);
381 MONO_HANDLE_SETVAL (res
, token
, guint32
, mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1));
385 return MONO_HANDLE_CAST (MonoReflectionModule
, NULL_HANDLE
);
389 mono_type_normalize (MonoType
*type
)
392 MonoGenericClass
*gclass
;
393 MonoGenericInst
*ginst
;
395 MonoGenericContainer
*gcontainer
;
396 MonoType
**argv
= NULL
;
397 gboolean is_denorm_gtd
= TRUE
, requires_rebind
= FALSE
;
399 if (type
->type
!= MONO_TYPE_GENERICINST
)
402 gclass
= type
->data
.generic_class
;
403 ginst
= gclass
->context
.class_inst
;
407 gtd
= gclass
->container_class
;
408 gcontainer
= mono_class_get_generic_container (gtd
);
409 argv
= g_newa (MonoType
*, ginst
->type_argc
);
411 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
412 MonoType
*t
= ginst
->type_argv
[i
], *norm
;
413 if (t
->type
!= MONO_TYPE_VAR
|| t
->data
.generic_param
->num
!= i
|| t
->data
.generic_param
->owner
!= gcontainer
)
414 is_denorm_gtd
= FALSE
;
415 norm
= mono_type_normalize (t
);
418 requires_rebind
= TRUE
;
422 return type
->byref
== m_class_get_byval_arg (gtd
)->byref
? m_class_get_byval_arg (gtd
) : m_class_get_this_arg (gtd
);
424 if (requires_rebind
) {
425 MonoClass
*klass
= mono_class_bind_generic_parameters (gtd
, ginst
->type_argc
, argv
, gclass
->is_dynamic
);
426 return type
->byref
== m_class_get_byval_arg (klass
)->byref
? m_class_get_byval_arg (klass
) : m_class_get_this_arg (klass
);
433 * mono_type_get_object:
434 * \param domain an app domain
436 * \returns A \c System.MonoType object representing the type \p type.
439 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
441 MonoReflectionType
*ret
;
442 MONO_ENTER_GC_UNSAFE
;
444 ret
= mono_type_get_object_checked (domain
, type
, error
);
445 mono_error_cleanup (error
);
451 mono_type_get_object_checked (MonoDomain
*domain
, MonoType
*type
, MonoError
*error
)
454 MonoReflectionType
*res
;
459 g_assert (type
!= NULL
);
460 klass
= mono_class_from_mono_type_internal (type
);
462 /*we must avoid using @type as it might have come
463 * from a mono_metadata_type_dup and the caller
464 * expects that is can be freed.
465 * Using the right type from
467 type
= m_class_get_byval_arg (klass
)->byref
== type
->byref
? m_class_get_byval_arg (klass
) : m_class_get_this_arg (klass
);
469 /* We don't want to return types with custom modifiers to the managed
470 * world since they're hard to distinguish from plain types using the
471 * reflection APIs, but they are not ReferenceEqual to the unadorned
474 * If we ever see cmods here, it's a bug: MonoClass:byval_arg and
475 * MonoClass:this_arg shouldn't have cmods by construction.
477 g_assert (!type
->has_cmods
);
479 /* void is very common */
480 #ifdef ENABLE_NETCORE
481 if (!type
->byref
&& type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
482 return (MonoReflectionType
*)domain
->typeof_void
;
484 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
485 return (MonoReflectionType
*)domain
->typeof_void
;
489 * If the vtable of the given class was already created, we can use
490 * the MonoType from there and avoid all locking and hash table lookups.
492 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
493 * that the resulting object is different.
495 if (type
== m_class_get_byval_arg (klass
) && !image_is_dynamic (m_class_get_image (klass
))) {
496 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
497 if (vtable
&& vtable
->type
)
498 return (MonoReflectionType
*)vtable
->type
;
501 mono_loader_lock (); /*FIXME mono_class_init_internal and mono_class_vtable acquire it*/
502 mono_domain_lock (domain
);
503 if (!domain
->type_hash
)
504 domain
->type_hash
= mono_g_hash_table_new_type_internal ((GHashFunc
)mono_metadata_type_hash
,
505 (GCompareFunc
)mono_metadata_type_equal
, MONO_HASH_VALUE_GC
, MONO_ROOT_SOURCE_DOMAIN
, domain
, "Domain Reflection Type Table");
506 if ((res
= (MonoReflectionType
*)mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
507 mono_domain_unlock (domain
);
508 mono_loader_unlock ();
512 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
513 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
514 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
515 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
516 * artifact of how generics are encoded and should be transparent to managed code so we
517 * need to weed out this diference when retrieving managed System.Type objects.
519 norm_type
= mono_type_normalize (type
);
520 if (norm_type
!= type
) {
521 res
= mono_type_get_object_checked (domain
, norm_type
, error
);
522 if (!mono_error_ok (error
)) {
523 mono_domain_unlock (domain
);
524 mono_loader_unlock ();
527 mono_g_hash_table_insert_internal (domain
->type_hash
, type
, res
);
528 mono_domain_unlock (domain
);
529 mono_loader_unlock ();
533 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !m_class_was_typebuilder (type
->data
.generic_class
->container_class
)) {
534 /* This can happen if a TypeBuilder for a generic class K<T,U>
535 * had reflection_create_generic_class) called on it, but not
536 * ves_icall_TypeBuilder_create_runtime_class. This can happen
537 * if the K`2 is refernced from a generic instantiation
538 * (e.g. K<int,string>) that appears as type argument
539 * (e.g. Dict<string,K<int,string>>), field (e.g. K<int,string>
540 * Foo) or method signature, parent class or any of the above
541 * in a nested class of some other TypeBuilder. Such an
542 * occurrence caused mono_reflection_type_get_handle to be
543 * called on the sre generic instance (K<int,string>) which
544 * required the container_class for the generic class K`2 to be
545 * set up, but the remainder of class construction for K`2 has
547 char * full_name
= mono_type_get_full_name (klass
);
548 /* I would have expected ReflectionTypeLoadException, but evidently .NET throws TLE in this case. */
549 mono_error_set_type_load_class (error
, klass
, "TypeBuilder.CreateType() not called for generic class %s", full_name
);
551 mono_domain_unlock (domain
);
552 mono_loader_unlock ();
556 if (mono_class_has_ref_info (klass
) && !m_class_was_typebuilder (klass
) && !type
->byref
) {
557 mono_domain_unlock (domain
);
558 mono_loader_unlock ();
559 return &mono_class_get_ref_info_raw (klass
)->type
; /* FIXME use handles */
561 /* This is stored in vtables/JITted code so it has to be pinned */
562 res
= (MonoReflectionType
*)mono_object_new_pinned (domain
, mono_defaults
.runtimetype_class
, error
);
563 if (!mono_error_ok (error
)) {
564 mono_domain_unlock (domain
);
565 mono_loader_unlock ();
570 mono_g_hash_table_insert_internal (domain
->type_hash
, type
, res
);
572 if (type
->type
== MONO_TYPE_VOID
)
573 domain
->typeof_void
= (MonoObject
*)res
;
575 mono_domain_unlock (domain
);
576 mono_loader_unlock ();
580 MonoReflectionTypeHandle
581 mono_type_get_object_handle (MonoDomain
*domain
, MonoType
*type
, MonoError
*error
)
583 /* NOTE: We happen to know that mono_type_get_object_checked returns
584 * pinned objects, so we can just wrap its return value in a handle for
585 * uniformity. If it ever starts returning unpinned, objects, this
586 * implementation would need to change!
588 return MONO_HANDLE_NEW (MonoReflectionType
, mono_type_get_object_checked (domain
, type
, error
));
592 * mono_method_get_object:
593 * \param domain an app domain
594 * \param method a method
595 * \param refclass the reflected type (can be NULL)
596 * \returns A \c System.Reflection.MonoMethod object representing the method \p method.
598 MonoReflectionMethod
*
599 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
601 HANDLE_FUNCTION_ENTER ();
602 MonoReflectionMethodHandle ret
;
603 MONO_ENTER_GC_UNSAFE
;
605 ret
= mono_method_get_object_handle (domain
, method
, refclass
, error
);
606 mono_error_cleanup (error
);
608 HANDLE_FUNCTION_RETURN_OBJ (ret
);
611 static MonoReflectionMethodHandle
612 method_object_construct (MonoDomain
*domain
, MonoClass
*refclass
, MonoMethod
*method
, gpointer user_data
, MonoError
*error
)
615 g_assert (refclass
!= NULL
);
617 * We use the same C representation for methods and constructors, but the type
618 * name in C# is different.
624 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
625 klass
= mono_class_get_mono_cmethod_class ();
628 klass
= mono_class_get_mono_method_class ();
630 MonoReflectionMethodHandle ret
= MONO_HANDLE_CAST (MonoReflectionMethod
, mono_object_new_handle (domain
, klass
, error
));
631 goto_if_nok (error
, fail
);
632 MONO_HANDLE_SETVAL (ret
, method
, MonoMethod
*, method
);
634 MonoReflectionTypeHandle rt
;
635 rt
= mono_type_get_object_handle (domain
, m_class_get_byval_arg (refclass
), error
);
636 goto_if_nok (error
, fail
);
638 MONO_HANDLE_SET (ret
, reftype
, rt
);
643 return MONO_HANDLE_CAST (MonoReflectionMethod
, NULL_HANDLE
);
647 * mono_method_get_object_handle:
648 * @domain: an app domain
650 * @refclass: the reflected type (can be NULL)
651 * @error: set on error.
653 * Return an System.Reflection.MonoMethod object representing the method @method.
654 * Returns NULL and sets @error on error.
656 MonoReflectionMethodHandle
657 mono_method_get_object_handle (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
, MonoError
*error
)
661 refclass
= method
->klass
;
663 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethod
, method
, refclass
, method_object_construct
, NULL
);
666 * mono_method_get_object_checked:
667 * @domain: an app domain
669 * @refclass: the reflected type (can be NULL)
670 * @error: set on error.
672 * Return an System.Reflection.MonoMethod object representing the method @method.
673 * Returns NULL and sets @error on error.
675 MonoReflectionMethod
*
676 mono_method_get_object_checked (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
, MonoError
*error
)
678 HANDLE_FUNCTION_ENTER ();
679 MonoReflectionMethodHandle result
= mono_method_get_object_handle (domain
, method
, refclass
, error
);
680 HANDLE_FUNCTION_RETURN_OBJ (result
);
684 * mono_method_clear_object:
686 * Clear the cached reflection objects for the dynamic method METHOD.
689 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
692 g_assert (method_is_dynamic (method
));
694 klass
= method
->klass
;
696 clear_cached_object (domain
, method
, klass
);
697 klass
= m_class_get_parent (klass
);
699 /* Added by mono_param_get_objects () */
700 clear_cached_object (domain
, &(method
->signature
), NULL
);
701 klass
= method
->klass
;
703 clear_cached_object (domain
, &(method
->signature
), klass
);
704 klass
= m_class_get_parent (klass
);
709 * mono_field_get_object:
710 * \param domain an app domain
711 * \param klass a type
712 * \param field a field
713 * \returns A \c System.Reflection.MonoField object representing the field \p field
717 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
719 HANDLE_FUNCTION_ENTER ();
721 MonoReflectionFieldHandle result
= mono_field_get_object_handle (domain
, klass
, field
, error
);
722 mono_error_cleanup (error
);
723 HANDLE_FUNCTION_RETURN_OBJ (result
);
726 static MonoReflectionFieldHandle
727 field_object_construct (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
, gpointer user_data
, MonoError
*error
)
731 MonoReflectionFieldHandle res
= MONO_HANDLE_CAST (MonoReflectionField
, mono_object_new_handle (domain
, mono_class_get_mono_field_class (), error
));
732 goto_if_nok (error
, fail
);
733 MONO_HANDLE_SETVAL (res
, klass
, MonoClass
*, klass
);
734 MONO_HANDLE_SETVAL (res
, field
, MonoClassField
*, field
);
735 MonoStringHandle name
;
736 name
= mono_string_new_handle (domain
, mono_field_get_name (field
), error
);
737 goto_if_nok (error
, fail
);
738 MONO_HANDLE_SET (res
, name
, name
);
741 MonoReflectionTypeHandle rt
= mono_type_get_object_handle (domain
, field
->type
, error
);
742 goto_if_nok (error
, fail
);
744 MONO_HANDLE_SET (res
, type
, rt
);
746 MONO_HANDLE_SETVAL (res
, attrs
, guint32
, mono_field_get_flags (field
));
749 return MONO_HANDLE_CAST (MonoReflectionField
, NULL_HANDLE
);
753 * mono_field_get_object_handle:
754 * @domain: an app domain
757 * @error: set on error
759 * Return an System.Reflection.MonoField object representing the field @field
760 * in class @klass. On error, returns NULL and sets @error.
762 MonoReflectionFieldHandle
763 mono_field_get_object_handle (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
766 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionField
, field
, klass
, field_object_construct
, NULL
);
771 * mono_field_get_object_checked:
772 * @domain: an app domain
775 * @error: set on error
777 * Return an System.Reflection.MonoField object representing the field @field
778 * in class @klass. On error, returns NULL and sets @error.
781 mono_field_get_object_checked (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
783 HANDLE_FUNCTION_ENTER ();
784 MonoReflectionFieldHandle result
= mono_field_get_object_handle (domain
, klass
, field
, error
);
785 HANDLE_FUNCTION_RETURN_OBJ (result
);
789 * mono_property_get_object:
790 * @domain: an app domain
792 * @property: a property
794 * Return an System.Reflection.MonoProperty object representing the property @property
797 MonoReflectionProperty
*
798 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
800 HANDLE_FUNCTION_ENTER ();
802 MonoReflectionPropertyHandle result
= mono_property_get_object_handle (domain
, klass
, property
, error
);
803 mono_error_cleanup (error
);
804 HANDLE_FUNCTION_RETURN_OBJ (result
);
807 static MonoReflectionPropertyHandle
808 property_object_construct (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
, gpointer user_data
, MonoError
*error
)
812 MonoReflectionPropertyHandle res
= MONO_HANDLE_CAST (MonoReflectionProperty
, mono_object_new_handle (domain
, mono_class_get_mono_property_class (), error
));
813 goto_if_nok (error
, fail
);
814 MONO_HANDLE_SETVAL (res
, klass
, MonoClass
*, klass
);
815 MONO_HANDLE_SETVAL (res
, property
, MonoProperty
*, property
);
818 return MONO_HANDLE_CAST (MonoReflectionProperty
, NULL_HANDLE
);
822 * mono_property_get_object_handle:
823 * \param domain an app domain
824 * \param klass a type
825 * \param property a property
826 * \param error set on error
828 * \returns A \c System.Reflection.MonoProperty object representing the property \p property
829 * in class \p klass. On error returns NULL and sets \p error.
831 MonoReflectionPropertyHandle
832 mono_property_get_object_handle (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
834 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionProperty
, property
, klass
, property_object_construct
, NULL
);
838 * mono_property_get_object:
839 * \param domain an app domain
840 * \param klass a type
841 * \param property a property
842 * \param error set on error
843 * \returns a \c System.Reflection.MonoProperty object representing the property \p property
844 * in class \p klass. On error returns NULL and sets \p error.
846 MonoReflectionProperty
*
847 mono_property_get_object_checked (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
849 HANDLE_FUNCTION_ENTER ();
850 MonoReflectionPropertyHandle res
= mono_property_get_object_handle (domain
, klass
, property
, error
);
851 HANDLE_FUNCTION_RETURN_OBJ (res
);
855 * mono_event_get_object:
856 * \param domain an app domain
857 * \param klass a type
858 * \param event a event
859 * \returns A \c System.Reflection.MonoEvent object representing the event \p event
863 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
865 HANDLE_FUNCTION_ENTER ();
867 MonoReflectionEventHandle result
= mono_event_get_object_handle (domain
, klass
, event
, error
);
868 mono_error_cleanup (error
);
869 HANDLE_FUNCTION_RETURN_OBJ (result
);
872 static MonoReflectionEventHandle
873 event_object_construct (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
, gpointer user_data
, MonoError
*error
)
877 MonoReflectionMonoEventHandle mono_event
= MONO_HANDLE_CAST (MonoReflectionMonoEvent
, mono_object_new_handle (domain
, mono_class_get_mono_event_class (), error
));
879 return MONO_HANDLE_CAST (MonoReflectionEvent
, NULL_HANDLE
);
880 MONO_HANDLE_SETVAL (mono_event
, klass
, MonoClass
* , klass
);
881 MONO_HANDLE_SETVAL (mono_event
, event
, MonoEvent
* , event
);
882 return MONO_HANDLE_CAST (MonoReflectionEvent
, mono_event
);
886 * mono_event_get_object_handle:
887 * \param domain an app domain
888 * \param klass a type
889 * \param event a event
890 * \param error set on error
891 * \returns a \c System.Reflection.MonoEvent object representing the event \p event
892 * in class \p klass. On failure sets \p error and returns NULL
894 MonoReflectionEventHandle
895 mono_event_get_object_handle (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
898 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionEvent
, event
, klass
, event_object_construct
, NULL
);
903 * mono_get_reflection_missing_object:
904 * \param domain Domain where the object lives
906 * \returns the \c System.Reflection.Missing.Value singleton object
907 * (of type \c System.Reflection.Missing).
909 * Used as the value for \c ParameterInfo.DefaultValue when Optional
912 static MonoObjectHandle
913 mono_get_reflection_missing_object (MonoDomain
*domain
)
916 static MonoClassField
*missing_value_field
= NULL
;
918 if (!missing_value_field
) {
919 MonoClass
*missing_klass
;
920 missing_klass
= mono_class_get_missing_class ();
921 mono_class_init_internal (missing_klass
);
922 missing_value_field
= mono_class_get_field_from_name_full (missing_klass
, "Value", NULL
);
923 g_assert (missing_value_field
);
925 /* FIXME change mono_field_get_value_object_checked to return a handle */
926 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, mono_field_get_value_object_checked (domain
, missing_value_field
, NULL
, error
));
927 mono_error_assert_ok (error
);
931 static MonoObjectHandle
932 get_dbnull_object (MonoDomain
*domain
, MonoError
*error
)
934 static MonoClassField
*dbnull_value_field
= NULL
;
938 if (!dbnull_value_field
) {
939 MonoClass
*dbnull_klass
;
940 dbnull_klass
= mono_class_get_dbnull_class ();
941 dbnull_value_field
= mono_class_get_field_from_name_full (dbnull_klass
, "Value", NULL
);
942 g_assert (dbnull_value_field
);
944 /* FIXME change mono_field_get_value_object_checked to return a handle */
945 MonoObjectHandle obj
= MONO_HANDLE_NEW (MonoObject
, mono_field_get_value_object_checked (domain
, dbnull_value_field
, NULL
, error
));
949 static MonoObjectHandle
950 get_dbnull (MonoDomain
*domain
, MonoObjectHandle dbnull
, MonoError
*error
)
953 if (MONO_HANDLE_IS_NULL (dbnull
))
954 MONO_HANDLE_ASSIGN (dbnull
, get_dbnull_object (domain
, error
));
958 static MonoObjectHandle
959 get_reflection_missing (MonoDomain
*domain
, MonoObjectHandleOut reflection_missing
)
961 if (MONO_HANDLE_IS_NULL (reflection_missing
))
962 MONO_HANDLE_ASSIGN (reflection_missing
, mono_get_reflection_missing_object (domain
));
963 return reflection_missing
;
967 add_parameter_object_to_array (MonoDomain
*domain
, MonoMethod
*method
, MonoObjectHandle member
, int idx
, const char *name
, MonoType
*sig_param
, guint32 blob_type_enum
, const char *blob
, MonoMarshalSpec
*mspec
, MonoObjectHandle missing
, MonoObjectHandle dbnull
, MonoArrayHandle dest
, MonoError
*error
)
969 HANDLE_FUNCTION_ENTER ();
971 MonoReflectionParameterHandle param
= MONO_HANDLE_CAST (MonoReflectionParameter
, mono_object_new_handle (domain
, mono_class_get_mono_parameter_info_class (), error
));
972 goto_if_nok (error
, leave
);
974 static MonoMethod
*ctor
;
976 MonoMethod
*m
= mono_class_get_method_from_name_checked (mono_class_get_mono_parameter_info_class (), ".ctor", 7, 0, error
);
978 mono_memory_barrier ();
984 MonoReflectionTypeHandle rt
;
985 rt
= mono_type_get_object_handle (domain
, sig_param
, error
);
986 goto_if_nok (error
, leave
);
988 MonoStringHandle name_str
;
989 name_str
= mono_string_new_handle (domain
, name
, error
);
990 goto_if_nok (error
, leave
);
992 MonoObjectHandle def_value
;
994 if (!(sig_param
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
995 if (sig_param
->attrs
& PARAM_ATTRIBUTE_OPTIONAL
)
996 def_value
= get_reflection_missing (domain
, missing
);
998 def_value
= get_dbnull (domain
, dbnull
, error
);
999 goto_if_nok (error
, leave
);
1003 blob_type
.type
= (MonoTypeEnum
)blob_type_enum
;
1004 blob_type
.data
.klass
= NULL
;
1005 if (blob_type_enum
== MONO_TYPE_CLASS
)
1006 blob_type
.data
.klass
= mono_defaults
.object_class
;
1007 else if ((sig_param
->type
== MONO_TYPE_VALUETYPE
) && m_class_is_enumtype (sig_param
->data
.klass
)) {
1008 /* For enums, types [i] contains the base type */
1010 blob_type
.type
= MONO_TYPE_VALUETYPE
;
1011 blob_type
.data
.klass
= mono_class_from_mono_type_internal (sig_param
);
1013 blob_type
.data
.klass
= mono_class_from_mono_type_internal (&blob_type
);
1015 def_value
= MONO_HANDLE_NEW (MonoObject
, mono_get_object_from_blob (domain
, &blob_type
, blob
, error
)); /* FIXME make mono_get_object_from_blob return a handle */
1016 goto_if_nok (error
, leave
);
1018 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
1019 if (blob_type_enum
!= MONO_TYPE_CLASS
&& MONO_HANDLE_IS_NULL(def_value
)) {
1020 if (sig_param
->attrs
& PARAM_ATTRIBUTE_OPTIONAL
)
1021 def_value
= get_reflection_missing (domain
, missing
);
1023 def_value
= get_dbnull (domain
, dbnull
, error
);
1024 goto_if_nok (error
, leave
);
1028 MonoReflectionMarshalAsAttributeHandle mobj
;
1029 mobj
= MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute
, NULL
);
1031 mobj
= mono_reflection_marshal_as_attribute_from_marshal_spec (domain
, method
->klass
, mspec
, error
);
1032 goto_if_nok (error
, leave
);
1035 /* internal RuntimeParameterInfo (string name, Type type, int position, int attrs, object defaultValue, MemberInfo member, MarshalAsAttribute marshalAs) */
1036 args
[0] = MONO_HANDLE_RAW (name_str
);
1037 args
[1] = MONO_HANDLE_RAW (rt
);
1040 attrs
= sig_param
->attrs
;
1042 args
[4] = MONO_HANDLE_RAW (def_value
);
1043 args
[5] = MONO_HANDLE_RAW (member
);
1044 args
[6] = MONO_HANDLE_RAW (mobj
);
1046 mono_runtime_invoke_handle_void (ctor
, MONO_HANDLE_CAST (MonoObject
, param
), args
, error
);
1047 goto_if_nok (error
, leave
);
1049 MONO_HANDLE_ARRAY_SETREF (dest
, idx
, param
);
1052 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
1055 static MonoArrayHandle
1056 param_objects_construct (MonoDomain
*domain
, MonoClass
*refclass
, MonoMethodSignature
**addr_of_sig
, gpointer user_data
, MonoError
*error
)
1058 MonoMethod
*method
= (MonoMethod
*)user_data
;
1059 MonoMethodSignature
*sig
= *addr_of_sig
; /* see note in mono_param_get_objects_internal */
1061 MonoArrayHandle res
= MONO_HANDLE_NEW (MonoArray
, NULL
);
1062 char **names
= NULL
, **blobs
= NULL
;
1063 guint32
*types
= NULL
;
1064 MonoMarshalSpec
**mspecs
= NULL
;
1069 MonoReflectionMethodHandle member
= mono_method_get_object_handle (domain
, method
, refclass
, error
);
1070 goto_if_nok (error
, leave
);
1071 names
= g_new (char *, sig
->param_count
);
1072 mono_method_get_param_names (method
, (const char **) names
);
1074 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
1075 mono_method_get_marshal_info (method
, mspecs
);
1077 res
= mono_array_new_handle (domain
, mono_class_get_mono_parameter_info_class (), sig
->param_count
, error
);
1078 if (MONO_HANDLE_IS_NULL (res
))
1081 gboolean any_default_value
;
1082 any_default_value
= FALSE
;
1083 for (i
= 0; i
< sig
->param_count
; ++i
) {
1084 if ((sig
->params
[i
]->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) != 0) {
1085 any_default_value
= TRUE
;
1089 if (any_default_value
) {
1090 blobs
= g_new0 (char *, sig
->param_count
);
1091 types
= g_new0 (guint32
, sig
->param_count
);
1092 get_default_param_value_blobs (method
, blobs
, types
);
1095 /* Handles missing and dbnull are assigned in add_parameter_object_to_array when needed */
1096 MonoObjectHandle missing
;
1097 missing
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1098 MonoObjectHandle dbnull
;
1099 dbnull
= MONO_HANDLE_NEW (MonoObject
, NULL
);
1100 for (i
= 0; i
< sig
->param_count
; ++i
) {
1101 if (!add_parameter_object_to_array (domain
, method
, MONO_HANDLE_CAST(MonoObject
, member
), i
, names
[i
], sig
->params
[i
], types
? types
[i
] : 0, blobs
? blobs
[i
] : NULL
, mspecs
[i
+ 1], missing
, dbnull
, res
, error
))
1110 if (sig
&& mspecs
) {
1111 for (i
= sig
->param_count
; i
>= 0; i
--) {
1113 mono_metadata_free_marshal_spec (mspecs
[i
]);
1119 return NULL_HANDLE_ARRAY
;
1125 * mono_param_get_objects:
1126 * @domain: an app domain
1129 * Return an System.Reflection.ParameterInfo array object representing the parameters
1130 * in the method @method.
1133 mono_param_get_objects_internal (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
, MonoError
*error
)
1137 /* side-effect: sets method->signature non-NULL on success */
1138 MonoMethodSignature
*sig
= mono_method_signature_checked (method
, error
);
1139 goto_if_nok (error
, fail
);
1141 if (!sig
->param_count
) {
1142 MonoArrayHandle res
= mono_array_new_handle (domain
, mono_class_get_mono_parameter_info_class (), 0, error
);
1143 goto_if_nok (error
, fail
);
1148 /* Note: the cache is based on the address of the signature into the method
1149 * since we already cache MethodInfos with the method as keys.
1151 return CHECK_OR_CONSTRUCT_HANDLE (MonoArray
, &method
->signature
, refclass
, param_objects_construct
, method
);
1153 return MONO_HANDLE_NEW (MonoArray
, NULL
);
1157 * mono_param_get_objects:
1160 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
1162 HANDLE_FUNCTION_ENTER ();
1164 MonoArrayHandle result
= mono_param_get_objects_internal (domain
, method
, NULL
, error
);
1165 mono_error_assert_ok (error
);
1166 HANDLE_FUNCTION_RETURN_OBJ (result
);
1170 add_local_var_info_to_array (MonoDomain
*domain
, MonoMethodHeader
*header
, int idx
, MonoArrayHandle dest
, MonoError
*error
)
1172 HANDLE_FUNCTION_ENTER ();
1174 MonoReflectionLocalVariableInfoHandle info
= MONO_HANDLE_CAST (MonoReflectionLocalVariableInfo
, mono_object_new_handle (domain
, mono_class_get_local_variable_info_class (), error
));
1175 goto_if_nok (error
, leave
);
1177 MonoReflectionTypeHandle rt
;
1178 rt
= mono_type_get_object_handle (domain
, header
->locals
[idx
], error
);
1179 goto_if_nok (error
, leave
);
1181 MONO_HANDLE_SET (info
, local_type
, rt
);
1183 MONO_HANDLE_SETVAL (info
, is_pinned
, MonoBoolean
, header
->locals
[idx
]->pinned
);
1184 MONO_HANDLE_SETVAL (info
, local_index
, guint16
, idx
);
1186 MONO_HANDLE_ARRAY_SETREF (dest
, idx
, info
);
1189 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
1193 add_exception_handling_clause_to_array (MonoDomain
*domain
, MonoMethodHeader
*header
, int idx
, MonoArrayHandle dest
, MonoError
*error
)
1195 HANDLE_FUNCTION_ENTER ();
1197 MonoReflectionExceptionHandlingClauseHandle info
= MONO_HANDLE_CAST (MonoReflectionExceptionHandlingClause
, mono_object_new_handle (domain
, mono_class_get_exception_handling_clause_class (), error
));
1198 goto_if_nok (error
, leave
);
1199 MonoExceptionClause
*clause
;
1200 clause
= &header
->clauses
[idx
];
1202 MONO_HANDLE_SETVAL (info
, flags
, gint32
, clause
->flags
);
1203 MONO_HANDLE_SETVAL (info
, try_offset
, gint32
, clause
->try_offset
);
1204 MONO_HANDLE_SETVAL (info
, try_length
, gint32
, clause
->try_len
);
1205 MONO_HANDLE_SETVAL (info
, handler_offset
, gint32
, clause
->handler_offset
);
1206 MONO_HANDLE_SETVAL (info
, handler_length
, gint32
, clause
->handler_len
);
1207 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
1208 MONO_HANDLE_SETVAL (info
, filter_offset
, gint32
, clause
->data
.filter_offset
);
1209 else if (clause
->data
.catch_class
) {
1210 MonoReflectionTypeHandle rt
= mono_type_get_object_handle (mono_domain_get (), m_class_get_byval_arg (clause
->data
.catch_class
), error
);
1211 goto_if_nok (error
, leave
);
1213 MONO_HANDLE_SET (info
, catch_type
, rt
);
1216 MONO_HANDLE_ARRAY_SETREF (dest
, idx
, info
);
1218 HANDLE_FUNCTION_RETURN_VAL (is_ok (error
));
1222 * mono_method_body_get_object:
1223 * \param domain an app domain
1224 * \param method a method
1225 * \return A \c System.Reflection.MethodBody/RuntimeMethodBody object representing the method \p method.
1227 MonoReflectionMethodBody
*
1228 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
1230 HANDLE_FUNCTION_ENTER ();
1232 MonoReflectionMethodBodyHandle result
= mono_method_body_get_object_handle (domain
, method
, error
);
1233 mono_error_cleanup (error
);
1234 HANDLE_FUNCTION_RETURN_OBJ (result
);
1237 /* WARNING: This method can return NULL on success */
1238 static MonoReflectionMethodBodyHandle
1239 method_body_object_construct (MonoDomain
*domain
, MonoClass
*unused_class
, MonoMethod
*method
, gpointer user_data
, MonoError
*error
)
1241 MonoMethodHeader
*header
= NULL
;
1243 guint32 method_rva
, local_var_sig_token
;
1245 unsigned char format
, flags
;
1247 gpointer params
[6];
1248 MonoBoolean init_locals_param
;
1249 gint32 sig_token_param
;
1250 gint32 max_stack_param
;
1254 /* for compatibility with .net */
1255 if (method_is_dynamic (method
)) {
1256 mono_error_set_generic_error (error
, "System", "InvalidOperationException", "");
1260 image
= m_class_get_image (method
->klass
);
1261 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
1262 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
1263 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
1264 (image
->raw_data
&& image
->raw_data
[1] != 'Z') ||
1265 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
1266 return MONO_HANDLE_CAST (MonoReflectionMethodBody
, NULL_HANDLE
);
1268 header
= mono_method_get_header_checked (method
, error
);
1269 goto_if_nok (error
, fail
);
1271 if (!image_is_dynamic (image
)) {
1272 /* Obtain local vars signature token */
1273 method_rva
= mono_metadata_decode_row_col (&image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
1274 ptr
= mono_image_rva_map (image
, method_rva
);
1275 flags
= *(const unsigned char *) ptr
;
1276 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
1278 case METHOD_HEADER_TINY_FORMAT
:
1279 local_var_sig_token
= 0;
1281 case METHOD_HEADER_FAT_FORMAT
:
1285 local_var_sig_token
= read32 (ptr
);
1288 g_assert_not_reached ();
1291 local_var_sig_token
= 0; //FIXME
1293 static MonoMethod
*ctor
;
1295 MonoMethod
*tmp
= mono_class_get_method_from_name_checked (mono_class_get_method_body_class (), ".ctor", 6, 0, error
);
1296 mono_error_assert_ok (error
);
1299 mono_memory_barrier ();
1303 MonoReflectionMethodBodyHandle ret
;
1304 ret
= MONO_HANDLE_CAST (MonoReflectionMethodBody
, mono_object_new_handle (domain
, mono_class_get_method_body_class (), error
));
1305 goto_if_nok (error
, fail
);
1307 MonoArrayHandle il_arr
;
1308 il_arr
= mono_array_new_handle (domain
, mono_defaults
.byte_class
, header
->code_size
, error
);
1309 goto_if_nok (error
, fail
);
1310 uint32_t il_gchandle
;
1312 il_data
= MONO_ARRAY_HANDLE_PIN (il_arr
, guint8
, 0, &il_gchandle
);
1313 memcpy (il_data
, header
->code
, header
->code_size
);
1314 mono_gchandle_free_internal (il_gchandle
);
1317 MonoArrayHandle locals_arr
;
1318 locals_arr
= mono_array_new_handle (domain
, mono_class_get_local_variable_info_class (), header
->num_locals
, error
);
1319 goto_if_nok (error
, fail
);
1320 for (i
= 0; i
< header
->num_locals
; ++i
) {
1321 if (!add_local_var_info_to_array (domain
, header
, i
, locals_arr
, error
))
1326 MonoArrayHandle exn_clauses
;
1327 exn_clauses
= mono_array_new_handle (domain
, mono_class_get_exception_handling_clause_class (), header
->num_clauses
, error
);
1328 goto_if_nok (error
, fail
);
1329 for (i
= 0; i
< header
->num_clauses
; ++i
) {
1330 if (!add_exception_handling_clause_to_array (domain
, header
, i
, exn_clauses
, error
))
1335 MethodBody (ExceptionHandlingClause[] clauses, LocalVariableInfo[] locals,
1336 byte[] il, bool init_locals, int sig_token, int max_stack)
1338 init_locals_param
= header
->init_locals
;
1339 sig_token_param
= local_var_sig_token
;
1340 max_stack_param
= header
->max_stack
;
1341 mono_metadata_free_mh (header
);
1344 params
[0] = MONO_HANDLE_RAW (exn_clauses
);
1345 params
[1] = MONO_HANDLE_RAW (locals_arr
);
1346 params
[2] = MONO_HANDLE_RAW (il_arr
);
1347 params
[3] = &init_locals_param
;
1348 params
[4] = &sig_token_param
;
1349 params
[5] = &max_stack_param
;
1350 mono_runtime_invoke_handle_void (ctor
, MONO_HANDLE_CAST (MonoObject
, ret
), params
, error
);
1351 mono_error_assert_ok (error
);
1356 mono_metadata_free_mh (header
);
1357 return MONO_HANDLE_CAST (MonoReflectionMethodBody
, NULL_HANDLE
);
1361 * mono_method_body_get_object_handle:
1362 * \param domain an app domain
1363 * \param method a method
1364 * \param error set on error
1365 * \returns a \c System.Reflection.MethodBody object representing the
1366 * method \p method. On failure, returns NULL and sets \p error.
1368 MonoReflectionMethodBodyHandle
1369 mono_method_body_get_object_handle (MonoDomain
*domain
, MonoMethod
*method
, MonoError
*error
)
1372 return CHECK_OR_CONSTRUCT_HANDLE (MonoReflectionMethodBody
, method
, NULL
, method_body_object_construct
, NULL
);
1377 * mono_get_dbnull_object:
1378 * \param domain Domain where the object lives
1379 * Used as the value for \c ParameterInfo.DefaultValue
1380 * \returns the \c System.DBNull.Value singleton object
1383 mono_get_dbnull_object (MonoDomain
*domain
)
1385 HANDLE_FUNCTION_ENTER ();
1387 MonoObjectHandle obj
= get_dbnull_object (domain
, error
);
1388 mono_error_assert_ok (error
);
1389 HANDLE_FUNCTION_RETURN_OBJ (obj
);
1393 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
1395 guint32 param_index
, i
, lastp
, crow
= 0;
1396 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
1399 MonoClass
*klass
= method
->klass
;
1400 MonoImage
*image
= m_class_get_image (klass
);
1401 MonoMethodSignature
*methodsig
= mono_method_signature_internal (method
);
1403 MonoTableInfo
*constt
;
1404 MonoTableInfo
*methodt
;
1405 MonoTableInfo
*paramt
;
1407 if (!methodsig
->param_count
)
1410 mono_class_init_internal (klass
);
1412 if (image_is_dynamic (image
)) {
1413 MonoReflectionMethodAux
*aux
;
1414 if (method
->is_inflated
)
1415 method
= ((MonoMethodInflated
*)method
)->declaring
;
1416 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)m_class_get_image (method
->klass
))->method_aux_hash
, method
);
1417 if (aux
&& aux
->param_defaults
) {
1418 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
1419 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
1424 methodt
= &image
->tables
[MONO_TABLE_METHOD
];
1425 paramt
= &image
->tables
[MONO_TABLE_PARAM
];
1426 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
1428 idx
= mono_method_get_index (method
) - 1;
1429 g_assert (idx
!= -1);
1431 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
1432 if (idx
+ 1 < methodt
->rows
)
1433 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
1435 lastp
= paramt
->rows
+ 1;
1437 for (i
= param_index
; i
< lastp
; ++i
) {
1440 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
1441 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
1443 if (!(param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
))
1446 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
1451 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
1452 blobs
[paramseq
- 1] = (char *)mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
1453 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
1460 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
, MonoError
*error
)
1465 MonoType
*basetype
= type
;
1472 klass
= mono_class_from_mono_type_internal (type
);
1473 if (m_class_is_valuetype (klass
)) {
1474 object
= mono_object_new_checked (domain
, klass
, error
);
1475 return_val_if_nok (error
, NULL
);
1476 retval
= mono_object_get_data (object
);
1477 if (m_class_is_enumtype (klass
))
1478 basetype
= mono_class_enum_basetype_internal (klass
);
1483 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
, error
))
1490 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
1493 gboolean quoted
= FALSE
;
1495 memset (assembly
, 0, sizeof (MonoAssemblyName
));
1496 assembly
->culture
= "";
1497 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
1504 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@' || g_ascii_isspace (*p
)))
1515 /* Remove trailing whitespace */
1517 while (*s
&& g_ascii_isspace (*s
))
1520 while (g_ascii_isspace (*p
))
1523 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
1525 assembly
->major
= strtoul (p
, &s
, 10);
1526 if (s
== p
|| *s
!= '.')
1529 assembly
->minor
= strtoul (p
, &s
, 10);
1530 if (s
== p
|| *s
!= '.')
1533 assembly
->build
= strtoul (p
, &s
, 10);
1534 if (s
== p
|| *s
!= '.')
1537 assembly
->revision
= strtoul (p
, &s
, 10);
1541 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
1543 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
1544 assembly
->culture
= "";
1547 assembly
->culture
= p
;
1548 while (*p
&& *p
!= ',') {
1552 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
1554 if (strncmp (p
, "null", 4) == 0) {
1559 while (*p
&& *p
!= ',') {
1562 len
= (p
- start
+ 1);
1563 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
1564 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
1565 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
1568 while (*p
&& *p
!= ',')
1572 while (g_ascii_isspace (*p
) || *p
== ',') {
1586 * mono_reflection_parse_type:
1589 * Parse a type name as accepted by the GetType () method and output the info
1590 * extracted in the info structure.
1591 * the name param will be mangled, so, make a copy before passing it to this function.
1592 * The fields in info will be valid until the memory pointed to by name is valid.
1594 * See also mono_type_get_name () below.
1596 * Returns: 0 on parse error.
1599 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
1600 MonoTypeNameParse
*info
)
1602 char *start
, *p
, *w
, *last_point
, *startn
;
1603 int in_modifiers
= 0;
1604 int isbyref
= 0, rank
= 0, isptr
= 0;
1606 start
= p
= w
= name
;
1608 memset (info
, 0, sizeof (MonoTypeNameParse
));
1610 /* last_point separates the namespace from the name */
1613 while (*p
== ' ') p
++, start
++, w
++, name
++;
1618 *p
= 0; /* NULL terminate the name */
1620 info
->nested
= g_list_append (info
->nested
, startn
);
1621 /* we have parsed the nesting namespace + name */
1625 info
->name_space
= start
;
1627 info
->name
= last_point
+ 1;
1629 info
->name_space
= (char *)"";
1657 info
->name_space
= start
;
1660 info
->name
= last_point
+ 1;
1662 info
->name_space
= (char *)"";
1669 if (isbyref
) /* only one level allowed by the spec */
1673 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
1677 if (isbyref
) /* pointer to ref not okay */
1679 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
1684 if (isbyref
) /* array of ref and generic ref are not okay */
1686 //Decide if it's an array of a generic argument list
1691 if (*p
== ',' || *p
== '*' || *p
== ']') { //array
1692 gboolean bounded
= FALSE
;
1700 else if (*p
== '*') /* '*' means unknown lower bound */
1708 /* bounded only allowed when rank == 1 */
1709 if (bounded
&& rank
> 1)
1711 /* n.b. bounded needs both modifiers: -2 == bounded, 1 == rank 1 array */
1713 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
1714 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
1716 if (rank
|| isptr
) /* generic args after array spec or ptr*/ //XXX test
1719 info
->type_arguments
= g_ptr_array_new ();
1721 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
1722 gboolean fqname
= FALSE
;
1724 g_ptr_array_add (info
->type_arguments
, subinfo
);
1726 while (*p
== ' ') p
++;
1732 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
1735 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
1736 if (fqname
&& (*p
!= ']')) {
1744 while (*p
&& (*p
!= ']'))
1752 if (g_ascii_isspace (*aname
)) {
1759 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
1761 } else if (fqname
&& (*p
== ']')) {
1783 if (g_ascii_isspace (*p
)) {
1790 return 0; /* missing assembly name */
1791 if (!assembly_name_to_aname (&info
->assembly
, p
))
1797 if (info
->assembly
.name
)
1800 // *w = 0; /* terminate class name */
1802 if (!info
->name
|| !*info
->name
)
1806 /* add other consistency checks */
1812 * mono_identifier_unescape_type_name_chars:
1813 * \param identifier the display name of a mono type
1815 * \returns The name in internal form, that is without escaping backslashes.
1817 * The string is modified in place!
1820 mono_identifier_unescape_type_name_chars(char* identifier
)
1825 for (w
= r
= identifier
; *r
!= 0; r
++)
1843 mono_identifier_unescape_info (MonoTypeNameParse
* info
);
1846 unescape_each_type_argument(void* data
, void* user_data
)
1848 MonoTypeNameParse
* info
= (MonoTypeNameParse
*)data
;
1849 mono_identifier_unescape_info (info
);
1853 unescape_each_nested_name (void* data
, void* user_data
)
1855 char* nested_name
= (char*) data
;
1856 mono_identifier_unescape_type_name_chars(nested_name
);
1860 * mono_identifier_unescape_info:
1862 * \param info a parsed display form of an (optionally assembly qualified) full type name.
1864 * Destructively updates the info by unescaping the identifiers that
1865 * comprise the type namespace, name, nested types (if any) and
1866 * generic type arguments (if any).
1868 * The resulting info has the names in internal form.
1872 mono_identifier_unescape_info (MonoTypeNameParse
*info
)
1876 mono_identifier_unescape_type_name_chars(info
->name_space
);
1877 mono_identifier_unescape_type_name_chars(info
->name
);
1878 // but don't escape info->assembly
1879 if (info
->type_arguments
)
1880 g_ptr_array_foreach(info
->type_arguments
, &unescape_each_type_argument
, NULL
);
1882 g_list_foreach(info
->nested
, &unescape_each_nested_name
, NULL
);
1886 * mono_reflection_parse_type:
1889 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
1892 gboolean result
= mono_reflection_parse_type_checked (name
, info
, error
);
1893 mono_error_cleanup (error
);
1894 return result
? 1 : 0;
1898 * mono_reflection_parse_type_checked:
1899 * \param name the string to parse
1900 * \param info the parsed name components
1901 * \param error set on error
1903 * Parse the given \p name and write the results to \p info, setting \p error
1904 * on error. The string \p name is modified in place and \p info points into
1905 * its memory and into allocated memory.
1907 * \returns TRUE if parsing succeeded, otherwise returns FALSE and sets \p error.
1911 mono_reflection_parse_type_checked (char *name
, MonoTypeNameParse
*info
, MonoError
*error
)
1914 int ok
= _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
1916 mono_identifier_unescape_info (info
);
1918 mono_error_set_argument_format (error
, "typeName", "failed parse: %s", name
);
1924 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
, MonoError
*error
)
1926 gboolean type_resolve
= FALSE
;
1928 MonoImage
*rootimage
= image
;
1932 if (info
->assembly
.name
) {
1933 MonoAssembly
*assembly
= mono_assembly_loaded_full (&info
->assembly
, FALSE
);
1934 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
1936 * This could happen in the AOT compiler case when the search hook is not
1939 assembly
= image
->assembly
;
1941 /* then we must load the assembly ourselve - see #60439 */
1942 assembly
= mono_assembly_load (&info
->assembly
, image
->assembly
->basedir
, NULL
);
1946 image
= assembly
->image
;
1947 } else if (!image
) {
1948 image
= mono_defaults
.corlib
;
1951 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
, error
);
1952 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
1953 /* ignore the error and try again */
1954 mono_error_cleanup (error
);
1956 image
= mono_defaults
.corlib
;
1957 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
, error
);
1964 * mono_reflection_get_type_internal:
1966 * Returns: may return NULL on success, sets error on failure.
1969 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
1971 HANDLE_FUNCTION_ENTER ();
1975 gboolean bounded
= FALSE
;
1976 MonoType
* type
= NULL
;
1980 image
= mono_defaults
.corlib
;
1983 rootimage
= mono_defaults
.corlib
;
1986 klass
= mono_class_from_name_case_checked (image
, info
->name_space
, info
->name
, error
);
1988 klass
= mono_class_from_name_checked (image
, info
->name_space
, info
->name
, error
);
1993 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
1994 gpointer iter
= NULL
;
1998 mono_class_init_internal (parent
);
2000 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
2002 char *nested_name
, *nested_nspace
;
2003 gboolean match
= TRUE
;
2005 lastp
= strrchr ((const char *)mod
->data
, '.');
2007 /* Nested classes can have namespaces */
2010 nested_name
= g_strdup (lastp
+ 1);
2011 nspace_len
= lastp
- (char*)mod
->data
;
2012 nested_nspace
= (char *)g_malloc (nspace_len
+ 1);
2013 memcpy (nested_nspace
, mod
->data
, nspace_len
);
2014 nested_nspace
[nspace_len
] = '\0';
2017 nested_name
= (char *)mod
->data
;
2018 nested_nspace
= NULL
;
2021 if (nested_nspace
) {
2022 const char *klass_name_space
= m_class_get_name_space (klass
);
2024 if (!(klass_name_space
&& mono_utf8_strcasecmp (klass_name_space
, nested_nspace
) == 0))
2027 if (!(klass_name_space
&& strcmp (klass_name_space
, nested_nspace
) == 0))
2032 const char *klass_name
= m_class_get_name (klass
);
2034 if (mono_utf8_strcasecmp (klass_name
, nested_name
) != 0)
2037 if (strcmp (klass_name
, nested_name
) != 0)
2042 g_free (nested_name
);
2043 g_free (nested_nspace
);
2055 if (info
->type_arguments
) {
2056 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
2057 MonoReflectionTypeHandle the_type
;
2061 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
2062 MonoTypeNameParse
*subinfo
= (MonoTypeNameParse
*)g_ptr_array_index (info
->type_arguments
, i
);
2064 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
, error
);
2065 if (!type_args
[i
]) {
2071 the_type
= mono_type_get_object_handle (mono_domain_get (), m_class_get_byval_arg (klass
), error
);
2072 if (!is_ok (error
) || MONO_HANDLE_IS_NULL (the_type
))
2075 instance
= mono_reflection_bind_generic_parameters (
2076 the_type
, info
->type_arguments
->len
, type_args
, error
);
2082 klass
= mono_class_from_mono_type_internal (instance
);
2085 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
2086 modval
= GPOINTER_TO_UINT (mod
->data
);
2087 if (!modval
) { /* byref: must be last modifier */
2088 type
= m_class_get_this_arg (klass
);
2090 } else if (modval
== -1) {
2091 klass
= mono_class_create_ptr (m_class_get_byval_arg (klass
));
2092 } else if (modval
== -2) {
2094 } else { /* array rank */
2095 klass
= mono_class_create_bounded_array (klass
, modval
, bounded
);
2099 type
= m_class_get_byval_arg (klass
);
2102 HANDLE_FUNCTION_RETURN_VAL (type
);
2106 * mono_reflection_get_type:
2107 * \param image a metadata context
2108 * \param info type description structure
2109 * \param ignorecase flag for case-insensitive string compares
2110 * \param type_resolve whenever type resolve was already tried
2112 * Build a MonoType from the type description in \p info.
2116 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
2118 MonoType
*result
= mono_reflection_get_type_with_rootimage (image
, image
, info
, ignorecase
, type_resolve
, error
);
2119 mono_error_cleanup (error
);
2124 * mono_reflection_get_type_checked:
2125 * \param rootimage the image of the currently active managed caller
2126 * \param image a metadata context
2127 * \param info type description structure
2128 * \param ignorecase flag for case-insensitive string compares
2129 * \param type_resolve whenever type resolve was already tried
2130 * \param error set on error.
2131 * Build a \c MonoType from the type description in \p info. On failure returns NULL and sets \p error.
2134 mono_reflection_get_type_checked (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
) {
2136 return mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, type_resolve
, error
);
2141 module_builder_array_get_type (MonoArrayHandle module_builders
, int i
, MonoImage
*rootimage
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
2143 HANDLE_FUNCTION_ENTER ();
2145 MonoType
*type
= NULL
;
2146 MonoReflectionModuleBuilderHandle mb
= MONO_HANDLE_NEW (MonoReflectionModuleBuilder
, NULL
);
2147 MONO_HANDLE_ARRAY_GETREF (mb
, module_builders
, i
);
2148 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (mb
, dynamic_image
);
2149 type
= mono_reflection_get_type_internal (rootimage
, &dynamic_image
->image
, info
, ignorecase
, error
);
2150 HANDLE_FUNCTION_RETURN_VAL (type
);
2154 module_array_get_type (MonoArrayHandle modules
, int i
, MonoImage
*rootimage
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
2156 HANDLE_FUNCTION_ENTER ();
2158 MonoType
*type
= NULL
;
2159 MonoReflectionModuleHandle mod
= MONO_HANDLE_NEW (MonoReflectionModule
, NULL
);
2160 MONO_HANDLE_ARRAY_GETREF (mod
, modules
, i
);
2161 MonoImage
*image
= MONO_HANDLE_GETVAL (mod
, image
);
2162 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
, error
);
2163 HANDLE_FUNCTION_RETURN_VAL (type
);
2167 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
, MonoError
*error
)
2169 HANDLE_FUNCTION_ENTER ();
2170 MonoType
*type
= NULL
;
2174 g_assert (assembly_is_dynamic (assembly
));
2175 MonoReflectionAssemblyBuilderHandle abuilder
= MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder
, mono_assembly_get_object_handle (((MonoDynamicAssembly
*)assembly
)->domain
, assembly
, error
));
2176 goto_if_nok (error
, leave
);
2178 /* Enumerate all modules */
2180 MonoArrayHandle modules
;
2181 modules
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2182 MONO_HANDLE_GET (modules
, abuilder
, modules
);
2183 if (!MONO_HANDLE_IS_NULL (modules
)) {
2184 int n
= mono_array_handle_length (modules
);
2185 for (i
= 0; i
< n
; ++i
) {
2186 type
= module_builder_array_get_type (modules
, i
, rootimage
, info
, ignorecase
, error
);
2189 goto_if_nok (error
, leave
);
2193 MonoArrayHandle loaded_modules
;
2194 loaded_modules
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2195 MONO_HANDLE_GET (loaded_modules
, abuilder
, loaded_modules
);
2196 if (!type
&& !MONO_HANDLE_IS_NULL(loaded_modules
)) {
2197 int n
= mono_array_handle_length (loaded_modules
);
2198 for (i
= 0; i
< n
; ++i
) {
2199 type
= module_array_get_type (loaded_modules
, i
, rootimage
, info
, ignorecase
, error
);
2202 goto_if_nok (error
, leave
);
2207 HANDLE_FUNCTION_RETURN_VAL (type
);
2211 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
, MonoError
*error
)
2213 HANDLE_FUNCTION_ENTER ();
2216 MonoReflectionAssemblyHandle reflection_assembly
;
2217 GString
*fullName
= NULL
;
2222 if (image
&& image_is_dynamic (image
))
2223 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
, error
);
2225 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
, error
);
2226 goto_if_nok (error
, return_null
);
2230 if (!mono_domain_has_type_resolve (mono_domain_get ()))
2236 *type_resolve
= TRUE
;
2239 /* Reconstruct the type name */
2240 fullName
= g_string_new ("");
2241 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
2242 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
2244 g_string_printf (fullName
, "%s", info
->name
);
2245 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
2246 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
2248 MonoStringHandle name_handle
;
2249 name_handle
= mono_string_new_handle (mono_domain_get (), fullName
->str
, error
);
2250 goto_if_nok (error
, return_null
);
2251 reflection_assembly
= mono_domain_try_type_resolve_name ( mono_domain_get (), name_handle
, error
);
2252 goto_if_nok (error
, return_null
);
2254 if (MONO_HANDLE_BOOL (reflection_assembly
)) {
2255 MonoAssembly
*assembly
= MONO_HANDLE_GETVAL (reflection_assembly
, assembly
);
2256 if (assembly_is_dynamic (assembly
))
2257 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
,
2258 info
, ignorecase
, error
);
2260 type
= mono_reflection_get_type_internal (rootimage
, assembly
->image
,
2261 info
, ignorecase
, error
);
2263 goto_if_nok (error
, return_null
);
2272 g_string_free (fullName
, TRUE
);
2273 HANDLE_FUNCTION_RETURN_VAL (type
);
2277 * mono_reflection_free_type_info:
2280 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
2282 g_list_free (info
->modifiers
);
2283 g_list_free (info
->nested
);
2285 if (info
->type_arguments
) {
2288 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
2289 MonoTypeNameParse
*subinfo
= (MonoTypeNameParse
*)g_ptr_array_index (info
->type_arguments
, i
);
2291 mono_reflection_free_type_info (subinfo
);
2292 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
2296 g_ptr_array_free (info
->type_arguments
, TRUE
);
2301 * mono_reflection_type_from_name:
2302 * \param name type name.
2303 * \param image a metadata context (can be NULL).
2305 * Retrieves a \c MonoType from its \p name. If the name is not fully qualified,
2306 * it defaults to get the type from \p image or, if \p image is NULL or loading
2307 * from it fails, uses corlib.
2311 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
2316 MonoType
* const result
= mono_reflection_type_from_name_checked (name
, image
, error
);
2318 mono_error_cleanup (error
);
2323 * mono_reflection_type_from_name_checked:
2324 * \param name type name.
2325 * \param image a metadata context (can be NULL).
2326 * \param error set on errror.
2327 * Retrieves a MonoType from its \p name. If the name is not fully qualified,
2328 * it defaults to get the type from \p image or, if \p image is NULL or loading
2329 * from it fails, uses corlib. On failure returns NULL and sets \p error.
2332 mono_reflection_type_from_name_checked (char *name
, MonoImage
*image
, MonoError
*error
)
2334 MonoType
*type
= NULL
;
2335 MonoTypeNameParse info
;
2339 /* Make a copy since parse_type modifies its argument */
2340 tmp
= g_strdup (name
);
2342 /*g_print ("requested type %s\n", str);*/
2343 ERROR_DECL (parse_error
);
2344 if (!mono_reflection_parse_type_checked (tmp
, &info
, parse_error
)) {
2345 mono_error_cleanup (parse_error
);
2348 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
, error
);
2351 mono_reflection_free_type_info (&info
);
2356 * mono_reflection_get_token:
2357 * \returns the metadata token of \p obj which should be an object
2358 * representing a metadata element.
2361 mono_reflection_get_token (MonoObject
*obj_raw
)
2363 HANDLE_FUNCTION_ENTER ();
2364 MONO_HANDLE_DCL (MonoObject
, obj
);
2366 guint32 result
= mono_reflection_get_token_checked (obj
, error
);
2367 mono_error_assert_ok (error
);
2368 HANDLE_FUNCTION_RETURN_VAL (result
);
2372 * mono_reflection_get_param_info_member_and_pos:
2374 * Return the MemberImpl and PositionImpl fields of P.
2377 mono_reflection_get_param_info_member_and_pos (MonoReflectionParameterHandle p
, MonoObjectHandle member_impl
, int *out_position
)
2379 MonoClass
*klass
= mono_class_get_mono_parameter_info_class ();
2381 /* These two fields are part of ParameterInfo instead of RuntimeParameterInfo, and they cannot be moved */
2383 static MonoClassField
*member_field
;
2384 if (!member_field
) {
2385 MonoClassField
*f
= mono_class_get_field_from_name_full (klass
, "MemberImpl", NULL
);
2390 mono_field_get_value_internal (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject
, p
)), member_field
, &member
);
2391 MONO_HANDLE_ASSIGN_RAW (member_impl
, member
);
2393 static MonoClassField
*pos_field
;
2395 MonoClassField
*f
= mono_class_get_field_from_name_full (klass
, "PositionImpl", NULL
);
2399 mono_field_get_value_internal (MONO_HANDLE_RAW (MONO_HANDLE_CAST (MonoObject
, p
)), pos_field
, out_position
);
2403 * mono_reflection_get_token_checked:
2404 * \param obj the object
2405 * \param error set on error
2406 * \returns the metadata token of \p obj which should be an object
2407 * representing a metadata element. On failure sets \p error.
2410 mono_reflection_get_token_checked (MonoObjectHandle obj
, MonoError
*error
)
2416 MonoClass
*klass
= mono_handle_class (obj
);
2418 const char *klass_name
= m_class_get_name (klass
);
2419 if (strcmp (klass_name
, "MethodBuilder") == 0) {
2420 MonoReflectionMethodBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionMethodBuilder
, obj
);
2422 token
= MONO_HANDLE_GETVAL (mb
, table_idx
) | MONO_TOKEN_METHOD_DEF
;
2423 } else if (strcmp (klass_name
, "ConstructorBuilder") == 0) {
2424 MonoReflectionCtorBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionCtorBuilder
, obj
);
2426 token
= MONO_HANDLE_GETVAL (mb
, table_idx
) | MONO_TOKEN_METHOD_DEF
;
2427 } else if (strcmp (klass_name
, "FieldBuilder") == 0) {
2428 g_assert_not_reached ();
2429 } else if (strcmp (klass_name
, "TypeBuilder") == 0) {
2430 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, obj
);
2431 token
= MONO_HANDLE_GETVAL (tb
, table_idx
) | MONO_TOKEN_TYPE_DEF
;
2432 } else if (strcmp (klass_name
, "RuntimeType") == 0) {
2433 MonoType
*type
= mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType
, obj
), error
);
2434 return_val_if_nok (error
, 0);
2435 MonoClass
*mc
= mono_class_from_mono_type_internal (type
);
2436 if (!mono_class_init_internal (mc
)) {
2437 mono_error_set_for_class_failure (error
, mc
);
2441 token
= m_class_get_type_token (mc
);
2442 } else if (strcmp (klass_name
, "RuntimeMethodInfo") == 0 ||
2443 strcmp (klass_name
, "RuntimeConstructorInfo") == 0) {
2444 MonoReflectionMethodHandle m
= MONO_HANDLE_CAST (MonoReflectionMethod
, obj
);
2445 MonoMethod
*method
= MONO_HANDLE_GETVAL (m
, method
);
2446 if (method
->is_inflated
) {
2447 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) method
;
2448 return inflated
->declaring
->token
;
2450 token
= method
->token
;
2452 } else if (strcmp (klass_name
, "RuntimeFieldInfo") == 0) {
2453 MonoReflectionFieldHandle f
= MONO_HANDLE_CAST (MonoReflectionField
, obj
);
2455 token
= mono_class_get_field_token (MONO_HANDLE_GETVAL (f
, field
));
2456 } else if (strcmp (klass_name
, "RuntimePropertyInfo") == 0) {
2457 MonoReflectionPropertyHandle p
= MONO_HANDLE_CAST (MonoReflectionProperty
, obj
);
2459 token
= mono_class_get_property_token (MONO_HANDLE_GETVAL (p
, property
));
2460 } else if (strcmp (klass_name
, "RuntimeEventInfo") == 0) {
2461 MonoReflectionMonoEventHandle p
= MONO_HANDLE_CAST (MonoReflectionMonoEvent
, obj
);
2463 token
= mono_class_get_event_token (MONO_HANDLE_GETVAL (p
, event
));
2464 } else if (strcmp (klass_name
, "ParameterInfo") == 0 || strcmp (klass_name
, "RuntimeParameterInfo") == 0) {
2465 MonoReflectionParameterHandle p
= MONO_HANDLE_CAST (MonoReflectionParameter
, obj
);
2467 MonoObjectHandle member_impl
= MONO_HANDLE_NEW (MonoObject
, NULL
);
2469 mono_reflection_get_param_info_member_and_pos (p
, member_impl
, &position
);
2471 MonoClass
*member_class
= mono_handle_class (member_impl
);
2472 g_assert (mono_class_is_reflection_method_or_constructor (member_class
));
2473 MonoMethod
*method
= MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionMethod
, member_impl
), method
);
2475 token
= mono_method_get_param_token (method
, position
);
2476 } else if (strcmp (klass_name
, "RuntimeModule") == 0 || strcmp (klass_name
, "ModuleBuilder") == 0) {
2477 MonoReflectionModuleHandle m
= MONO_HANDLE_CAST (MonoReflectionModule
, obj
);
2479 token
= MONO_HANDLE_GETVAL (m
, token
);
2480 } else if (strcmp (klass_name
, "RuntimeAssembly") == 0) {
2481 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
2483 mono_error_set_not_implemented (error
, "MetadataToken is not supported for type '%s.%s'",
2484 m_class_get_name_space (klass
), klass_name
);
2493 mono_reflection_is_usertype (MonoReflectionTypeHandle ref
)
2495 MonoClass
*klass
= mono_handle_class (ref
);
2496 return m_class_get_image (klass
) != mono_defaults
.corlib
|| strcmp ("TypeDelegator", m_class_get_name (klass
)) == 0;
2500 * mono_reflection_bind_generic_parameters:
2501 * \param type a managed type object (which should be some kind of generic (instance? definition?))
2502 * \param type_args the number of type arguments to bind
2503 * \param types array of type arguments
2504 * \param error set on error
2505 * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
2506 * \returns the \c MonoType* for the resulting type instantiation. On failure returns NULL and sets \p error.
2509 mono_reflection_bind_generic_parameters (MonoReflectionTypeHandle reftype
, int type_argc
, MonoType
**types
, MonoError
*error
)
2511 gboolean is_dynamic
= FALSE
;
2516 mono_loader_lock ();
2518 MonoClass
*klass
= mono_handle_class (reftype
);
2519 if (mono_is_sre_type_builder (klass
)) {
2521 } else if (mono_is_sre_generic_instance (klass
)) {
2522 /* Does this ever make sense? what does instantiating a generic instance even mean? */
2523 g_assert_not_reached ();
2524 MonoReflectionGenericClassHandle rgi
= MONO_HANDLE_CAST (MonoReflectionGenericClass
, reftype
);
2525 MonoReflectionTypeHandle gtd
= MONO_HANDLE_NEW_GET (MonoReflectionType
, rgi
, generic_type
);
2527 if (mono_is_sre_type_builder (mono_handle_class (gtd
)))
2531 MonoType
*t
= mono_reflection_type_handle_mono_type (reftype
, error
);
2532 if (!is_ok (error
)) {
2533 mono_loader_unlock ();
2537 klass
= mono_class_from_mono_type_internal (t
);
2538 if (!mono_class_is_gtd (klass
)) {
2539 mono_loader_unlock ();
2540 mono_error_set_type_load_class (error
, klass
, "Cannot bind generic parameters of a non-generic type");
2544 guint gtd_type_argc
= mono_class_get_generic_container (klass
)->type_argc
;
2545 if (gtd_type_argc
!= type_argc
) {
2546 mono_loader_unlock ();
2547 mono_error_set_argument_format (error
, "types", "The generic type definition needs %d type arguments, but was instantiated with %d ", gtd_type_argc
, type_argc
);
2552 if (m_class_was_typebuilder (klass
))
2555 mono_loader_unlock ();
2557 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
2559 return m_class_get_byval_arg (geninst
);
2563 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
2565 MonoGenericClass
*gclass
;
2566 MonoGenericInst
*inst
;
2568 g_assert (mono_class_is_gtd (klass
));
2570 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
2571 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
2573 return mono_class_create_generic_inst (gclass
);
2576 static MonoGenericInst
*
2577 generic_inst_from_type_array_handle (MonoArrayHandle types
, MonoError
*error
)
2579 HANDLE_FUNCTION_ENTER ();
2581 MonoGenericInst
*ginst
= NULL
;
2582 int count
= mono_array_handle_length (types
);
2583 MonoType
**type_argv
= g_new0 (MonoType
*, count
);
2584 MonoReflectionTypeHandle garg
= MONO_HANDLE_NEW (MonoReflectionType
, NULL
);
2585 for (int i
= 0; i
< count
; i
++) {
2586 MONO_HANDLE_ARRAY_GETREF (garg
, types
, i
);
2587 type_argv
[i
] = mono_reflection_type_handle_mono_type (garg
, error
);
2588 goto_if_nok (error
, leave
);
2591 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2594 HANDLE_FUNCTION_RETURN_VAL (ginst
);
2598 reflection_bind_generic_method_parameters (MonoMethod
*method
, MonoArrayHandle types
, MonoError
*error
)
2601 MonoMethod
*inflated
;
2602 MonoGenericContext tmp_context
;
2606 klass
= method
->klass
;
2608 if (method
->is_inflated
)
2609 method
= ((MonoMethodInflated
*) method
)->declaring
;
2611 int count
= mono_method_signature_internal (method
)->generic_param_count
;
2612 if (count
!= mono_array_handle_length (types
)) {
2613 mono_error_set_argument (error
, "typeArguments", "Incorrect number of generic arguments");
2617 MonoGenericInst
*ginst
= generic_inst_from_type_array_handle (types
, error
);
2618 return_val_if_nok (error
, NULL
);
2620 tmp_context
.class_inst
= mono_class_is_ginst (klass
) ? mono_class_get_generic_class (klass
)->context
.class_inst
: NULL
;
2621 tmp_context
.method_inst
= ginst
;
2623 inflated
= mono_class_inflate_generic_method_checked (method
, &tmp_context
, error
);
2624 mono_error_assert_ok (error
);
2626 if (!mono_verifier_is_method_valid_generic_instantiation (inflated
)) {
2627 mono_error_set_argument (error
, "typeArguments", "Invalid generic arguments");
2634 MonoReflectionMethodHandle
2635 ves_icall_RuntimeMethodInfo_MakeGenericMethod_impl (MonoReflectionMethodHandle rmethod
, MonoArrayHandle types
, MonoError
*error
)
2638 g_assert (0 != strcmp (m_class_get_name (mono_handle_class (rmethod
)), "MethodBuilder"));
2640 MonoMethod
*method
= MONO_HANDLE_GETVAL (rmethod
, method
);
2641 MonoMethod
*imethod
= reflection_bind_generic_method_parameters (method
, types
, error
);
2642 return_val_if_nok (error
, MONO_HANDLE_CAST (MonoReflectionMethod
, NULL_HANDLE
));
2644 /*FIXME but I think this is no longer necessary*/
2645 if (image_is_dynamic (m_class_get_image (method
->klass
))) {
2646 MonoDynamicImage
*image
= (MonoDynamicImage
*)m_class_get_image (method
->klass
);
2648 * This table maps metadata structures representing inflated methods/fields
2649 * to the reflection objects representing their generic definitions.
2651 mono_image_lock ((MonoImage
*)image
);
2652 mono_g_hash_table_insert_internal (image
->generic_def_objects
, imethod
, MONO_HANDLE_RAW (rmethod
));
2653 mono_image_unlock ((MonoImage
*)image
);
2656 return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (rmethod
), imethod
, NULL
, error
);
2660 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
2661 const static guint32 declsec_flags_map
[] = {
2662 0x00000000, /* empty */
2663 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
2664 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
2665 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
2666 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
2667 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
2668 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
2669 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
2670 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
2671 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
2672 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
2673 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
2674 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
2675 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
2676 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
2677 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
2678 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
2679 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
2680 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
2684 * Returns flags that includes all available security action associated to the handle.
2685 * @token: metadata token (either for a class or a method)
2686 * @image: image where resides the metadata.
2689 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
2691 int index
= mono_metadata_declsec_from_index (image
, token
);
2692 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
2697 /* HasSecurity can be present for other, not specially encoded, attributes,
2698 e.g. SuppressUnmanagedCodeSecurityAttribute */
2702 for (i
= index
; i
< t
->rows
; i
++) {
2703 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
2705 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
2706 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
2709 action
= cols
[MONO_DECL_SECURITY_ACTION
];
2710 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
2711 result
|= declsec_flags_map
[action
];
2713 g_assert_not_reached ();
2720 * mono_declsec_flags_from_method:
2721 * \param method The method for which we want the declarative security flags.
2722 * Get the security actions (in the form of flags) associated with the specified method.
2723 * To keep \c MonoMethod size down we do not cache the declarative security flags
2724 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
2725 * \returns the declarative security flags for the method (only).
2728 mono_declsec_flags_from_method (MonoMethod
*method
)
2730 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
2731 /* FIXME: No cache (for the moment) */
2732 guint32 idx
= mono_method_get_index (method
);
2733 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
2734 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
2735 return mono_declsec_get_flags (m_class_get_image (method
->klass
), idx
);
2741 * mono_declsec_flags_from_class:
2742 * \param klass The class for which we want the declarative security flags.
2743 * Get the security actions (in the form of flags) associated with the specified class.
2744 * We cache the flags inside the \c MonoClass structure as this will get
2745 * called very often (at least for each method).
2746 * \returns the declarative security flags for the class.
2749 mono_declsec_flags_from_class (MonoClass
*klass
)
2751 if (mono_class_get_flags (klass
) & TYPE_ATTRIBUTE_HAS_SECURITY
) {
2752 guint32 flags
= mono_class_get_declsec_flags (klass
);
2757 idx
= mono_metadata_token_index (m_class_get_type_token (klass
));
2758 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
2759 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
2760 flags
= mono_declsec_get_flags (m_class_get_image (klass
), idx
);
2761 /* we cache the flags on classes */
2762 mono_class_set_declsec_flags (klass
, flags
);
2770 * mono_declsec_flags_from_assembly:
2771 * \param assembly The assembly for which we want the declarative security flags.
2772 * Get the security actions (in the form of flags) associated with the specified assembly.
2773 * \returns the declarative security flags for the assembly.
2776 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
2778 guint32 idx
= 1; /* there is only one assembly */
2779 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
2780 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
2781 return mono_declsec_get_flags (assembly
->image
, idx
);
2786 * Fill actions for the specific index (which may either be an encoded class token or
2787 * an encoded method token) from the metadata image.
2788 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
2791 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
2792 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
2794 MonoBoolean result
= FALSE
;
2796 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
2797 int index
= mono_metadata_declsec_from_index (image
, token
);
2800 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
2801 for (i
= index
; i
< t
->rows
; i
++) {
2802 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
2804 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
2807 /* if present only replace (class) permissions with method permissions */
2808 /* if empty accept either class or method permissions */
2809 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
2810 if (!actions
->demand
.blob
) {
2811 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
2812 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
2813 actions
->demand
.blob
= (char*) (blob
+ 2);
2814 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
2817 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
2818 if (!actions
->noncasdemand
.blob
) {
2819 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
2820 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
2821 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
2822 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
2825 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
2826 if (!actions
->demandchoice
.blob
) {
2827 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
2828 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
2829 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
2830 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
2840 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
2841 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
2843 guint32 idx
= mono_metadata_token_index (m_class_get_type_token (klass
));
2844 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
2845 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
2846 return fill_actions_from_index (m_class_get_image (klass
), idx
, demands
, id_std
, id_noncas
, id_choice
);
2850 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
2851 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
2853 guint32 idx
= mono_method_get_index (method
);
2854 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
2855 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
2856 return fill_actions_from_index (m_class_get_image (method
->klass
), idx
, demands
, id_std
, id_noncas
, id_choice
);
2860 * mono_declsec_get_demands:
2861 * Collect all actions (that requires to generate code in mini) assigned for
2862 * the specified method.
2863 * Don't use the content of actions if the function return FALSE.
2866 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
2868 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
2869 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
2870 MonoBoolean result
= FALSE
;
2873 /* quick exit if no declarative security is present in the metadata */
2874 if (!m_class_get_image (method
->klass
)->tables
[MONO_TABLE_DECLSECURITY
].rows
)
2877 /* we want the original as the wrapper is "free" of the security informations */
2878 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
2879 method
= mono_marshal_method_from_wrapper (method
);
2884 /* First we look for method-level attributes */
2885 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
2886 mono_class_init_internal (method
->klass
);
2887 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
2889 result
= mono_declsec_get_method_demands_params (method
, demands
,
2890 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
2893 /* Here we use (or create) the class declarative cache to look for demands */
2894 flags
= mono_declsec_flags_from_class (method
->klass
);
2897 mono_class_init_internal (method
->klass
);
2898 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
2900 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
2901 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
2904 /* The boolean return value is used as a shortcut in case nothing needs to
2905 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
2911 * mono_declsec_get_linkdemands:
2912 * Collect all Link actions: \c LinkDemand, \c NonCasLinkDemand and \c LinkDemandChoice (2.0).
2913 * Don't use the content of actions if the function return FALSE.
2916 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
2918 MonoBoolean result
= FALSE
;
2921 /* quick exit if no declarative security is present in the metadata */
2922 if (!m_class_get_image (method
->klass
)->tables
[MONO_TABLE_DECLSECURITY
].rows
)
2925 /* we want the original as the wrapper is "free" of the security informations */
2926 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
2927 method
= mono_marshal_method_from_wrapper (method
);
2932 /* results are independant - zeroize both */
2933 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
2934 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
2936 /* First we look for method-level attributes */
2937 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
2938 mono_class_init_internal (method
->klass
);
2940 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
2941 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
2944 /* Here we use (or create) the class declarative cache to look for demands */
2945 flags
= mono_declsec_flags_from_class (method
->klass
);
2946 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
2947 mono_class_init_internal (method
->klass
);
2949 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
2950 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
2957 * mono_declsec_get_inheritdemands_class:
2958 * \param klass The inherited class - this is the class that provides the security check (attributes)
2960 * Collect all Inherit actions - \c InheritanceDemand, \c NonCasInheritanceDemand and \c InheritanceDemandChoice (2.0).
2961 * Don't use the content of actions if the function return FALSE.
2962 * \returns TRUE if inheritance demands (any kind) are present, FALSE otherwise.
2965 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
2967 MonoBoolean result
= FALSE
;
2970 /* quick exit if no declarative security is present in the metadata */
2971 if (!m_class_get_image (klass
)->tables
[MONO_TABLE_DECLSECURITY
].rows
)
2974 /* Here we use (or create) the class declarative cache to look for demands */
2975 flags
= mono_declsec_flags_from_class (klass
);
2976 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
2977 mono_class_init_internal (klass
);
2978 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
2980 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
2981 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
2988 * mono_declsec_get_inheritdemands_method:
2989 * Collect all Inherit actions: \c InheritanceDemand, \c NonCasInheritanceDemand and \c InheritanceDemandChoice (2.0).
2990 * Don't use the content of actions if the function return FALSE.
2993 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
2995 /* quick exit if no declarative security is present in the metadata */
2996 if (!m_class_get_image (method
->klass
)->tables
[MONO_TABLE_DECLSECURITY
].rows
)
2999 /* we want the original as the wrapper is "free" of the security informations */
3000 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
3001 method
= mono_marshal_method_from_wrapper (method
);
3006 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
3007 mono_class_init_internal (method
->klass
);
3008 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
3010 return mono_declsec_get_method_demands_params (method
, demands
,
3011 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
3018 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
3020 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
3024 int index
= mono_metadata_declsec_from_index (image
, token
);
3028 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
3029 for (i
= index
; i
< t
->rows
; i
++) {
3030 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
3032 /* shortcut - index are ordered */
3033 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
3036 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
3037 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
3038 entry
->blob
= (char*) (metadata
+ 2);
3039 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
3048 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
3050 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
3051 guint32 idx
= mono_method_get_index (method
);
3052 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
3053 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
3054 return get_declsec_action (m_class_get_image (method
->klass
), idx
, action
, entry
);
3060 * mono_declsec_get_class_action:
3063 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
3066 guint32 flags
= mono_declsec_flags_from_class (klass
);
3067 if (declsec_flags_map
[action
] & flags
) {
3068 guint32 idx
= mono_metadata_token_index (m_class_get_type_token (klass
));
3069 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
3070 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
3071 return get_declsec_action (m_class_get_image (klass
), idx
, action
, entry
);
3077 * mono_declsec_get_assembly_action:
3080 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
3082 guint32 idx
= 1; /* there is only one assembly */
3083 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
3084 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
3086 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
3090 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
, MonoError
*error
)
3092 MonoObject
*res
, *exc
;
3094 static MonoMethod
*method
= NULL
;
3098 if (method
== NULL
) {
3099 method
= mono_class_get_method_from_name_checked (mono_class_get_type_builder_class (), "IsAssignableTo", 1, 0, error
);
3100 mono_error_assert_ok (error
);
3105 * The result of mono_type_get_object_checked () might be a System.MonoType but we
3106 * need a TypeBuilder so use mono_class_get_ref_info (klass).
3108 g_assert (mono_class_has_ref_info (klass
));
3109 g_assert (!strcmp (m_class_get_name (mono_object_class (&mono_class_get_ref_info_raw (klass
)->type
.object
)), "TypeBuilder")); /* FIXME use handles */
3111 params
[0] = mono_type_get_object_checked (mono_domain_get (), m_class_get_byval_arg (oklass
), error
);
3112 return_val_if_nok (error
, FALSE
);
3114 ERROR_DECL (inner_error
);
3115 res
= mono_runtime_try_invoke (method
, &mono_class_get_ref_info_raw (klass
)->type
.object
, params
, &exc
, inner_error
); /* FIXME use handles */
3117 if (exc
|| !is_ok (inner_error
)) {
3118 mono_error_cleanup (inner_error
);
3121 return *(MonoBoolean
*)mono_object_unbox_internal (res
);
3125 * mono_reflection_type_get_type:
3126 * \param reftype the \c System.Type object
3127 * \returns the \c MonoType* associated with the C# \c System.Type object \p reftype.
3130 mono_reflection_type_get_type (MonoReflectionType
*reftype
)
3133 MONO_ENTER_GC_UNSAFE
;
3137 result
= mono_reflection_type_get_handle (reftype
, error
);
3138 mono_error_assert_ok (error
);
3139 MONO_EXIT_GC_UNSAFE
;
3144 * mono_reflection_assembly_get_assembly:
3145 * \param refassembly the \c System.Reflection.Assembly object
3146 * \returns the \c MonoAssembly* associated with the C# \c System.Reflection.Assembly object \p refassembly.
3149 mono_reflection_assembly_get_assembly (MonoReflectionAssembly
*refassembly
)
3151 g_assert (refassembly
);
3153 return refassembly
->assembly
;
3157 * mono_class_from_mono_type_handle:
3158 * \param reftype the \c System.Type handle
3159 * \returns the \c MonoClass* corresponding to the given type.
3162 mono_class_from_mono_type_handle (MonoReflectionTypeHandle reftype
)
3164 return mono_class_from_mono_type_internal (MONO_HANDLE_RAW (reftype
)->type
);
3167 // This is called by icalls, it will return NULL and set pending exception (in wrapper) on failure.
3168 MonoReflectionTypeHandle
3169 mono_type_from_handle_impl (MonoType
*handle
, MonoError
*error
)
3171 mono_class_init_internal (mono_class_from_mono_type_internal (handle
));
3172 return mono_type_get_object_handle (mono_domain_get (), handle
, error
);