[coop] Transition various public APIs into an external/internal form to avoid unneces...
[mono-project.git] / mono / metadata / reflection.c
blobf51462b32d452d53a373f0f326a51cd8e70d1580
1 /**
2 * \file
3 * System.Type icalls and related reflection queries.
4 *
5 * Author:
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.
15 #include <config.h>
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>
33 #include <stdio.h>
34 #include <glib.h>
35 #include <errno.h>
36 #include <time.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "image.h"
40 #include "cil-coff.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");
68 #ifdef ENABLE_NETCORE
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");
72 #else
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");
76 #endif
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;
83 void
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));
109 gboolean
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)
124 return NULL;
125 return (MonoReflectionTypeBuilder*)mono_gchandle_get_target_internal (ref_info_handle);
128 void
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);
141 void
142 mono_class_free_ref_info (MonoClass *klass)
144 MONO_REQ_GC_NEUTRAL_MODE;
145 guint32 handle = mono_class_get_ref_info_handle (klass);
147 if (handle) {
148 mono_gchandle_free_internal (handle);
149 mono_class_set_ref_info_handle (klass, 0);
154 * mono_custom_attrs_free:
156 void
157 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
159 MONO_REQ_GC_NEUTRAL_MODE;
161 if (ainfo && !ainfo->cached)
162 g_free (ainfo);
165 gboolean
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);
174 guint
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);
180 return seed;
183 static void
184 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
186 mono_domain_lock (domain);
187 if (domain->refobject_hash) {
188 ReflectedEntry pe;
189 gpointer orig_pe, orig_value;
191 pe.item = o;
192 pe.refclass = klass;
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);
202 static void
203 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
205 free_reflected_entry ((ReflectedEntry*)key);
208 void
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;
230 ERROR_DECL (error);
231 result = mono_assembly_get_object_handle (domain, assembly, error);
232 mono_error_cleanup (error); /* FIXME new API that doesn't swallow the error */
233 MONO_EXIT_GC_UNSAFE;
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)
240 error_init (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);
244 return res;
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)
257 error_init (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 ();
268 ERROR_DECL (error);
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)
277 char* basename;
279 error_init (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);
297 g_free (basename);
299 guint32 token;
300 token = 0;
301 if (image->assembly->image == image) {
302 token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
303 } else {
304 int i;
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);
315 return res;
316 fail:
317 return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
320 MonoReflectionModuleHandle
321 mono_module_get_object_handle (MonoDomain *domain, MonoImage *image, MonoError *error)
323 error_init (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 ();
334 ERROR_DECL (error);
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];
345 const char *name;
346 guint32 i, name_idx;
347 const char *val;
349 error_init (error);
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));
383 return res;
384 fail:
385 return MONO_HANDLE_CAST (MonoReflectionModule, NULL_HANDLE);
388 static MonoType*
389 mono_type_normalize (MonoType *type)
391 int i;
392 MonoGenericClass *gclass;
393 MonoGenericInst *ginst;
394 MonoClass *gtd;
395 MonoGenericContainer *gcontainer;
396 MonoType **argv = NULL;
397 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
399 if (type->type != MONO_TYPE_GENERICINST)
400 return type;
402 gclass = type->data.generic_class;
403 ginst = gclass->context.class_inst;
404 if (!ginst->is_open)
405 return type;
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);
416 argv [i] = norm;
417 if (norm != t)
418 requires_rebind = TRUE;
421 if (is_denorm_gtd)
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);
429 return type;
433 * mono_type_get_object:
434 * \param domain an app domain
435 * \param type a type
436 * \returns A \c System.MonoType object representing the type \p type.
438 MonoReflectionType*
439 mono_type_get_object (MonoDomain *domain, MonoType *type)
441 MonoReflectionType *ret;
442 MONO_ENTER_GC_UNSAFE;
443 ERROR_DECL (error);
444 ret = mono_type_get_object_checked (domain, type, error);
445 mono_error_cleanup (error);
446 MONO_EXIT_GC_UNSAFE;
447 return ret;
450 MonoReflectionType*
451 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
453 MonoType *norm_type;
454 MonoReflectionType *res;
455 MonoClass *klass;
457 error_init (error);
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
472 * types.
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;
483 #else
484 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
485 return (MonoReflectionType*)domain->typeof_void;
486 #endif
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 ();
509 return res;
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 ();
525 return NULL;
527 mono_g_hash_table_insert_internal (domain->type_hash, type, res);
528 mono_domain_unlock (domain);
529 mono_loader_unlock ();
530 return res;
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
546 * not been done. */
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);
550 g_free (full_name);
551 mono_domain_unlock (domain);
552 mono_loader_unlock ();
553 return NULL;
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 ();
566 return NULL;
569 res->type = type;
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 ();
577 return res;
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;
604 ERROR_DECL (error);
605 ret = mono_method_get_object_handle (domain, method, refclass, error);
606 mono_error_cleanup (error);
607 MONO_EXIT_GC_UNSAFE;
608 HANDLE_FUNCTION_RETURN_OBJ (ret);
611 static MonoReflectionMethodHandle
612 method_object_construct (MonoDomain *domain, MonoClass *refclass, MonoMethod *method, gpointer user_data, MonoError *error)
614 error_init (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.
620 MonoClass *klass;
622 error_init (error);
624 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
625 klass = mono_class_get_mono_cmethod_class ();
627 else {
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);
640 return ret;
642 fail:
643 return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
647 * mono_method_get_object_handle:
648 * @domain: an app domain
649 * @method: a method
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)
659 error_init (error);
660 if (!refclass)
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
668 * @method: a method
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.
688 void
689 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
691 MonoClass *klass;
692 g_assert (method_is_dynamic (method));
694 klass = method->klass;
695 while (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;
702 while (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
714 * in class \p klass.
716 MonoReflectionField*
717 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
719 HANDLE_FUNCTION_ENTER ();
720 ERROR_DECL (error);
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)
729 error_init (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);
740 if (field->type) {
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));
747 return res;
748 fail:
749 return MONO_HANDLE_CAST (MonoReflectionField, NULL_HANDLE);
753 * mono_field_get_object_handle:
754 * @domain: an app domain
755 * @klass: a type
756 * @field: a field
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)
765 error_init (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
773 * @klass: a type
774 * @field: a field
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.
780 MonoReflectionField*
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
791 * @klass: a type
792 * @property: a property
794 * Return an System.Reflection.MonoProperty object representing the property @property
795 * in class @klass.
797 MonoReflectionProperty*
798 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
800 HANDLE_FUNCTION_ENTER ();
801 ERROR_DECL (error);
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)
810 error_init (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);
816 return res;
817 fail:
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
860 * in class \p klass.
862 MonoReflectionEvent*
863 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
865 HANDLE_FUNCTION_ENTER ();
866 ERROR_DECL (error);
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)
876 error_init (error);
877 MonoReflectionMonoEventHandle mono_event = MONO_HANDLE_CAST (MonoReflectionMonoEvent, mono_object_new_handle (domain, mono_class_get_mono_event_class (), error));
878 if (!is_ok (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)
897 error_init (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
910 * is present
912 static MonoObjectHandle
913 mono_get_reflection_missing_object (MonoDomain *domain)
915 ERROR_DECL (error);
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);
928 return obj;
931 static MonoObjectHandle
932 get_dbnull_object (MonoDomain *domain, MonoError *error)
934 static MonoClassField *dbnull_value_field = NULL;
936 error_init (error);
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));
946 return obj;
949 static MonoObjectHandle
950 get_dbnull (MonoDomain *domain, MonoObjectHandle dbnull, MonoError *error)
952 error_init (error);
953 if (MONO_HANDLE_IS_NULL (dbnull))
954 MONO_HANDLE_ASSIGN (dbnull, get_dbnull_object (domain, error));
955 return dbnull;
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;
966 static gboolean
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 ();
970 error_init (error);
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;
975 if (!ctor) {
976 MonoMethod *m = mono_class_get_method_from_name_checked (mono_class_get_mono_parameter_info_class (), ".ctor", 7, 0, error);
977 g_assert (m);
978 mono_memory_barrier ();
979 ctor = m;
982 void *args [16];
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);
997 else
998 def_value = get_dbnull (domain, dbnull, error);
999 goto_if_nok (error, leave);
1000 } else {
1001 MonoType blob_type;
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);
1012 } else
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);
1022 else
1023 def_value = get_dbnull (domain, dbnull, error);
1024 goto_if_nok (error, leave);
1028 MonoReflectionMarshalAsAttributeHandle mobj;
1029 mobj = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
1030 if (mspec) {
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);
1038 args [2] = &idx;
1039 int attrs;
1040 attrs = sig_param->attrs;
1041 args [3] = &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);
1051 leave:
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;
1065 int i;
1067 error_init (error);
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))
1079 goto leave;
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;
1086 break;
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))
1102 goto leave;
1105 leave:
1106 g_free (names);
1107 g_free (blobs);
1108 g_free (types);
1110 if (sig && mspecs) {
1111 for (i = sig->param_count; i >= 0; i--) {
1112 if (mspecs [i])
1113 mono_metadata_free_marshal_spec (mspecs [i]);
1116 g_free (mspecs);
1118 if (!is_ok (error))
1119 return NULL_HANDLE_ARRAY;
1121 return res;
1125 * mono_param_get_objects:
1126 * @domain: an app domain
1127 * @method: a method
1129 * Return an System.Reflection.ParameterInfo array object representing the parameters
1130 * in the method @method.
1132 MonoArrayHandle
1133 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
1135 error_init (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);
1145 return res;
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);
1152 fail:
1153 return MONO_HANDLE_NEW (MonoArray, NULL);
1157 * mono_param_get_objects:
1159 MonoArray*
1160 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
1162 HANDLE_FUNCTION_ENTER ();
1163 ERROR_DECL (error);
1164 MonoArrayHandle result = mono_param_get_objects_internal (domain, method, NULL, error);
1165 mono_error_assert_ok (error);
1166 HANDLE_FUNCTION_RETURN_OBJ (result);
1169 static gboolean
1170 add_local_var_info_to_array (MonoDomain *domain, MonoMethodHeader *header, int idx, MonoArrayHandle dest, MonoError *error)
1172 HANDLE_FUNCTION_ENTER ();
1173 error_init (error);
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);
1188 leave:
1189 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
1192 static gboolean
1193 add_exception_handling_clause_to_array (MonoDomain *domain, MonoMethodHeader *header, int idx, MonoArrayHandle dest, MonoError *error)
1195 HANDLE_FUNCTION_ENTER ();
1196 error_init (error);
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);
1217 leave:
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 ();
1231 ERROR_DECL (error);
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;
1242 MonoImage *image;
1243 guint32 method_rva, local_var_sig_token;
1244 char *ptr;
1245 unsigned char format, flags;
1246 int i;
1247 gpointer params [6];
1248 MonoBoolean init_locals_param;
1249 gint32 sig_token_param;
1250 gint32 max_stack_param;
1252 error_init (error);
1254 /* for compatibility with .net */
1255 if (method_is_dynamic (method)) {
1256 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
1257 goto fail;
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;
1277 switch (format){
1278 case METHOD_HEADER_TINY_FORMAT:
1279 local_var_sig_token = 0;
1280 break;
1281 case METHOD_HEADER_FAT_FORMAT:
1282 ptr += 2;
1283 ptr += 2;
1284 ptr += 4;
1285 local_var_sig_token = read32 (ptr);
1286 break;
1287 default:
1288 g_assert_not_reached ();
1290 } else
1291 local_var_sig_token = 0; //FIXME
1293 static MonoMethod *ctor;
1294 if (!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);
1297 g_assert (tmp);
1299 mono_memory_barrier ();
1300 ctor = tmp;
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;
1311 guint8* il_data;
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);
1316 /* Locals */
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))
1322 goto fail;
1325 /* Exceptions */
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))
1331 goto fail;
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);
1342 header = NULL;
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);
1353 return ret;
1354 fail:
1355 if (header)
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)
1371 error_init (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
1382 MonoObject *
1383 mono_get_dbnull_object (MonoDomain *domain)
1385 HANDLE_FUNCTION_ENTER ();
1386 ERROR_DECL (error);
1387 MonoObjectHandle obj = get_dbnull_object (domain, error);
1388 mono_error_assert_ok (error);
1389 HANDLE_FUNCTION_RETURN_OBJ (obj);
1392 static void
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];
1397 gint32 idx;
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)
1408 return;
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));
1421 return;
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);
1434 else
1435 lastp = paramt->rows + 1;
1437 for (i = param_index; i < lastp; ++i) {
1438 guint32 paramseq;
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))
1444 continue;
1446 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
1447 if (!crow) {
1448 continue;
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];
1456 return;
1459 MonoObject *
1460 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
1462 void *retval;
1463 MonoClass *klass;
1464 MonoObject *object;
1465 MonoType *basetype = type;
1467 error_init (error);
1469 if (!blob)
1470 return NULL;
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);
1479 } else {
1480 retval = &object;
1483 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval, error))
1484 return object;
1485 else
1486 return NULL;
1489 static int
1490 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
1491 int found_sep;
1492 char *s;
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);
1499 if (*p == '"') {
1500 quoted = TRUE;
1501 p++;
1503 assembly->name = p;
1504 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
1505 p++;
1506 if (quoted) {
1507 if (*p != '"')
1508 return 1;
1509 *p = 0;
1510 p++;
1512 if (*p != ',')
1513 return 1;
1514 *p = 0;
1515 /* Remove trailing whitespace */
1516 s = p - 1;
1517 while (*s && g_ascii_isspace (*s))
1518 *s-- = 0;
1519 p ++;
1520 while (g_ascii_isspace (*p))
1521 p++;
1522 while (*p) {
1523 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
1524 p += 8;
1525 assembly->major = strtoul (p, &s, 10);
1526 if (s == p || *s != '.')
1527 return 1;
1528 p = ++s;
1529 assembly->minor = strtoul (p, &s, 10);
1530 if (s == p || *s != '.')
1531 return 1;
1532 p = ++s;
1533 assembly->build = strtoul (p, &s, 10);
1534 if (s == p || *s != '.')
1535 return 1;
1536 p = ++s;
1537 assembly->revision = strtoul (p, &s, 10);
1538 if (s == p)
1539 return 1;
1540 p = s;
1541 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
1542 p += 8;
1543 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
1544 assembly->culture = "";
1545 p += 7;
1546 } else {
1547 assembly->culture = p;
1548 while (*p && *p != ',') {
1549 p++;
1552 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
1553 p += 15;
1554 if (strncmp (p, "null", 4) == 0) {
1555 p += 4;
1556 } else {
1557 int len;
1558 gchar *start = p;
1559 while (*p && *p != ',') {
1560 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);
1567 } else {
1568 while (*p && *p != ',')
1569 p++;
1571 found_sep = 0;
1572 while (g_ascii_isspace (*p) || *p == ',') {
1573 *p++ = 0;
1574 found_sep = 1;
1575 continue;
1577 /* failed */
1578 if (!found_sep)
1579 return 1;
1582 return 0;
1586 * mono_reflection_parse_type:
1587 * @name: type name
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.
1598 static int
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 */
1611 last_point = NULL;
1612 /* Skips spaces */
1613 while (*p == ' ') p++, start++, w++, name++;
1615 while (*p) {
1616 switch (*p) {
1617 case '+':
1618 *p = 0; /* NULL terminate the name */
1619 startn = p + 1;
1620 info->nested = g_list_append (info->nested, startn);
1621 /* we have parsed the nesting namespace + name */
1622 if (info->name)
1623 break;
1624 if (last_point) {
1625 info->name_space = start;
1626 *last_point = 0;
1627 info->name = last_point + 1;
1628 } else {
1629 info->name_space = (char *)"";
1630 info->name = start;
1632 break;
1633 case '.':
1634 last_point = p;
1635 break;
1636 case '\\':
1637 ++p;
1638 break;
1639 case '&':
1640 case '*':
1641 case '[':
1642 case ',':
1643 case ']':
1644 in_modifiers = 1;
1645 break;
1646 default:
1647 break;
1649 if (in_modifiers)
1650 break;
1651 // *w++ = *p++;
1652 p++;
1655 if (!info->name) {
1656 if (last_point) {
1657 info->name_space = start;
1659 *last_point = 0;
1660 info->name = last_point + 1;
1661 } else {
1662 info->name_space = (char *)"";
1663 info->name = start;
1666 while (*p) {
1667 switch (*p) {
1668 case '&':
1669 if (isbyref) /* only one level allowed by the spec */
1670 return 0;
1671 isbyref = 1;
1672 isptr = 0;
1673 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
1674 *p++ = 0;
1675 break;
1676 case '*':
1677 if (isbyref) /* pointer to ref not okay */
1678 return 0;
1679 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
1680 isptr = 1;
1681 *p++ = 0;
1682 break;
1683 case '[':
1684 if (isbyref) /* array of ref and generic ref are not okay */
1685 return 0;
1686 //Decide if it's an array of a generic argument list
1687 *p++ = 0;
1689 if (!*p) //XXX test
1690 return 0;
1691 if (*p == ',' || *p == '*' || *p == ']') { //array
1692 gboolean bounded = FALSE;
1693 isptr = 0;
1694 rank = 1;
1695 while (*p) {
1696 if (*p == ']')
1697 break;
1698 if (*p == ',')
1699 rank++;
1700 else if (*p == '*') /* '*' means unknown lower bound */
1701 bounded = TRUE;
1702 else
1703 return 0;
1704 ++p;
1706 if (*p++ != ']')
1707 return 0;
1708 /* bounded only allowed when rank == 1 */
1709 if (bounded && rank > 1)
1710 return 0;
1711 /* n.b. bounded needs both modifiers: -2 == bounded, 1 == rank 1 array */
1712 if (bounded)
1713 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
1714 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
1715 } else {
1716 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
1717 return 0;
1718 isptr = 0;
1719 info->type_arguments = g_ptr_array_new ();
1720 while (*p) {
1721 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
1722 gboolean fqname = FALSE;
1724 g_ptr_array_add (info->type_arguments, subinfo);
1726 while (*p == ' ') p++;
1727 if (*p == '[') {
1728 p++;
1729 fqname = TRUE;
1732 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
1733 return 0;
1735 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
1736 if (fqname && (*p != ']')) {
1737 char *aname;
1739 if (*p != ',')
1740 return 0;
1741 *p++ = 0;
1743 aname = p;
1744 while (*p && (*p != ']'))
1745 p++;
1747 if (*p != ']')
1748 return 0;
1750 *p++ = 0;
1751 while (*aname) {
1752 if (g_ascii_isspace (*aname)) {
1753 ++aname;
1754 continue;
1756 break;
1758 if (!*aname ||
1759 !assembly_name_to_aname (&subinfo->assembly, aname))
1760 return 0;
1761 } else if (fqname && (*p == ']')) {
1762 *p++ = 0;
1764 if (*p == ']') {
1765 *p++ = 0;
1766 break;
1767 } else if (!*p) {
1768 return 0;
1770 *p++ = 0;
1773 break;
1774 case ']':
1775 if (is_recursed)
1776 goto end;
1777 return 0;
1778 case ',':
1779 if (is_recursed)
1780 goto end;
1781 *p++ = 0;
1782 while (*p) {
1783 if (g_ascii_isspace (*p)) {
1784 ++p;
1785 continue;
1787 break;
1789 if (!*p)
1790 return 0; /* missing assembly name */
1791 if (!assembly_name_to_aname (&info->assembly, p))
1792 return 0;
1793 break;
1794 default:
1795 return 0;
1797 if (info->assembly.name)
1798 break;
1800 // *w = 0; /* terminate class name */
1801 end:
1802 if (!info->name || !*info->name)
1803 return 0;
1804 if (endptr)
1805 *endptr = p;
1806 /* add other consistency checks */
1807 return 1;
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!
1819 char*
1820 mono_identifier_unescape_type_name_chars(char* identifier)
1822 char *w, *r;
1823 if (!identifier)
1824 return NULL;
1825 for (w = r = identifier; *r != 0; r++)
1827 char c = *r;
1828 if (c == '\\') {
1829 r++;
1830 if (*r == 0)
1831 break;
1832 c = *r;
1834 *w = c;
1835 w++;
1837 if (w != r)
1838 *w = 0;
1839 return identifier;
1842 void
1843 mono_identifier_unescape_info (MonoTypeNameParse* info);
1845 static void
1846 unescape_each_type_argument(void* data, void* user_data)
1848 MonoTypeNameParse* info = (MonoTypeNameParse*)data;
1849 mono_identifier_unescape_info (info);
1852 static void
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.
1871 void
1872 mono_identifier_unescape_info (MonoTypeNameParse *info)
1874 if (!info)
1875 return;
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);
1881 if (info->nested)
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)
1891 ERROR_DECL (error);
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.
1910 gboolean
1911 mono_reflection_parse_type_checked (char *name, MonoTypeNameParse *info, MonoError *error)
1913 error_init (error);
1914 int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
1915 if (ok) {
1916 mono_identifier_unescape_info (info);
1917 } else {
1918 mono_error_set_argument_format (error, "typeName", "failed parse: %s", name);
1920 return (ok != 0);
1923 static MonoType*
1924 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
1926 gboolean type_resolve = FALSE;
1927 MonoType *type;
1928 MonoImage *rootimage = image;
1930 error_init (error);
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
1937 * installed.
1939 assembly = image->assembly;
1940 if (!assembly) {
1941 /* then we must load the assembly ourselve - see #60439 */
1942 assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
1943 if (!assembly)
1944 return 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);
1955 error_init (error);
1956 image = mono_defaults.corlib;
1957 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
1960 return type;
1964 * mono_reflection_get_type_internal:
1966 * Returns: may return NULL on success, sets error on failure.
1968 static MonoType*
1969 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
1971 HANDLE_FUNCTION_ENTER ();
1972 MonoClass *klass;
1973 GList *mod;
1974 int modval;
1975 gboolean bounded = FALSE;
1976 MonoType* type = NULL;
1978 error_init (error);
1979 if (!image)
1980 image = mono_defaults.corlib;
1982 if (!rootimage)
1983 rootimage = mono_defaults.corlib;
1985 if (ignorecase)
1986 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
1987 else
1988 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
1990 if (!klass)
1991 goto leave;
1993 for (mod = info->nested; mod; mod = mod->next) {
1994 gpointer iter = NULL;
1995 MonoClass *parent;
1997 parent = klass;
1998 mono_class_init_internal (parent);
2000 while ((klass = mono_class_get_nested_types (parent, &iter))) {
2001 const char *lastp;
2002 char *nested_name, *nested_nspace;
2003 gboolean match = TRUE;
2005 lastp = strrchr ((const char *)mod->data, '.');
2006 if (lastp) {
2007 /* Nested classes can have namespaces */
2008 int nspace_len;
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';
2016 } else {
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);
2023 if (ignorecase) {
2024 if (!(klass_name_space && mono_utf8_strcasecmp (klass_name_space, nested_nspace) == 0))
2025 match = FALSE;
2026 } else {
2027 if (!(klass_name_space && strcmp (klass_name_space, nested_nspace) == 0))
2028 match = FALSE;
2031 if (match) {
2032 const char *klass_name = m_class_get_name (klass);
2033 if (ignorecase) {
2034 if (mono_utf8_strcasecmp (klass_name, nested_name) != 0)
2035 match = FALSE;
2036 } else {
2037 if (strcmp (klass_name, nested_name) != 0)
2038 match = FALSE;
2041 if (lastp) {
2042 g_free (nested_name);
2043 g_free (nested_nspace);
2045 if (match)
2046 break;
2049 if (!klass)
2050 break;
2052 if (!klass)
2053 goto leave;
2055 if (info->type_arguments) {
2056 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
2057 MonoReflectionTypeHandle the_type;
2058 MonoType *instance;
2059 int i;
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]) {
2066 g_free (type_args);
2067 goto leave;
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))
2073 goto leave;
2075 instance = mono_reflection_bind_generic_parameters (
2076 the_type, info->type_arguments->len, type_args, error);
2078 g_free (type_args);
2079 if (!instance)
2080 goto leave;
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);
2089 goto leave;
2090 } else if (modval == -1) {
2091 klass = mono_class_create_ptr (m_class_get_byval_arg (klass));
2092 } else if (modval == -2) {
2093 bounded = TRUE;
2094 } else { /* array rank */
2095 klass = mono_class_create_bounded_array (klass, modval, bounded);
2099 type = m_class_get_byval_arg (klass);
2101 leave:
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.
2115 MonoType*
2116 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
2117 ERROR_DECL (error);
2118 MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
2119 mono_error_cleanup (error);
2120 return result;
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.
2133 MonoType*
2134 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
2135 error_init (error);
2136 return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
2140 static MonoType*
2141 module_builder_array_get_type (MonoArrayHandle module_builders, int i, MonoImage *rootimage, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
2143 HANDLE_FUNCTION_ENTER ();
2144 error_init (error);
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);
2153 static MonoType*
2154 module_array_get_type (MonoArrayHandle modules, int i, MonoImage *rootimage, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
2156 HANDLE_FUNCTION_ENTER ();
2157 error_init (error);
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);
2166 static MonoType*
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;
2171 int i;
2173 error_init (error);
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);
2187 if (type)
2188 break;
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);
2200 if (type)
2201 break;
2202 goto_if_nok (error, leave);
2206 leave:
2207 HANDLE_FUNCTION_RETURN_VAL (type);
2210 MonoType*
2211 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
2213 HANDLE_FUNCTION_ENTER ();
2215 MonoType *type;
2216 MonoReflectionAssemblyHandle reflection_assembly;
2217 GString *fullName = NULL;
2218 GList *mod;
2220 error_init (error);
2222 if (image && image_is_dynamic (image))
2223 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
2224 else
2225 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
2226 goto_if_nok (error, return_null);
2228 if (type)
2229 goto exit;
2230 if (!mono_domain_has_type_resolve (mono_domain_get ()))
2231 goto return_null;
2233 if (type_resolve) {
2234 if (*type_resolve)
2235 goto return_null;
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);
2243 else
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);
2259 else
2260 type = mono_reflection_get_type_internal (rootimage, assembly->image,
2261 info, ignorecase, error);
2263 goto_if_nok (error, return_null);
2264 goto exit;
2266 return_null:
2267 type = NULL;
2268 goto exit;
2270 exit:
2271 if (fullName)
2272 g_string_free (fullName, TRUE);
2273 HANDLE_FUNCTION_RETURN_VAL (type);
2277 * mono_reflection_free_type_info:
2279 void
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) {
2286 int i;
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*/
2293 g_free (subinfo);
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.
2310 MonoType*
2311 mono_reflection_type_from_name (char *name, MonoImage *image)
2313 ERROR_DECL (error);
2314 error_init (error);
2316 MonoType * const result = mono_reflection_type_from_name_checked (name, image, error);
2318 mono_error_cleanup (error);
2319 return result;
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.
2331 MonoType*
2332 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
2334 MonoType *type = NULL;
2335 MonoTypeNameParse info;
2336 char *tmp;
2338 error_init (error);
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);
2346 goto leave;
2348 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
2349 leave:
2350 g_free (tmp);
2351 mono_reflection_free_type_info (&info);
2352 return type;
2356 * mono_reflection_get_token:
2357 * \returns the metadata token of \p obj which should be an object
2358 * representing a metadata element.
2360 guint32
2361 mono_reflection_get_token (MonoObject *obj_raw)
2363 HANDLE_FUNCTION_ENTER ();
2364 MONO_HANDLE_DCL (MonoObject, obj);
2365 ERROR_DECL (error);
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.
2376 void
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);
2386 g_assert (f);
2387 member_field = f;
2389 MonoObject *member;
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;
2394 if (!pos_field) {
2395 MonoClassField *f = mono_class_get_field_from_name_full (klass, "PositionImpl", NULL);
2396 g_assert (f);
2397 pos_field = f;
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.
2409 guint32
2410 mono_reflection_get_token_checked (MonoObjectHandle obj, MonoError *error)
2412 guint32 token = 0;
2414 error_init (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);
2438 return 0;
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;
2449 } else {
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);
2468 int position;
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);
2482 } else {
2483 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
2484 m_class_get_name_space (klass), klass_name);
2485 return 0;
2488 return token;
2492 gboolean
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.
2508 MonoType*
2509 mono_reflection_bind_generic_parameters (MonoReflectionTypeHandle reftype, int type_argc, MonoType **types, MonoError *error)
2511 gboolean is_dynamic = FALSE;
2512 MonoClass *geninst;
2514 error_init (error);
2516 mono_loader_lock ();
2518 MonoClass *klass = mono_handle_class (reftype);
2519 if (mono_is_sre_type_builder (klass)) {
2520 is_dynamic = TRUE;
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)))
2528 is_dynamic = TRUE;
2531 MonoType *t = mono_reflection_type_handle_mono_type (reftype, error);
2532 if (!is_ok (error)) {
2533 mono_loader_unlock ();
2534 return NULL;
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");
2541 return NULL;
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);
2548 return NULL;
2552 if (m_class_was_typebuilder (klass))
2553 is_dynamic = TRUE;
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);
2562 MonoClass*
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 ();
2580 error_init (error);
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);
2592 leave:
2593 g_free (type_argv);
2594 HANDLE_FUNCTION_RETURN_VAL (ginst);
2597 static MonoMethod*
2598 reflection_bind_generic_method_parameters (MonoMethod *method, MonoArrayHandle types, MonoError *error)
2600 MonoClass *klass;
2601 MonoMethod *inflated;
2602 MonoGenericContext tmp_context;
2604 error_init (error);
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");
2614 return NULL;
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");
2628 return NULL;
2631 return inflated;
2634 MonoReflectionMethodHandle
2635 ves_icall_RuntimeMethodInfo_MakeGenericMethod_impl (MonoReflectionMethodHandle rmethod, MonoArrayHandle types, MonoError *error)
2637 error_init (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.
2688 static guint32
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];
2693 guint32 result = 0;
2694 guint32 action;
2695 int i;
2697 /* HasSecurity can be present for other, not specially encoded, attributes,
2698 e.g. SuppressUnmanagedCodeSecurityAttribute */
2699 if (index < 0)
2700 return 0;
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)
2707 break;
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];
2712 } else {
2713 g_assert_not_reached ();
2716 return result;
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).
2727 guint32
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);
2737 return 0;
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.
2748 guint32
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);
2754 if (!flags) {
2755 guint32 idx;
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);
2764 return flags;
2766 return 0;
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.
2775 guint32
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.
2790 static MonoBoolean
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;
2795 MonoTableInfo *t;
2796 guint32 cols [MONO_DECL_SECURITY_SIZE];
2797 int index = mono_metadata_declsec_from_index (image, token);
2798 int i;
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)
2805 return result;
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);
2815 result = TRUE;
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);
2823 result = TRUE;
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);
2831 result = TRUE;
2836 return result;
2839 static MonoBoolean
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);
2849 static MonoBoolean
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.
2865 MonoBoolean
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;
2871 guint32 flags;
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)
2875 return FALSE;
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);
2880 if (!method)
2881 return FALSE;
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);
2895 if (flags & mask) {
2896 if (!result) {
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]) */
2906 return result;
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.
2915 MonoBoolean
2916 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
2918 MonoBoolean result = FALSE;
2919 guint32 flags;
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)
2923 return FALSE;
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);
2928 if (!method)
2929 return FALSE;
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);
2953 return result;
2957 * mono_declsec_get_inheritdemands_class:
2958 * \param klass The inherited class - this is the class that provides the security check (attributes)
2959 * \param demands
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.
2964 MonoBoolean
2965 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
2967 MonoBoolean result = FALSE;
2968 guint32 flags;
2970 /* quick exit if no declarative security is present in the metadata */
2971 if (!m_class_get_image (klass)->tables [MONO_TABLE_DECLSECURITY].rows)
2972 return FALSE;
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);
2984 return result;
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.
2992 MonoBoolean
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)
2997 return FALSE;
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);
3002 if (!method)
3003 return FALSE;
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);
3013 return FALSE;
3017 static MonoBoolean
3018 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
3020 guint32 cols [MONO_DECL_SECURITY_SIZE];
3021 MonoTableInfo *t;
3022 int i;
3024 int index = mono_metadata_declsec_from_index (image, token);
3025 if (index == -1)
3026 return FALSE;
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])
3034 return FALSE;
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);
3040 return TRUE;
3044 return FALSE;
3047 MonoBoolean
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);
3056 return FALSE;
3060 * mono_declsec_get_class_action:
3062 MonoBoolean
3063 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
3065 /* use cache */
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);
3073 return FALSE;
3077 * mono_declsec_get_assembly_action:
3079 MonoBoolean
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);
3089 gboolean
3090 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
3092 MonoObject *res, *exc;
3093 void *params [1];
3094 static MonoMethod *method = NULL;
3096 error_init (error);
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);
3101 g_assert (method);
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);
3119 return FALSE;
3120 } else
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.
3129 MonoType*
3130 mono_reflection_type_get_type (MonoReflectionType *reftype)
3132 MonoType *result;
3133 MONO_ENTER_GC_UNSAFE;
3134 g_assert (reftype);
3136 ERROR_DECL (error);
3137 result = mono_reflection_type_get_handle (reftype, error);
3138 mono_error_assert_ok (error);
3139 MONO_EXIT_GC_UNSAFE;
3140 return result;
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.
3148 MonoAssembly*
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.
3161 MonoClass*
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);