2 * custom-attrs.c: Custom attributes.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2011 Rodrigo Kumpera
10 * Copyright 2016 Microsoft
12 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
15 #include "mono/metadata/assembly.h"
16 #include "mono/metadata/gc-internals.h"
17 #include "mono/metadata/mono-endian.h"
18 #include "mono/metadata/object-internals.h"
19 #include "mono/metadata/custom-attrs-internals.h"
20 #include "mono/metadata/sre-internals.h"
21 #include "mono/metadata/reflection-internals.h"
22 #include "mono/metadata/tabledefs.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/verify-internals.h"
25 #include "mono/utils/checked-build.h"
28 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
29 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
31 #if SIZEOF_VOID_P == 4
32 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
34 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
37 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
38 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
40 static gboolean
type_is_reference (MonoType
*type
);
42 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument
, System
.Reflection
, CustomAttributeTypedArgument
);
43 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument
, System
.Reflection
, CustomAttributeNamedArgument
);
46 * LOCKING: Acquires the loader lock.
48 static MonoCustomAttrInfo
*
49 lookup_custom_attr (MonoImage
*image
, gpointer member
)
51 MONO_REQ_GC_NEUTRAL_MODE
;
53 MonoCustomAttrInfo
* res
;
55 res
= (MonoCustomAttrInfo
*)mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
60 res
= (MonoCustomAttrInfo
*)g_memdup (res
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * res
->num_attrs
);
66 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
68 MONO_REQ_GC_UNSAFE_MODE
;
70 /* FIXME: Need to do more checks */
71 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
72 int visibility
= mono_class_get_flags (cattr
->ctor
->method
->klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
74 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
82 type_is_reference (MonoType
*type
)
85 case MONO_TYPE_BOOLEAN
:
99 case MONO_TYPE_VALUETYPE
:
107 free_param_data (MonoMethodSignature
*sig
, void **params
) {
109 for (i
= 0; i
< sig
->param_count
; ++i
) {
110 if (!type_is_reference (sig
->params
[i
]))
116 * Find the field index in the metadata FieldDef table.
119 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
122 int fcount
= mono_class_get_field_count (klass
);
123 for (i
= 0; i
< fcount
; ++i
) {
124 if (field
== &klass
->fields
[i
])
125 return mono_class_get_first_field_idx (klass
) + 1 + i
;
131 * Find the property index in the metadata Property table.
134 find_property_index (MonoClass
*klass
, MonoProperty
*property
)
137 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
139 for (i
= 0; i
< info
->count
; ++i
) {
140 if (property
== &info
->properties
[i
])
141 return info
->first
+ 1 + i
;
147 * Find the event index in the metadata Event table.
150 find_event_index (MonoClass
*klass
, MonoEvent
*event
)
153 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
155 for (i
= 0; i
< info
->count
; ++i
) {
156 if (event
== &info
->events
[i
])
157 return info
->first
+ 1 + i
;
163 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
164 * The @is_enum flag only affects the error message that's displayed on failure.
167 cattr_type_from_name (char *n
, MonoImage
*image
, gboolean is_enum
, MonoError
*error
)
169 MonoError inner_error
;
170 MonoType
*t
= mono_reflection_type_from_name_checked (n
, image
, &inner_error
);
172 mono_error_set_type_load_name (error
, g_strdup(n
), NULL
,
173 "Could not load %s %s while decoding custom attribute: %s",
174 is_enum
? "enum type": "type",
176 mono_error_get_message (&inner_error
));
177 mono_error_cleanup (&inner_error
);
184 load_cattr_enum_type (MonoImage
*image
, const char *p
, const char **end
, MonoError
*error
)
188 int slen
= mono_metadata_decode_value (p
, &p
);
190 mono_error_init (error
);
192 n
= (char *)g_memdup (p
, slen
+ 1);
194 t
= cattr_type_from_name (n
, image
, TRUE
, error
);
196 return_val_if_nok (error
, NULL
);
199 return mono_class_from_mono_type (t
);
203 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
, MonoError
*error
)
205 int slen
, type
= t
->type
;
206 MonoClass
*tklass
= t
->data
.klass
;
208 mono_error_init (error
);
214 case MONO_TYPE_BOOLEAN
: {
215 MonoBoolean
*bval
= (MonoBoolean
*)g_malloc (sizeof (MonoBoolean
));
223 guint16
*val
= (guint16
*)g_malloc (sizeof (guint16
));
228 #if SIZEOF_VOID_P == 4
235 guint32
*val
= (guint32
*)g_malloc (sizeof (guint32
));
240 #if SIZEOF_VOID_P == 8
241 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
246 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
252 double *val
= (double *)g_malloc (sizeof (double));
257 case MONO_TYPE_VALUETYPE
:
258 if (t
->data
.klass
->enumtype
) {
259 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
262 MonoClass
*k
= t
->data
.klass
;
264 if (mono_is_corlib_image (k
->image
) && strcmp (k
->name_space
, "System") == 0 && strcmp (k
->name
, "DateTime") == 0){
265 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
271 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
274 case MONO_TYPE_STRING
:
275 if (*p
== (char)0xFF) {
279 slen
= mono_metadata_decode_value (p
, &p
);
281 return mono_string_new_len_checked (mono_domain_get (), p
, slen
, error
);
282 case MONO_TYPE_CLASS
: {
283 MonoReflectionType
*rt
;
286 if (*p
== (char)0xFF) {
291 slen
= mono_metadata_decode_value (p
, &p
);
292 n
= (char *)g_memdup (p
, slen
+ 1);
294 t
= cattr_type_from_name (n
, image
, FALSE
, error
);
296 return_val_if_nok (error
, NULL
);
299 rt
= mono_type_get_object_checked (mono_domain_get (), t
, error
);
300 if (!mono_error_ok (error
))
305 case MONO_TYPE_OBJECT
: {
308 MonoClass
*subc
= NULL
;
313 } else if (subt
== 0x0E) {
314 type
= MONO_TYPE_STRING
;
316 } else if (subt
== 0x1D) {
317 MonoType simple_type
= {{0}};
321 type
= MONO_TYPE_SZARRAY
;
323 tklass
= mono_defaults
.systemtype_class
;
324 } else if (etype
== 0x55) {
325 tklass
= load_cattr_enum_type (image
, p
, &p
, error
);
326 if (!mono_error_ok (error
))
330 /* See Partition II, Appendix B3 */
331 etype
= MONO_TYPE_OBJECT
;
332 simple_type
.type
= (MonoTypeEnum
)etype
;
333 tklass
= mono_class_from_mono_type (&simple_type
);
336 } else if (subt
== 0x55) {
339 slen
= mono_metadata_decode_value (p
, &p
);
340 n
= (char *)g_memdup (p
, slen
+ 1);
342 t
= cattr_type_from_name (n
, image
, FALSE
, error
);
344 return_val_if_nok (error
, NULL
);
346 subc
= mono_class_from_mono_type (t
);
347 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
348 MonoType simple_type
= {{0}};
349 simple_type
.type
= (MonoTypeEnum
)subt
;
350 subc
= mono_class_from_mono_type (&simple_type
);
352 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
354 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
, error
);
356 if (mono_error_ok (error
)) {
357 obj
= mono_object_new_checked (mono_domain_get (), subc
, error
);
358 g_assert (!subc
->has_references
);
359 if (mono_error_ok (error
))
360 mono_gc_memmove_atomic ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
366 case MONO_TYPE_SZARRAY
: {
368 guint32 i
, alen
, basetype
;
371 if (alen
== 0xffffffff) {
375 arr
= mono_array_new_checked (mono_domain_get(), tklass
, alen
, error
);
376 return_val_if_nok (error
, NULL
);
377 basetype
= tklass
->byval_arg
.type
;
378 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
379 basetype
= mono_class_enum_basetype (tklass
)->type
;
384 case MONO_TYPE_BOOLEAN
:
385 for (i
= 0; i
< alen
; i
++) {
386 MonoBoolean val
= *p
++;
387 mono_array_set (arr
, MonoBoolean
, i
, val
);
393 for (i
= 0; i
< alen
; i
++) {
394 guint16 val
= read16 (p
);
395 mono_array_set (arr
, guint16
, i
, val
);
402 for (i
= 0; i
< alen
; i
++) {
403 guint32 val
= read32 (p
);
404 mono_array_set (arr
, guint32
, i
, val
);
409 for (i
= 0; i
< alen
; i
++) {
412 mono_array_set (arr
, double, i
, val
);
418 for (i
= 0; i
< alen
; i
++) {
419 guint64 val
= read64 (p
);
420 mono_array_set (arr
, guint64
, i
, val
);
424 case MONO_TYPE_CLASS
:
425 case MONO_TYPE_OBJECT
:
426 case MONO_TYPE_STRING
:
427 case MONO_TYPE_SZARRAY
:
428 for (i
= 0; i
< alen
; i
++) {
429 MonoObject
*item
= (MonoObject
*)load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
, error
);
430 if (!mono_error_ok (error
))
432 mono_array_setref (arr
, i
, item
);
436 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
442 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
448 load_cattr_value_boxed (MonoDomain
*domain
, MonoImage
*image
, MonoType
*t
, const char* p
, const char** end
, MonoError
*error
)
450 mono_error_init (error
);
452 gboolean is_ref
= type_is_reference (t
);
454 void *val
= load_cattr_value (image
, t
, p
, end
, error
);
455 if (!is_ok (error
)) {
462 return (MonoObject
*)val
;
464 MonoObject
*boxed
= mono_value_box_checked (domain
, mono_class_from_mono_type (t
), val
, error
);
470 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
, MonoError
*error
)
472 static MonoMethod
*ctor
;
474 void *params
[2], *unboxed
;
476 mono_error_init (error
);
479 ctor
= mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
481 params
[0] = mono_type_get_object_checked (mono_domain_get (), t
, error
);
482 return_val_if_nok (error
, NULL
);
485 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error
);
486 return_val_if_nok (error
, NULL
);
487 unboxed
= mono_object_unbox (retval
);
489 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
490 return_val_if_nok (error
, NULL
);
496 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
, MonoError
*error
)
498 static MonoMethod
*ctor
;
500 void *unboxed
, *params
[2];
502 mono_error_init (error
);
505 ctor
= mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
508 params
[1] = typedarg
;
509 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error
);
510 return_val_if_nok (error
, NULL
);
512 unboxed
= mono_object_unbox (retval
);
514 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
515 return_val_if_nok (error
, NULL
);
522 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
524 MONO_REQ_GC_UNSAFE_MODE
;
526 int i
, index
, count
, not_visible
;
527 MonoCustomAttrInfo
*ainfo
;
528 MonoReflectionCustomAttr
*cattr
;
532 /* FIXME: check in assembly the Run flag is set */
534 count
= mono_array_length (cattrs
);
536 /* Skip nonpublic attributes since MS.NET seems to do the same */
537 /* FIXME: This needs to be done more globally */
539 for (i
= 0; i
< count
; ++i
) {
540 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
541 if (!custom_attr_visible (image
, cattr
))
545 int num_attrs
= count
- not_visible
;
546 ainfo
= (MonoCustomAttrInfo
*)mono_image_g_malloc0 (alloc_img
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * num_attrs
);
548 ainfo
->image
= image
;
549 ainfo
->num_attrs
= num_attrs
;
550 ainfo
->cached
= alloc_img
!= NULL
;
552 for (i
= 0; i
< count
; ++i
) {
553 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
554 if (custom_attr_visible (image
, cattr
)) {
555 unsigned char *saved
= (unsigned char *)mono_image_alloc (image
, mono_array_length (cattr
->data
));
556 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
557 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
558 g_assert (cattr
->ctor
->method
);
559 ainfo
->attrs
[index
].data
= saved
;
560 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
564 g_assert (index
== num_attrs
&& count
== num_attrs
+ not_visible
);
571 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoError
*error
)
573 const char *p
= (const char*)data
;
575 guint32 i
, j
, num_named
;
577 void *params_buf
[32];
578 void **params
= NULL
;
579 MonoMethodSignature
*sig
;
581 mono_error_init (error
);
583 mono_class_init (method
->klass
);
585 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, NULL
)) {
586 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
591 attr
= mono_object_new_checked (mono_domain_get (), method
->klass
, error
);
592 if (!mono_error_ok (error
)) return NULL
;
594 mono_runtime_invoke_checked (method
, attr
, NULL
, error
);
595 if (!mono_error_ok (error
))
601 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
604 /*g_print ("got attr %s\n", method->klass->name);*/
606 sig
= mono_method_signature (method
);
607 if (sig
->param_count
< 32) {
609 memset (params
, 0, sizeof (void*) * sig
->param_count
);
611 /* Allocate using GC so it gets GC tracking */
612 params
= (void **)mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), MONO_GC_DESCRIPTOR_NULL
, MONO_ROOT_SOURCE_REFLECTION
, "custom attribute parameters");
617 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
618 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
, error
);
619 if (!mono_error_ok (error
))
624 attr
= mono_object_new_checked (mono_domain_get (), method
->klass
, error
);
625 if (!mono_error_ok (error
)) goto fail
;
627 MonoObject
*exc
= NULL
;
628 mono_runtime_try_invoke (method
, attr
, params
, &exc
, error
);
629 if (!mono_error_ok (error
))
632 mono_error_set_exception_instance (error
, (MonoException
*)exc
);
636 num_named
= read16 (named
);
638 for (j
= 0; j
< num_named
; j
++) {
640 char *name
, named_type
, data_type
;
641 named_type
= *named
++;
642 data_type
= *named
++; /* type of data */
643 if (data_type
== MONO_TYPE_SZARRAY
)
644 data_type
= *named
++;
645 if (data_type
== MONO_TYPE_ENUM
) {
648 type_len
= mono_metadata_decode_blob_size (named
, &named
);
649 type_name
= (char *)g_malloc (type_len
+ 1);
650 memcpy (type_name
, named
, type_len
);
651 type_name
[type_len
] = 0;
653 /* FIXME: lookup the type and check type consistency */
656 name_len
= mono_metadata_decode_blob_size (named
, &named
);
657 name
= (char *)g_malloc (name_len
+ 1);
658 memcpy (name
, named
, name_len
);
661 if (named_type
== 0x53) {
662 MonoClassField
*field
;
665 /* how this fail is a blackbox */
666 field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
668 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name
);
673 val
= load_cattr_value (image
, field
->type
, named
, &named
, error
);
674 if (!mono_error_ok (error
)) {
676 if (!type_is_reference (field
->type
))
681 mono_field_set_value (attr
, field
, val
);
682 if (!type_is_reference (field
->type
))
684 } else if (named_type
== 0x54) {
689 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
692 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name
);
698 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name
);
703 /* can we have more that 1 arg in a custom attr named property? */
704 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
705 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
707 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
, error
);
708 if (!mono_error_ok (error
)) {
710 if (!type_is_reference (prop_type
))
711 g_free (pparams
[0]);
716 mono_property_set_value_checked (prop
, attr
, pparams
, error
);
717 if (!type_is_reference (prop_type
))
718 g_free (pparams
[0]);
719 if (!is_ok (error
)) {
727 free_param_data (method
->signature
, params
);
728 if (params
!= params_buf
)
729 mono_gc_free_fixed (params
);
734 free_param_data (method
->signature
, params
);
735 if (params
!= params_buf
)
736 mono_gc_free_fixed (params
);
741 * mono_reflection_create_custom_attr_data_args:
743 * Create an array of typed and named arguments from the cattr blob given by DATA.
744 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
745 * NAMED_ARG_INFO will contain information about the named arguments.
748 mono_reflection_create_custom_attr_data_args (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoArray
**typed_args
, MonoArray
**named_args
, CattrNamedArg
**named_arg_info
, MonoError
*error
)
750 MonoArray
*typedargs
, *namedargs
;
751 MonoClass
*attrklass
;
753 const char *p
= (const char*)data
;
755 guint32 i
, j
, num_named
;
756 CattrNamedArg
*arginfo
= NULL
;
760 *named_arg_info
= NULL
;
762 mono_error_init (error
);
764 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, NULL
)) {
765 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
769 mono_class_init (method
->klass
);
771 domain
= mono_domain_get ();
773 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
776 typedargs
= mono_array_new_checked (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
, error
);
777 return_if_nok (error
);
781 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
784 obj
= load_cattr_value_boxed (domain
, image
, mono_method_signature (method
)->params
[i
], p
, &p
, error
);
785 return_if_nok (error
);
786 mono_array_setref (typedargs
, i
, obj
);
790 num_named
= read16 (named
);
791 namedargs
= mono_array_new_checked (domain
, mono_get_object_class (), num_named
, error
);
792 return_if_nok (error
);
794 attrklass
= method
->klass
;
796 arginfo
= g_new0 (CattrNamedArg
, num_named
);
797 *named_arg_info
= arginfo
;
799 for (j
= 0; j
< num_named
; j
++) {
801 char *name
, named_type
, data_type
;
802 named_type
= *named
++;
803 data_type
= *named
++; /* type of data */
804 if (data_type
== MONO_TYPE_SZARRAY
)
805 data_type
= *named
++;
806 if (data_type
== MONO_TYPE_ENUM
) {
809 type_len
= mono_metadata_decode_blob_size (named
, &named
);
810 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
813 type_name
= (char *)g_malloc (type_len
+ 1);
814 memcpy (type_name
, named
, type_len
);
815 type_name
[type_len
] = 0;
817 /* FIXME: lookup the type and check type consistency */
820 name_len
= mono_metadata_decode_blob_size (named
, &named
);
821 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
823 name
= (char *)g_malloc (name_len
+ 1);
824 memcpy (name
, named
, name_len
);
827 if (named_type
== 0x53) {
829 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
836 arginfo
[j
].type
= field
->type
;
837 arginfo
[j
].field
= field
;
839 obj
= load_cattr_value_boxed (domain
, image
, field
->type
, named
, &named
, error
);
840 if (!is_ok (error
)) {
844 mono_array_setref (namedargs
, j
, obj
);
846 } else if (named_type
== 0x54) {
849 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
851 if (!prop
|| !prop
->set
) {
856 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
857 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
859 arginfo
[j
].type
= prop_type
;
860 arginfo
[j
].prop
= prop
;
862 obj
= load_cattr_value_boxed (domain
, image
, prop_type
, named
, &named
, error
);
863 if (!is_ok (error
)) {
867 mono_array_setref (namedargs
, j
, obj
);
872 *typed_args
= typedargs
;
873 *named_args
= namedargs
;
876 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
878 *named_arg_info
= NULL
;
882 reflection_resolve_custom_attribute_data (MonoReflectionMethod
*ref_method
, MonoReflectionAssembly
*assembly
, gpointer data
, guint32 len
, MonoArray
**ctor_args
, MonoArray
**named_args
, MonoError
*error
)
885 MonoArray
*typedargs
, *namedargs
;
888 CattrNamedArg
*arginfo
= NULL
;
891 mono_error_init (error
);
899 image
= assembly
->assembly
->image
;
900 method
= ref_method
->method
;
901 domain
= mono_object_domain (ref_method
);
903 if (!mono_class_init (method
->klass
)) {
904 mono_error_set_for_class_failure (error
, method
->klass
);
908 mono_reflection_create_custom_attr_data_args (image
, method
, (const guchar
*)data
, len
, &typedargs
, &namedargs
, &arginfo
, error
);
912 if (!typedargs
|| !namedargs
)
915 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
916 MonoObject
*obj
= mono_array_get (typedargs
, MonoObject
*, i
);
917 MonoObject
*typedarg
;
919 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
, error
);
922 mono_array_setref (typedargs
, i
, typedarg
);
925 for (i
= 0; i
< mono_array_length (namedargs
); ++i
) {
926 MonoObject
*obj
= mono_array_get (namedargs
, MonoObject
*, i
);
927 MonoObject
*typedarg
, *namedarg
, *minfo
;
929 if (arginfo
[i
].prop
) {
930 minfo
= (MonoObject
*)mono_property_get_object_checked (domain
, NULL
, arginfo
[i
].prop
, error
);
934 minfo
= (MonoObject
*)mono_field_get_object_checked (domain
, NULL
, arginfo
[i
].field
, error
);
939 typedarg
= create_cattr_typed_arg (arginfo
[i
].type
, obj
, error
);
942 namedarg
= create_cattr_named_arg (minfo
, typedarg
, error
);
946 mono_array_setref (namedargs
, i
, namedarg
);
949 *ctor_args
= typedargs
;
950 *named_args
= namedargs
;
954 return mono_error_ok (error
);
958 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod
*ref_method
, MonoReflectionAssembly
*assembly
, gpointer data
, guint32 len
, MonoArray
**ctor_args
, MonoArray
**named_args
)
961 (void) reflection_resolve_custom_attribute_data (ref_method
, assembly
, data
, len
, ctor_args
, named_args
, &error
);
962 mono_error_set_pending_exception (&error
);
965 static MonoObjectHandle
966 create_custom_attr_data_handle (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoError
*error
)
968 static MonoMethod
*ctor
;
973 mono_error_init (error
);
975 g_assert (image
->assembly
);
978 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 4);
980 domain
= mono_domain_get ();
982 MonoObjectHandle attr
= MONO_HANDLE_NEW (MonoObject
, mono_object_new_checked (domain
, mono_defaults
.customattribute_data_class
, error
));
986 MonoReflectionMethod
*ctor_obj
= mono_method_get_object_checked (domain
, cattr
->ctor
, NULL
, error
);
989 MonoReflectionAssemblyHandle assm
= mono_assembly_get_object_handle (domain
, image
->assembly
, error
);
992 params
[0] = ctor_obj
;
993 params
[1] = MONO_HANDLE_RAW (assm
);
994 params
[2] = (gpointer
)&cattr
->data
;
995 params
[3] = &cattr
->data_size
;
997 mono_runtime_invoke_checked (ctor
, MONO_HANDLE_RAW (attr
), params
, error
);
1000 return MONO_HANDLE_NEW (MonoObject
, NULL
);
1004 create_custom_attr_data (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoError
*error
)
1006 HANDLE_FUNCTION_ENTER ();
1007 MonoObjectHandle obj
= create_custom_attr_data_handle (image
, cattr
, error
);
1008 HANDLE_FUNCTION_RETURN_OBJ (obj
);
1012 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
, MonoError
*error
)
1018 mono_error_init (error
);
1020 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1021 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1022 if (!centry
->ctor
) {
1023 /* The cattr type is not finished yet */
1024 /* We should include the type name but cinfo doesn't contain it */
1025 mono_error_set_type_load_name (error
, NULL
, NULL
, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1032 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1033 MonoMethod
*ctor
= cinfo
->attrs
[i
].ctor
;
1035 if (mono_class_is_assignable_from (attr_klass
, ctor
->klass
))
1039 n
= cinfo
->num_attrs
;
1042 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
, error
);
1043 return_val_if_nok (error
, NULL
);
1045 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1046 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1047 if (!attr_klass
|| mono_class_is_assignable_from (attr_klass
, centry
->ctor
->klass
)) {
1048 attr
= create_custom_attr (cinfo
->image
, centry
->ctor
, centry
->data
, centry
->data_size
, error
);
1049 if (!mono_error_ok (error
))
1051 mono_array_setref (result
, n
, attr
);
1059 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
1062 MonoArray
*result
= mono_custom_attrs_construct_by_type (cinfo
, NULL
, &error
);
1063 mono_error_assert_ok (&error
); /*FIXME proper error handling*/
1069 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
, MonoError
*error
)
1075 mono_error_init (error
);
1076 result
= mono_array_new_checked (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
, error
);
1077 return_val_if_nok (error
, NULL
);
1078 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1079 attr
= create_custom_attr_data (cinfo
->image
, &cinfo
->attrs
[i
], error
);
1080 return_val_if_nok (error
, NULL
);
1081 mono_array_setref (result
, i
, attr
);
1087 * mono_custom_attrs_from_index:
1089 * Returns: NULL if no attributes are found or if a loading error occurs.
1092 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
1095 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, &error
);
1096 mono_error_cleanup (&error
);
1100 * mono_custom_attrs_from_index_checked:
1102 * Returns: NULL if no attributes are found. On error returns NULL and sets @error.
1105 mono_custom_attrs_from_index_checked (MonoImage
*image
, guint32 idx
, gboolean ignore_missing
, MonoError
*error
)
1107 guint32 mtoken
, i
, len
;
1108 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
1110 MonoCustomAttrInfo
*ainfo
;
1111 GList
*tmp
, *list
= NULL
;
1113 MonoCustomAttrEntry
* attr
;
1115 mono_error_init (error
);
1117 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1119 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
1123 while (i
< ca
->rows
) {
1124 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
1126 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
1129 len
= g_list_length (list
);
1132 ainfo
= (MonoCustomAttrInfo
*)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * len
);
1133 ainfo
->num_attrs
= len
;
1134 ainfo
->image
= image
;
1135 for (i
= len
, tmp
= list
; i
!= 0; --i
, tmp
= tmp
->next
) {
1136 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
1137 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
1138 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
1139 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
1140 mtoken
|= MONO_TOKEN_METHOD_DEF
;
1142 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
1143 mtoken
|= MONO_TOKEN_MEMBER_REF
;
1146 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
1149 attr
= &ainfo
->attrs
[i
- 1];
1150 attr
->ctor
= mono_get_method_checked (image
, mtoken
, NULL
, NULL
, error
);
1152 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image
->name
, mtoken
, mono_error_get_message (error
));
1153 if (ignore_missing
) {
1154 mono_error_cleanup (error
);
1155 mono_error_init (error
);
1163 if (!mono_verifier_verify_cattr_blob (image
, cols
[MONO_CUSTOM_ATTR_VALUE
], NULL
)) {
1164 /*FIXME raising an exception here doesn't make any sense*/
1165 g_warning ("Invalid custom attribute blob on image %s for index %x", image
->name
, idx
);
1170 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
1171 attr
->data_size
= mono_metadata_decode_value (data
, &data
);
1172 attr
->data
= (guchar
*)data
;
1180 mono_custom_attrs_from_method (MonoMethod
*method
)
1183 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_method_checked (method
, &error
);
1184 mono_error_cleanup (&error
); /* FIXME want a better API that doesn't swallow the error */
1189 mono_custom_attrs_from_method_checked (MonoMethod
*method
, MonoError
*error
)
1193 mono_error_init (error
);
1196 * An instantiated method has the same cattrs as the generic method definition.
1198 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1199 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1201 if (method
->is_inflated
)
1202 method
= ((MonoMethodInflated
*) method
)->declaring
;
1204 if (method_is_dynamic (method
) || image_is_dynamic (method
->klass
->image
))
1205 return lookup_custom_attr (method
->klass
->image
, method
);
1208 /* Synthetic methods */
1211 idx
= mono_method_get_index (method
);
1212 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1213 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
1214 return mono_custom_attrs_from_index_checked (method
->klass
->image
, idx
, FALSE
, error
);
1218 mono_custom_attrs_from_class (MonoClass
*klass
)
1221 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_class_checked (klass
, &error
);
1222 mono_error_cleanup (&error
);
1227 mono_custom_attrs_from_class_checked (MonoClass
*klass
, MonoError
*error
)
1231 mono_error_init (error
);
1233 if (mono_class_is_ginst (klass
))
1234 klass
= mono_class_get_generic_class (klass
)->container_class
;
1236 if (image_is_dynamic (klass
->image
))
1237 return lookup_custom_attr (klass
->image
, klass
);
1239 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
1240 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
1241 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1242 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
1244 idx
= mono_metadata_token_index (klass
->type_token
);
1245 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1246 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
1248 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, FALSE
, error
);
1252 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
1255 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_assembly_checked (assembly
, FALSE
, &error
);
1256 mono_error_cleanup (&error
);
1261 mono_custom_attrs_from_assembly_checked (MonoAssembly
*assembly
, gboolean ignore_missing
, MonoError
*error
)
1265 mono_error_init (error
);
1267 if (image_is_dynamic (assembly
->image
))
1268 return lookup_custom_attr (assembly
->image
, assembly
);
1269 idx
= 1; /* there is only one assembly */
1270 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1271 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
1272 return mono_custom_attrs_from_index_checked (assembly
->image
, idx
, ignore_missing
, error
);
1275 static MonoCustomAttrInfo
*
1276 mono_custom_attrs_from_module (MonoImage
*image
, MonoError
*error
)
1280 if (image_is_dynamic (image
))
1281 return lookup_custom_attr (image
, image
);
1282 idx
= 1; /* there is only one module */
1283 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1284 idx
|= MONO_CUSTOM_ATTR_MODULE
;
1285 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1289 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
1292 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_property_checked (klass
, property
, &error
);
1293 mono_error_cleanup (&error
);
1298 mono_custom_attrs_from_property_checked (MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
1302 if (image_is_dynamic (klass
->image
)) {
1303 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
1304 return lookup_custom_attr (klass
->image
, property
);
1306 idx
= find_property_index (klass
, property
);
1307 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1308 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
1309 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, FALSE
, error
);
1313 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
1316 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_event_checked (klass
, event
, &error
);
1317 mono_error_cleanup (&error
);
1322 mono_custom_attrs_from_event_checked (MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
1326 if (image_is_dynamic (klass
->image
)) {
1327 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
1328 return lookup_custom_attr (klass
->image
, event
);
1330 idx
= find_event_index (klass
, event
);
1331 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1332 idx
|= MONO_CUSTOM_ATTR_EVENT
;
1333 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, FALSE
, error
);
1337 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
1340 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_field_checked (klass
, field
, &error
);
1341 mono_error_cleanup (&error
);
1346 mono_custom_attrs_from_field_checked (MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
1349 mono_error_init (error
);
1351 if (image_is_dynamic (klass
->image
)) {
1352 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
1353 return lookup_custom_attr (klass
->image
, field
);
1355 idx
= find_field_index (klass
, field
);
1356 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1357 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
1358 return mono_custom_attrs_from_index_checked (klass
->image
, idx
, FALSE
, error
);
1362 * mono_custom_attrs_from_param:
1363 * @method: handle to the method that we want to retrieve custom parameter information from
1364 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1366 * The result must be released with mono_custom_attrs_free().
1368 * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
1371 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
1374 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_param_checked (method
, param
, &error
);
1375 mono_error_cleanup (&error
);
1380 * mono_custom_attrs_from_param_checked:
1381 * @method: handle to the method that we want to retrieve custom parameter information from
1382 * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1383 * @error: set on error
1385 * The result must be released with mono_custom_attrs_free().
1387 * Returns: the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets @error.
1390 mono_custom_attrs_from_param_checked (MonoMethod
*method
, guint32 param
, MonoError
*error
)
1393 guint32 i
, idx
, method_index
;
1394 guint32 param_list
, param_last
, param_pos
, found
;
1396 MonoReflectionMethodAux
*aux
;
1398 mono_error_init (error
);
1401 * An instantiated method has the same cattrs as the generic method definition.
1403 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1404 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1406 if (method
->is_inflated
)
1407 method
= ((MonoMethodInflated
*) method
)->declaring
;
1409 if (image_is_dynamic (method
->klass
->image
)) {
1410 MonoCustomAttrInfo
*res
, *ainfo
;
1413 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
1414 if (!aux
|| !aux
->param_cattr
)
1417 /* Need to copy since it will be freed later */
1418 ainfo
= aux
->param_cattr
[param
];
1421 size
= MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * ainfo
->num_attrs
;
1422 res
= (MonoCustomAttrInfo
*)g_malloc0 (size
);
1423 memcpy (res
, ainfo
, size
);
1427 image
= method
->klass
->image
;
1428 method_index
= mono_method_get_index (method
);
1431 ca
= &image
->tables
[MONO_TABLE_METHOD
];
1433 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
1434 if (method_index
== ca
->rows
) {
1435 ca
= &image
->tables
[MONO_TABLE_PARAM
];
1436 param_last
= ca
->rows
+ 1;
1438 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
1439 ca
= &image
->tables
[MONO_TABLE_PARAM
];
1442 for (i
= param_list
; i
< param_last
; ++i
) {
1443 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
1444 if (param_pos
== param
) {
1452 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1453 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
1454 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1458 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
1461 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
1462 MonoCustomAttrEntry
*centry
= &ainfo
->attrs
[i
];
1463 if (centry
->ctor
== NULL
)
1465 MonoClass
*klass
= centry
->ctor
->klass
;
1466 if (klass
== attr_klass
|| mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
1473 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
1476 MonoObject
*res
= mono_custom_attrs_get_attr_checked (ainfo
, attr_klass
, &error
);
1477 mono_error_assert_ok (&error
); /*FIXME proper error handling*/
1482 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
, MonoError
*error
)
1485 MonoCustomAttrEntry
*centry
= NULL
;
1487 g_assert (attr_klass
!= NULL
);
1489 mono_error_init (error
);
1491 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
1492 centry
= &ainfo
->attrs
[i
];
1493 if (centry
->ctor
== NULL
)
1495 MonoClass
*klass
= centry
->ctor
->klass
;
1496 if (attr_klass
== klass
|| mono_class_is_assignable_from (attr_klass
, klass
))
1502 return create_custom_attr (ainfo
->image
, centry
->ctor
, centry
->data
, centry
->data_size
, error
);
1506 * mono_reflection_get_custom_attrs_info:
1507 * @obj: a reflection object handle
1509 * Return the custom attribute info for attributes defined for the
1510 * reflection handle @obj. The objects.
1512 * FIXME this function leaks like a sieve for SRE objects.
1515 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
1518 MonoCustomAttrInfo
*result
= mono_reflection_get_custom_attrs_info_checked (obj
, &error
);
1519 mono_error_assert_ok (&error
);
1524 * mono_reflection_get_custom_attrs_info_checked:
1525 * @obj: a reflection object handle
1526 * @error: set on error
1528 * Return the custom attribute info for attributes defined for the
1529 * reflection handle @obj. The objects.
1531 * On failure returns NULL and sets @error.
1533 * FIXME this function leaks like a sieve for SRE objects.
1536 mono_reflection_get_custom_attrs_info_checked (MonoObject
*obj
, MonoError
*error
)
1539 MonoCustomAttrInfo
*cinfo
= NULL
;
1541 mono_error_init (error
);
1543 klass
= obj
->vtable
->klass
;
1544 if (klass
== mono_defaults
.runtimetype_class
) {
1545 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
, error
);
1546 return_val_if_nok (error
, NULL
);
1547 klass
= mono_class_from_mono_type (type
);
1548 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1549 cinfo
= mono_custom_attrs_from_class_checked (klass
, error
);
1550 return_val_if_nok (error
, NULL
);
1551 } else if (strcmp ("Assembly", klass
->name
) == 0 || strcmp ("MonoAssembly", klass
->name
) == 0) {
1552 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
1553 cinfo
= mono_custom_attrs_from_assembly_checked (rassembly
->assembly
, FALSE
, error
);
1554 return_val_if_nok (error
, NULL
);
1555 } else if (strcmp ("Module", klass
->name
) == 0 || strcmp ("MonoModule", klass
->name
) == 0) {
1556 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
1557 cinfo
= mono_custom_attrs_from_module (module
->image
, error
);
1558 return_val_if_nok (error
, NULL
);
1559 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
1560 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
1561 cinfo
= mono_custom_attrs_from_property_checked (rprop
->property
->parent
, rprop
->property
, error
);
1562 return_val_if_nok (error
, NULL
);
1563 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
1564 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
1565 cinfo
= mono_custom_attrs_from_event_checked (revent
->event
->parent
, revent
->event
, error
);
1566 return_val_if_nok (error
, NULL
);
1567 } else if (strcmp ("MonoField", klass
->name
) == 0) {
1568 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
1569 cinfo
= mono_custom_attrs_from_field_checked (rfield
->field
->parent
, rfield
->field
, error
);
1570 return_val_if_nok (error
, NULL
);
1571 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
1572 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
1573 cinfo
= mono_custom_attrs_from_method_checked (rmethod
->method
, error
);
1574 return_val_if_nok (error
, NULL
);
1575 } else if (strcmp ("ParameterInfo", klass
->name
) == 0 || strcmp ("MonoParameterInfo", klass
->name
) == 0) {
1576 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
1577 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
1578 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
1579 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
1580 cinfo
= mono_custom_attrs_from_param_checked (rmethod
->method
, param
->PositionImpl
+ 1, error
);
1581 return_val_if_nok (error
, NULL
);
1582 } else if (mono_is_sr_mono_property (member_class
)) {
1583 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
1585 if (!(method
= prop
->property
->get
))
1586 method
= prop
->property
->set
;
1589 cinfo
= mono_custom_attrs_from_param_checked (method
, param
->PositionImpl
+ 1, error
);
1590 return_val_if_nok (error
, NULL
);
1592 #ifndef DISABLE_REFLECTION_EMIT
1593 else if (mono_is_sre_method_on_tb_inst (member_class
)) {/*XXX This is a workaround for Compiler Context*/
1594 // FIXME: Is this still needed ?
1595 g_assert_not_reached ();
1596 } else if (mono_is_sre_ctor_on_tb_inst (member_class
)) { /*XX This is a workaround for Compiler Context*/
1597 // FIXME: Is this still needed ?
1598 g_assert_not_reached ();
1602 char *type_name
= mono_type_get_full_name (member_class
);
1603 mono_error_set_not_supported (error
,
1604 "Custom attributes on a ParamInfo with member %s are not supported",
1609 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
1610 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
1611 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
1612 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
1613 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
1614 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
1615 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
1616 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
1617 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
1618 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
1619 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
1620 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
1621 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
1622 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
1623 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
1624 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
1625 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
1626 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
1627 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
1628 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
1629 cinfo
= mono_reflection_get_custom_attrs_info_checked ((MonoObject
*)gclass
->generic_type
, error
);
1630 return_val_if_nok (error
, NULL
);
1631 } else { /* handle other types here... */
1632 g_error ("get custom attrs not yet supported for %s", klass
->name
);
1639 * mono_reflection_get_custom_attrs_by_type:
1640 * @obj: a reflection object handle
1642 * Return an array with all the custom attributes defined of the
1643 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
1644 * of that type are returned. The objects are fully build. Return NULL if a loading error
1648 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
, MonoError
*error
)
1651 MonoCustomAttrInfo
*cinfo
;
1653 mono_error_init (error
);
1655 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
1656 return_val_if_nok (error
, NULL
);
1658 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
, error
);
1660 mono_custom_attrs_free (cinfo
);
1664 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0, error
);
1671 * mono_reflection_get_custom_attrs:
1672 * @obj: a reflection object handle
1674 * Return an array with all the custom attributes defined of the
1675 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
1679 mono_reflection_get_custom_attrs (MonoObject
*obj
)
1683 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
, &error
);
1687 * mono_reflection_get_custom_attrs_data:
1688 * @obj: a reflection obj handle
1690 * Returns an array of System.Reflection.CustomAttributeData,
1691 * which include information about attributes reflected on
1692 * types loaded using the Reflection Only methods
1695 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
1699 result
= mono_reflection_get_custom_attrs_data_checked (obj
, &error
);
1700 mono_error_cleanup (&error
);
1705 * mono_reflection_get_custom_attrs_data_checked:
1706 * @obj: a reflection obj handle
1707 * @error: set on error
1709 * Returns an array of System.Reflection.CustomAttributeData,
1710 * which include information about attributes reflected on
1711 * types loaded using the Reflection Only methods
1714 mono_reflection_get_custom_attrs_data_checked (MonoObject
*obj
, MonoError
*error
)
1717 MonoCustomAttrInfo
*cinfo
;
1719 mono_error_init (error
);
1721 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
1722 return_val_if_nok (error
, NULL
);
1724 result
= mono_custom_attrs_data_construct (cinfo
, error
);
1726 mono_custom_attrs_free (cinfo
);
1727 return_val_if_nok (error
, NULL
);
1729 result
= mono_array_new_checked (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0, error
);
1735 custom_attr_class_name_from_methoddef (MonoImage
*image
, guint32 method_token
, const gchar
**nspace
, const gchar
**class_name
)
1737 /* mono_get_method_from_token () */
1738 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
);
1739 guint32 type_token
= mono_metadata_typedef_from_method (image
, method_token
);
1741 /* Bad method token (could not find corresponding typedef) */
1744 type_token
|= MONO_TOKEN_TYPE_DEF
;
1746 /* mono_class_create_from_typedef () */
1747 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
1748 guint32 cols
[MONO_TYPEDEF_SIZE
];
1749 guint tidx
= mono_metadata_token_index (type_token
);
1751 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
1752 /* "Invalid typedef token %x", type_token */
1756 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
1759 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
1761 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
1768 * custom_attr_class_name_from_method_token:
1769 * @image: The MonoImage
1770 * @method_token: a token for a custom attr constructor in @image
1771 * @assembly_token: out argment set to the assembly ref token of the custom attr
1772 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
1773 * @class_name: out argument set to the class name of the custom attr.
1775 * Given an @image and a @method_token (which is assumed to be a
1776 * constructor), fills in the out arguments with the assembly ref (if
1777 * a methodref) and the namespace and class name of the custom
1780 * Returns: TRUE on success, FALSE otherwise.
1782 * LOCKING: does not take locks
1785 custom_attr_class_name_from_method_token (MonoImage
*image
, guint32 method_token
, guint32
*assembly_token
, const gchar
**nspace
, const gchar
**class_name
)
1787 /* This only works with method tokens constructed from a
1788 * custom attr token, which can only be methoddef or
1790 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
1791 || mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
);
1793 if (mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
) {
1794 /* method_from_memberref () */
1796 guint32 nindex
, class_index
;
1798 int idx
= mono_metadata_token_index (method_token
);
1800 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, 3);
1801 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
1802 class_index
= cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
1803 if (class_index
== MONO_MEMBERREF_PARENT_TYPEREF
) {
1804 guint32 type_token
= MONO_TOKEN_TYPE_REF
| nindex
;
1805 /* mono_class_from_typeref_checked () */
1807 guint32 cols
[MONO_TYPEREF_SIZE
];
1808 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
1810 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
1813 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
1815 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
1817 *assembly_token
= cols
[MONO_TYPEREF_SCOPE
];
1820 } else if (class_index
== MONO_MEMBERREF_PARENT_METHODDEF
) {
1821 guint32 methoddef_token
= MONO_TOKEN_METHOD_DEF
| nindex
;
1823 *assembly_token
= 0;
1824 return custom_attr_class_name_from_methoddef (image
, methoddef_token
, nspace
, class_name
);
1826 /* Attributes can't be generic, so it won't be
1827 * a typespec, and they're always
1828 * constructors, so it won't be a moduleref */
1829 g_assert_not_reached ();
1832 /* must be MONO_TABLE_METHOD */
1834 *assembly_token
= 0;
1835 return custom_attr_class_name_from_methoddef (image
, method_token
, nspace
, class_name
);
1840 * mono_assembly_metadata_foreach_custom_attr:
1841 * @assembly: the assembly to iterate over
1842 * @func: the function to call for each custom attribute
1843 * @user_data: passed to @func
1845 * Calls @func for each custom attribute type on the given assembly until @func returns TRUE.
1846 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
1850 mono_assembly_metadata_foreach_custom_attr (MonoAssembly
*assembly
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
1854 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
1859 * This might be called during assembly loading, so do everything using the low-level
1863 image
= assembly
->image
;
1864 g_assert (!image_is_dynamic (image
));
1865 idx
= 1; /* there is only one assembly */
1866 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1867 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
1869 /* Inlined from mono_custom_attrs_from_index_checked () */
1870 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1871 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
1875 gboolean stop_iterating
= FALSE
;
1876 while (!stop_iterating
&& i
< ca
->rows
) {
1877 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
1879 mono_metadata_decode_row (ca
, i
, cols
, MONO_CUSTOM_ATTR_SIZE
);
1881 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
1882 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
1883 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
1884 mtoken
|= MONO_TOKEN_METHOD_DEF
;
1886 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
1887 mtoken
|= MONO_TOKEN_MEMBER_REF
;
1890 g_warning ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
1894 const char *nspace
= NULL
;
1895 const char *name
= NULL
;
1896 guint32 assembly_token
= 0;
1898 if (!custom_attr_class_name_from_method_token (image
, mtoken
, &assembly_token
, &nspace
, &name
))
1901 stop_iterating
= func (image
, assembly_token
, nspace
, name
, mtoken
, user_data
);