6 * Paolo Molaro (lupus@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2011 Rodrigo Kumpera
11 * Copyright 2016 Microsoft
13 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
16 #include "mono/metadata/assembly.h"
17 #include "mono/metadata/class-init.h"
18 #include "mono/metadata/gc-internals.h"
19 #include "mono/metadata/mono-endian.h"
20 #include "mono/metadata/object-internals.h"
21 #include "mono/metadata/custom-attrs-internals.h"
22 #include "mono/metadata/sre-internals.h"
23 #include "mono/metadata/reflection-internals.h"
24 #include "mono/metadata/tabledefs.h"
25 #include "mono/metadata/tokentype.h"
26 #include "mono/metadata/verify-internals.h"
27 #include "mono/utils/checked-build.h"
30 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
31 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
33 #if SIZEOF_VOID_P == 4
34 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
36 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
39 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
40 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
42 #define CATTR_TYPE_SYSTEM_TYPE 0x50
43 #define CATTR_BOXED_VALUETYPE_PREFIX 0x51
44 #define CATTR_TYPE_FIELD 0x53
45 #define CATTR_TYPE_PROPERTY 0x54
47 static gboolean
type_is_reference (MonoType
*type
);
49 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument
, "System.Reflection", "CustomAttributeTypedArgument");
50 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument
, "System.Reflection", "CustomAttributeNamedArgument");
51 static GENERATE_TRY_GET_CLASS_WITH_CACHE (customattribute_data
, "System.Reflection", "CustomAttributeData");
53 static MonoCustomAttrInfo
*
54 mono_custom_attrs_from_builders_handle (MonoImage
*alloc_img
, MonoImage
*image
, MonoArrayHandle cattrs
);
57 bcheck_blob (const char *ptr
, int bump
, const char *endp
, MonoError
*error
);
60 decode_blob_value_checked (const char *ptr
, const char *endp
, guint32
*size_out
, const char **retp
, MonoError
*error
);
63 * LOCKING: Acquires the loader lock.
65 static MonoCustomAttrInfo
*
66 lookup_custom_attr (MonoImage
*image
, gpointer member
)
68 MONO_REQ_GC_NEUTRAL_MODE
;
70 MonoCustomAttrInfo
* res
;
72 res
= (MonoCustomAttrInfo
*)mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
77 res
= (MonoCustomAttrInfo
*)g_memdup (res
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * res
->num_attrs
);
83 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
85 MONO_REQ_GC_UNSAFE_MODE
;
87 /* FIXME: Need to do more checks */
88 if (cattr
->ctor
->method
&& (m_class_get_image (cattr
->ctor
->method
->klass
) != image
)) {
89 int visibility
= mono_class_get_flags (cattr
->ctor
->method
->klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
91 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
99 type_is_reference (MonoType
*type
)
101 switch (type
->type
) {
102 case MONO_TYPE_BOOLEAN
:
116 case MONO_TYPE_VALUETYPE
:
124 free_param_data (MonoMethodSignature
*sig
, void **params
) {
126 for (i
= 0; i
< sig
->param_count
; ++i
) {
127 if (!type_is_reference (sig
->params
[i
]))
133 * Find the field index in the metadata FieldDef table.
136 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
137 int fcount
= mono_class_get_field_count (klass
);
138 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
139 int index
= field
- klass_fields
;
143 g_assert (field
== &klass_fields
[index
]);
144 return mono_class_get_first_field_idx (klass
) + 1 + index
;
148 * Find the property index in the metadata Property table.
151 find_property_index (MonoClass
*klass
, MonoProperty
*property
)
154 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
156 for (i
= 0; i
< info
->count
; ++i
) {
157 if (property
== &info
->properties
[i
])
158 return info
->first
+ 1 + i
;
164 * Find the event index in the metadata Event table.
167 find_event_index (MonoClass
*klass
, MonoEvent
*event
)
170 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
172 for (i
= 0; i
< info
->count
; ++i
) {
173 if (event
== &info
->events
[i
])
174 return info
->first
+ 1 + i
;
180 * Load the type with name @n on behalf of image @image. On failure sets @error and returns NULL.
181 * The @is_enum flag only affects the error message that's displayed on failure.
184 cattr_type_from_name (char *n
, MonoImage
*image
, gboolean is_enum
, MonoError
*error
)
186 ERROR_DECL_VALUE (inner_error
);
187 MonoType
*t
= mono_reflection_type_from_name_checked (n
, image
, &inner_error
);
189 mono_error_set_type_load_name (error
, g_strdup(n
), NULL
,
190 "Could not load %s %s while decoding custom attribute: %s",
191 is_enum
? "enum type": "type",
193 mono_error_get_message (&inner_error
));
194 mono_error_cleanup (&inner_error
);
201 load_cattr_enum_type (MonoImage
*image
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
)
208 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
211 if (boundp
&& slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
213 n
= (char *)g_memdup (p
, slen
+ 1);
215 t
= cattr_type_from_name (n
, image
, TRUE
, error
);
217 return_val_if_nok (error
, NULL
);
220 return mono_class_from_mono_type_internal (t
);
224 load_cattr_type (MonoImage
*image
, MonoType
*t
, gboolean header
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
, guint32
*slen
)
230 if (!bcheck_blob (p
, 0, boundp
, error
))
232 if (*p
== (char)0xFF) {
238 if (!decode_blob_value_checked (p
, boundp
, slen
, &p
, error
))
240 if (*slen
> 0 && !bcheck_blob (p
, *slen
- 1, boundp
, error
))
242 n
= (char *)g_memdup (p
, *slen
+ 1);
244 res
= cattr_type_from_name (n
, image
, FALSE
, error
);
246 return_val_if_nok (error
, NULL
);
253 static MonoReflectionType
*
254 load_cattr_type_object (MonoImage
*image
, MonoType
*t
, gboolean header
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
, guint32
*slen
)
258 type
= load_cattr_type (image
, t
, header
, p
, boundp
, end
, error
, slen
);
261 return mono_type_get_object_checked (mono_domain_get (), type
, error
);
265 * If OUT_OBJ is non-NULL, created objects are stored into it and NULL is returned.
266 * If OUT_OBJ is NULL, assert if objects were to be created.
269 load_cattr_value (MonoImage
*image
, MonoType
*t
, MonoObject
**out_obj
, const char *p
, const char *boundp
, const char **end
, MonoError
*error
)
273 MonoClass
*tklass
= t
->data
.klass
;
280 if (type
== MONO_TYPE_GENERICINST
) {
281 MonoGenericClass
* mgc
= t
->data
.generic_class
;
282 MonoClass
* cc
= mgc
->container_class
;
283 if (m_class_is_enumtype (cc
)) {
284 tklass
= m_class_get_element_class (cc
);
285 t
= m_class_get_byval_arg (tklass
);
288 g_error ("Unhandled type of generic instance in load_cattr_value: %s", m_class_get_name (cc
));
296 case MONO_TYPE_BOOLEAN
: {
297 MonoBoolean
*bval
= (MonoBoolean
*)g_malloc (sizeof (MonoBoolean
));
298 if (!bcheck_blob (p
, 0, boundp
, error
))
307 guint16
*val
= (guint16
*)g_malloc (sizeof (guint16
));
308 if (!bcheck_blob (p
, 1, boundp
, error
))
314 #if SIZEOF_VOID_P == 4
321 guint32
*val
= (guint32
*)g_malloc (sizeof (guint32
));
322 if (!bcheck_blob (p
, 3, boundp
, error
))
328 #if SIZEOF_VOID_P == 8
329 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
334 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
335 if (!bcheck_blob (p
, 7, boundp
, error
))
342 double *val
= (double *)g_malloc (sizeof (double));
343 if (!bcheck_blob (p
, 7, boundp
, error
))
349 case MONO_TYPE_VALUETYPE
:
350 if (m_class_is_enumtype (t
->data
.klass
)) {
351 type
= mono_class_enum_basetype_internal (t
->data
.klass
)->type
;
354 MonoClass
*k
= t
->data
.klass
;
356 if (mono_is_corlib_image (m_class_get_image (k
)) && strcmp (m_class_get_name_space (k
), "System") == 0 && strcmp (m_class_get_name (k
), "DateTime") == 0){
357 guint64
*val
= (guint64
*)g_malloc (sizeof (guint64
));
358 if (!bcheck_blob (p
, 7, boundp
, error
))
365 g_error ("generic valutype %s not handled in custom attr value decoding", m_class_get_name (t
->data
.klass
));
368 case MONO_TYPE_STRING
:
369 if (!bcheck_blob (p
, 0, boundp
, error
))
371 if (*p
== (char)0xFF) {
375 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
377 if (slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
382 // https://bugzilla.xamarin.com/show_bug.cgi?id=60848
383 // Custom attribute strings are encoded as wtf-8 instead of utf-8.
384 // If we decode using utf-8 like the spec says, we will silently fail
385 // to decode some attributes in assemblies that Windows .NET Framework
386 // and CoreCLR both manage to decode.
387 // See https://simonsapin.github.io/wtf-8/ for a description of wtf-8.
388 *out_obj
= (MonoObject
*)mono_string_new_wtf8_len_checked (mono_domain_get (), p
, slen
, error
);
390 case MONO_TYPE_CLASS
: {
391 MonoType
*type
= load_cattr_type (image
, t
, TRUE
, p
, boundp
, end
, error
, &slen
);
395 *out_obj
= (MonoObject
*)mono_type_get_object_checked (mono_domain_get (), type
, error
);
401 case MONO_TYPE_OBJECT
: {
402 if (!bcheck_blob (p
, 0, boundp
, error
))
406 MonoClass
*subc
= NULL
;
409 if (subt
== CATTR_TYPE_SYSTEM_TYPE
) {
410 MonoType
*type
= load_cattr_type (image
, t
, FALSE
, p
, boundp
, end
, error
, &slen
);
414 *out_obj
= (MonoObject
*)mono_type_get_object_checked (mono_domain_get (), type
, error
);
419 } else if (subt
== 0x0E) {
420 type
= MONO_TYPE_STRING
;
422 } else if (subt
== 0x1D) {
423 MonoType simple_type
= {{0}};
424 if (!bcheck_blob (p
, 0, boundp
, error
))
429 type
= MONO_TYPE_SZARRAY
;
430 if (etype
== CATTR_TYPE_SYSTEM_TYPE
) {
431 tklass
= mono_defaults
.systemtype_class
;
432 } else if (etype
== MONO_TYPE_ENUM
) {
433 tklass
= load_cattr_enum_type (image
, p
, boundp
, &p
, error
);
437 if (etype
== CATTR_BOXED_VALUETYPE_PREFIX
)
438 /* See Partition II, Appendix B3 */
439 etype
= MONO_TYPE_OBJECT
;
440 simple_type
.type
= (MonoTypeEnum
)etype
;
441 tklass
= mono_class_from_mono_type_internal (&simple_type
);
444 } else if (subt
== MONO_TYPE_ENUM
) {
447 if (!decode_blob_value_checked (p
, boundp
, &slen
, &p
, error
))
449 if (slen
> 0 && !bcheck_blob (p
, slen
- 1, boundp
, error
))
451 n
= (char *)g_memdup (p
, slen
+ 1);
453 t
= cattr_type_from_name (n
, image
, FALSE
, error
);
455 return_val_if_nok (error
, NULL
);
457 subc
= mono_class_from_mono_type_internal (t
);
458 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
459 MonoType simple_type
= {{0}};
460 simple_type
.type
= (MonoTypeEnum
)subt
;
461 subc
= mono_class_from_mono_type_internal (&simple_type
);
463 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
465 val
= load_cattr_value (image
, m_class_get_byval_arg (subc
), NULL
, p
, boundp
, end
, error
);
467 obj
= mono_object_new_checked (mono_domain_get (), subc
, error
);
468 g_assert (!m_class_has_references (subc
));
470 mono_gc_memmove_atomic (mono_object_get_data (obj
), val
, mono_class_value_size (subc
, NULL
));
478 case MONO_TYPE_SZARRAY
: {
480 guint32 i
, alen
, basetype
;
481 if (!bcheck_blob (p
, 3, boundp
, error
))
485 if (alen
== 0xffffffff) {
489 arr
= mono_array_new_checked (mono_domain_get(), tklass
, alen
, error
);
490 return_val_if_nok (error
, NULL
);
491 basetype
= m_class_get_byval_arg (tklass
)->type
;
492 if (basetype
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (tklass
))
493 basetype
= mono_class_enum_basetype_internal (tklass
)->type
;
495 if (basetype
== MONO_TYPE_GENERICINST
) {
496 MonoGenericClass
* mgc
= m_class_get_byval_arg (tklass
)->data
.generic_class
;
497 MonoClass
* cc
= mgc
->container_class
;
498 if (m_class_is_enumtype (cc
)) {
499 basetype
= m_class_get_byval_arg (m_class_get_element_class (cc
))->type
;
501 g_error ("Unhandled type of generic instance in load_cattr_value: %s[]", m_class_get_name (cc
));
508 case MONO_TYPE_BOOLEAN
:
509 for (i
= 0; i
< alen
; i
++) {
510 if (!bcheck_blob (p
, 0, boundp
, error
))
512 MonoBoolean val
= *p
++;
513 mono_array_set (arr
, MonoBoolean
, i
, val
);
519 for (i
= 0; i
< alen
; i
++) {
520 if (!bcheck_blob (p
, 1, boundp
, error
))
522 guint16 val
= read16 (p
);
523 mono_array_set (arr
, guint16
, i
, val
);
530 for (i
= 0; i
< alen
; i
++) {
531 if (!bcheck_blob (p
, 3, boundp
, error
))
533 guint32 val
= read32 (p
);
534 mono_array_set (arr
, guint32
, i
, val
);
539 for (i
= 0; i
< alen
; i
++) {
540 if (!bcheck_blob (p
, 7, boundp
, error
))
544 mono_array_set (arr
, double, i
, val
);
550 for (i
= 0; i
< alen
; i
++) {
551 if (!bcheck_blob (p
, 7, boundp
, error
))
553 guint64 val
= read64 (p
);
554 mono_array_set (arr
, guint64
, i
, val
);
558 case MONO_TYPE_CLASS
:
559 case MONO_TYPE_OBJECT
:
560 case MONO_TYPE_STRING
:
561 case MONO_TYPE_SZARRAY
:
562 for (i
= 0; i
< alen
; i
++) {
563 MonoObject
*item
= NULL
;
564 load_cattr_value (image
, m_class_get_byval_arg (tklass
), &item
, p
, boundp
, &p
, error
);
567 mono_array_setref (arr
, i
, item
);
571 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
575 *out_obj
= (MonoObject
*)arr
;
579 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
585 load_cattr_value_boxed (MonoDomain
*domain
, MonoImage
*image
, MonoType
*t
, const char* p
, const char *boundp
, const char** end
, MonoError
*error
)
589 gboolean is_ref
= type_is_reference (t
);
592 MonoObject
*obj
= NULL
;
593 gpointer val
= load_cattr_value (image
, t
, &obj
, p
, boundp
, end
, error
);
599 void *val
= load_cattr_value (image
, t
, NULL
, p
, boundp
, end
, error
);
603 MonoObject
*boxed
= mono_value_box_checked (domain
, mono_class_from_mono_type_internal (t
), val
, error
);
610 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
, MonoError
*error
)
612 static MonoMethod
*ctor
;
614 void *params
[2], *unboxed
;
619 ctor
= mono_class_get_method_from_name_checked (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2, 0, error
);
620 mono_error_assert_ok (error
);
623 params
[0] = mono_type_get_object_checked (mono_domain_get (), t
, error
);
624 return_val_if_nok (error
, NULL
);
627 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error
);
628 return_val_if_nok (error
, NULL
);
629 unboxed
= mono_object_unbox (retval
);
631 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
632 return_val_if_nok (error
, NULL
);
638 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
, MonoError
*error
)
640 static MonoMethod
*ctor
;
642 void *unboxed
, *params
[2];
647 ctor
= mono_class_get_method_from_name_checked (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2, 0, error
);
648 mono_error_assert_ok (error
);
652 params
[1] = typedarg
;
653 retval
= mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error
);
654 return_val_if_nok (error
, NULL
);
656 unboxed
= mono_object_unbox (retval
);
658 mono_runtime_invoke_checked (ctor
, unboxed
, params
, error
);
659 return_val_if_nok (error
, NULL
);
665 static MonoCustomAttrInfo
*
666 mono_custom_attrs_from_builders_handle (MonoImage
*alloc_img
, MonoImage
*image
, MonoArrayHandle cattrs
)
668 return mono_custom_attrs_from_builders (alloc_img
, image
, MONO_HANDLE_RAW (cattrs
)); /* FIXME use coop handles for mono_custom_attrs_from_builders */
672 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
674 MONO_REQ_GC_UNSAFE_MODE
;
676 int i
, index
, count
, not_visible
;
677 MonoCustomAttrInfo
*ainfo
;
678 MonoReflectionCustomAttr
*cattr
;
682 /* FIXME: check in assembly the Run flag is set */
684 count
= mono_array_length_internal (cattrs
);
686 /* Skip nonpublic attributes since MS.NET seems to do the same */
687 /* FIXME: This needs to be done more globally */
689 for (i
= 0; i
< count
; ++i
) {
690 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
691 if (!custom_attr_visible (image
, cattr
))
695 int num_attrs
= count
- not_visible
;
696 ainfo
= (MonoCustomAttrInfo
*)mono_image_g_malloc0 (alloc_img
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * num_attrs
);
698 ainfo
->image
= image
;
699 ainfo
->num_attrs
= num_attrs
;
700 ainfo
->cached
= alloc_img
!= NULL
;
702 for (i
= 0; i
< count
; ++i
) {
703 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
704 if (custom_attr_visible (image
, cattr
)) {
705 unsigned char *saved
= (unsigned char *)mono_image_alloc (image
, mono_array_length_internal (cattr
->data
));
706 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length_internal (cattr
->data
));
707 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
708 g_assert (cattr
->ctor
->method
);
709 ainfo
->attrs
[index
].data
= saved
;
710 ainfo
->attrs
[index
].data_size
= mono_array_length_internal (cattr
->data
);
714 g_assert (index
== num_attrs
&& count
== num_attrs
+ not_visible
);
720 set_custom_attr_fmt_error (MonoError
*error
)
723 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
728 * \param ptr a pointer into a blob
729 * \param bump how far we plan on reading past \p ptr.
730 * \param endp upper bound for \p ptr - one past the last valid value for \p ptr.
731 * \param error set on error
733 * Check that ptr+bump is below endp. Returns TRUE on success, or FALSE on
734 * failure and sets \p error.
737 bcheck_blob (const char *ptr
, int bump
, const char *endp
, MonoError
*error
)
740 if (ADDP_IS_GREATER_OR_OVF (ptr
, bump
, endp
- 1)) {
741 set_custom_attr_fmt_error (error
);
748 * decode_blob_size_checked:
749 * \param ptr a pointer into a blob
750 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
751 * \param size_out on success set to the decoded size
752 * \param retp on success set to the next byte after the encoded size
753 * \param error set on error
755 * Decode an encoded size value which takes 1, 2, or 4 bytes and set \p
756 * size_out to the decoded size and \p retp to the next byte after the encoded
757 * size. Returns TRUE on success, or FALASE on failure and sets \p error.
760 decode_blob_size_checked (const char *ptr
, const char *endp
, guint32
*size_out
, const char **retp
, MonoError
*error
)
763 if (endp
&& !bcheck_blob (ptr
, 0, endp
, error
))
765 if ((*ptr
& 0x80) != 0) {
766 if ((*ptr
& 0x40) == 0 && !bcheck_blob (ptr
, 1, endp
, error
))
768 else if (!bcheck_blob (ptr
, 3, endp
, error
))
771 *size_out
= mono_metadata_decode_blob_size (ptr
, retp
);
773 return is_ok (error
);
777 * decode_blob_value_checked:
778 * \param ptr a pointer into a blob
779 * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
780 * \param value_out on success set to the decoded value
781 * \param retp on success set to the next byte after the encoded size
782 * \param error set on error
784 * Decode an encoded uint32 value which takes 1, 2, or 4 bytes and set \p
785 * value_out to the decoded value and \p retp to the next byte after the
786 * encoded value. Returns TRUE on success, or FALASE on failure and sets \p
790 decode_blob_value_checked (const char *ptr
, const char *endp
, guint32
*value_out
, const char **retp
, MonoError
*error
)
792 /* This similar to decode_blob_size_checked, above but delegates to
793 * mono_metadata_decode_value which is semantically different. */
795 if (!bcheck_blob (ptr
, 0, endp
, error
))
797 if ((*ptr
& 0x80) != 0) {
798 if ((*ptr
& 0x40) == 0 && !bcheck_blob (ptr
, 1, endp
, error
))
800 else if (!bcheck_blob (ptr
, 3, endp
, error
))
803 *value_out
= mono_metadata_decode_value (ptr
, retp
);
805 return is_ok (error
);
808 static MonoObjectHandle
809 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
, MonoError
*error
)
811 HANDLE_FUNCTION_ENTER ();
813 const char *p
= (const char*)data
;
814 const char *data_end
= (const char*)data
+ len
;
816 guint32 i
, j
, num_named
;
817 MonoObjectHandle attr
= NULL_HANDLE
;
818 void *params_buf
[32];
819 void **params
= NULL
;
820 MonoMethodSignature
*sig
;
821 MonoClassField
*field
= NULL
;
823 void *pparams
[1] = { NULL
};
824 MonoType
*prop_type
= NULL
;
825 void *val
= NULL
; // FIXMEcoop is this a raw pointer or a value?
829 mono_class_init (method
->klass
);
831 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
835 attr
= mono_object_new_handle (mono_domain_get (), method
->klass
, error
);
836 goto_if_nok (error
, fail
);
838 mono_runtime_invoke_handle (method
, attr
, NULL
, error
);
839 goto_if_nok (error
, fail
);
844 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
847 /*g_print ("got attr %s\n", method->klass->name);*/
849 sig
= mono_method_signature_internal (method
);
850 if (sig
->param_count
< 32) {
852 memset (params
, 0, sizeof (void*) * sig
->param_count
);
854 /* Allocate using GC so it gets GC tracking */
855 params
= (void **)mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), MONO_GC_DESCRIPTOR_NULL
, MONO_ROOT_SOURCE_REFLECTION
, NULL
, "Reflection Custom Attribute Parameters");
860 for (i
= 0; i
< mono_method_signature_internal (method
)->param_count
; ++i
) {
861 MonoObject
*param_obj
;
862 params
[i
] = load_cattr_value (image
, mono_method_signature_internal (method
)->params
[i
], ¶m_obj
, p
, data_end
, &p
, error
);
864 params
[i
] = param_obj
;
865 goto_if_nok (error
, fail
);
869 attr
= mono_object_new_handle (mono_domain_get (), method
->klass
, error
);
870 goto_if_nok (error
, fail
);
872 (void)mono_runtime_try_invoke_handle (method
, attr
, params
, error
);
873 goto_if_nok (error
, fail
);
875 if (named
+ 1 < data_end
) {
876 num_named
= read16 (named
);
879 /* CoreCLR allows p == data + len */
880 if (named
== data_end
)
883 set_custom_attr_fmt_error (error
);
887 for (j
= 0; j
< num_named
; j
++) {
889 char named_type
, data_type
;
890 if (!bcheck_blob (named
, 1, data_end
, error
))
892 named_type
= *named
++;
893 data_type
= *named
++; /* type of data */
894 if (data_type
== MONO_TYPE_SZARRAY
) {
895 if (!bcheck_blob (named
, 0, data_end
, error
))
897 data_type
= *named
++;
899 if (data_type
== MONO_TYPE_ENUM
) {
902 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
904 if (type_len
> 0 && !bcheck_blob (named
, type_len
- 1, data_end
, error
))
906 type_name
= (char *)g_malloc (type_len
+ 1);
907 memcpy (type_name
, named
, type_len
);
908 type_name
[type_len
] = 0;
910 /* FIXME: lookup the type and check type consistency */
913 if (!decode_blob_size_checked (named
, data_end
, &name_len
, &named
, error
))
915 if (name_len
> 0 && !bcheck_blob (named
, name_len
- 1, data_end
, error
))
917 name
= (char *)g_malloc (name_len
+ 1);
918 memcpy (name
, named
, name_len
);
921 if (named_type
== CATTR_TYPE_FIELD
) {
922 /* how this fail is a blackbox */
923 field
= mono_class_get_field_from_name_full (mono_handle_class (attr
), name
, NULL
);
925 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name
);
929 MonoObject
*param_obj
;
930 val
= load_cattr_value (image
, field
->type
, ¶m_obj
, named
, data_end
, &named
, error
);
933 goto_if_nok (error
, fail
);
935 mono_field_set_value (MONO_HANDLE_RAW (attr
), field
, val
); // FIXMEcoop
936 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
938 prop
= mono_class_get_property_from_name (mono_handle_class (attr
), name
);
940 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name
);
945 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name
);
949 /* can we have more that 1 arg in a custom attr named property? */
950 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
951 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
953 MonoObject
*param_obj
;
954 pparams
[0] = load_cattr_value (image
, prop_type
, ¶m_obj
, named
, data_end
, &named
, error
);
956 pparams
[0] = param_obj
;
957 goto_if_nok (error
, fail
);
959 mono_property_set_value_handle (prop
, attr
, pparams
, error
);
960 goto_if_nok (error
, fail
);
966 attr
= mono_new_null ();
968 if (field
&& !type_is_reference (field
->type
))
971 if (prop_type
&& !type_is_reference (prop_type
))
972 g_free (pparams
[0]);
974 free_param_data (method
->signature
, params
);
975 if (params
!= params_buf
)
976 mono_gc_free_fixed (params
);
979 HANDLE_FUNCTION_RETURN_REF (MonoObject
, attr
);
983 create_custom_attr_into_array (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
,
984 guint32 len
, MonoArrayHandle array
, int index
, MonoError
*error
)
986 // This function serves to avoid creating handles in a loop.
987 HANDLE_FUNCTION_ENTER ();
988 MonoObjectHandle attr
= create_custom_attr (image
, method
, data
, len
, error
);
989 MONO_HANDLE_ARRAY_SETREF (array
, index
, attr
);
990 HANDLE_FUNCTION_RETURN ();
994 * mono_reflection_create_custom_attr_data_args:
996 * Create an array of typed and named arguments from the cattr blob given by DATA.
997 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
998 * NAMED_ARG_INFO will contain information about the named arguments.
1001 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
)
1003 MonoArray
*typedargs
, *namedargs
;
1004 MonoClass
*attrklass
;
1006 const char *p
= (const char*)data
;
1007 const char *data_end
= p
+ len
;
1009 guint32 i
, j
, num_named
;
1010 CattrNamedArg
*arginfo
= NULL
;
1014 *named_arg_info
= NULL
;
1018 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
1021 mono_class_init (method
->klass
);
1023 domain
= mono_domain_get ();
1025 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
1030 /* Parse each argument corresponding to the signature's parameters from
1031 * the blob and store in typedargs.
1033 typedargs
= mono_array_new_checked (domain
, mono_get_object_class (), mono_method_signature_internal (method
)->param_count
, error
);
1034 return_if_nok (error
);
1036 for (i
= 0; i
< mono_method_signature_internal (method
)->param_count
; ++i
) {
1039 obj
= load_cattr_value_boxed (domain
, image
, mono_method_signature_internal (method
)->params
[i
], p
, data_end
, &p
, error
);
1040 return_if_nok (error
);
1041 mono_array_setref (typedargs
, i
, obj
);
1046 /* Parse mandatory count of named arguments (could be zero) */
1047 if (!bcheck_blob (named
, 1, data_end
, error
))
1049 num_named
= read16 (named
);
1050 namedargs
= mono_array_new_checked (domain
, mono_get_object_class (), num_named
, error
);
1051 return_if_nok (error
);
1053 attrklass
= method
->klass
;
1055 arginfo
= g_new0 (CattrNamedArg
, num_named
);
1056 *named_arg_info
= arginfo
;
1058 /* Parse each named arg, and add to arginfo. Each named argument could
1059 * be a field name or a property name followed by a value. */
1060 for (j
= 0; j
< num_named
; j
++) {
1062 char *name
, named_type
, data_type
;
1063 if (!bcheck_blob (named
, 1, data_end
, error
))
1065 named_type
= *named
++; /* field or property? */
1066 data_type
= *named
++; /* type of data */
1067 if (data_type
== MONO_TYPE_SZARRAY
) {
1068 if (!bcheck_blob (named
, 0, data_end
, error
))
1070 data_type
= *named
++;
1072 if (data_type
== MONO_TYPE_ENUM
) {
1075 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
1077 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
1080 type_name
= (char *)g_malloc (type_len
+ 1);
1081 memcpy (type_name
, named
, type_len
);
1082 type_name
[type_len
] = 0;
1084 /* FIXME: lookup the type and check type consistency */
1087 /* named argument name: length, then name */
1088 if (!decode_blob_size_checked(named
, data_end
, &name_len
, &named
, error
))
1090 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
1092 name
= (char *)g_malloc (name_len
+ 1);
1093 memcpy (name
, named
, name_len
);
1094 name
[name_len
] = 0;
1096 if (named_type
== CATTR_TYPE_FIELD
) {
1097 /* Named arg is a field. */
1099 MonoClassField
*field
= mono_class_get_field_from_name_full (attrklass
, name
, NULL
);
1106 arginfo
[j
].type
= field
->type
;
1107 arginfo
[j
].field
= field
;
1109 obj
= load_cattr_value_boxed (domain
, image
, field
->type
, named
, data_end
, &named
, error
);
1110 if (!is_ok (error
)) {
1114 mono_array_setref (namedargs
, j
, obj
);
1116 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
1117 /* Named arg is a property */
1119 MonoType
*prop_type
;
1120 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
1122 if (!prop
|| !prop
->set
) {
1127 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
1128 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
1130 arginfo
[j
].type
= prop_type
;
1131 arginfo
[j
].prop
= prop
;
1133 obj
= load_cattr_value_boxed (domain
, image
, prop_type
, named
, data_end
, &named
, error
);
1134 if (!is_ok (error
)) {
1138 mono_array_setref (namedargs
, j
, obj
);
1143 *typed_args
= typedargs
;
1144 *named_args
= namedargs
;
1147 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
1149 *named_arg_info
= NULL
;
1153 * mono_reflection_create_custom_attr_data_args_noalloc:
1155 * Same as mono_reflection_create_custom_attr_data_args_noalloc but allocate no managed objects, return values
1156 * using C arrays. Only usable for cattrs with primitive/type arguments.
1157 * TYPED_ARGS, NAMED_ARGS, and NAMED_ARG_INFO should be freed using g_free ().
1160 mono_reflection_create_custom_attr_data_args_noalloc (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
,
1161 gpointer
**typed_args
, gpointer
**named_args
, int *num_named_args
,
1162 CattrNamedArg
**named_arg_info
, MonoError
*error
)
1164 gpointer
*typedargs
, *namedargs
;
1165 MonoClass
*attrklass
;
1166 const char *p
= (const char*)data
;
1167 const char *data_end
= p
+ len
;
1169 guint32 i
, j
, num_named
;
1170 CattrNamedArg
*arginfo
= NULL
;
1171 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
1175 *named_arg_info
= NULL
;
1179 if (!mono_verifier_verify_cattr_content (image
, method
, data
, len
, error
))
1182 mono_class_init (method
->klass
);
1184 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
1190 typedargs
= g_new0 (gpointer
, sig
->param_count
);
1192 for (i
= 0; i
< sig
->param_count
; ++i
) {
1193 typedargs
[i
] = load_cattr_value (image
, sig
->params
[i
], NULL
, p
, data_end
, &p
, error
);
1194 return_if_nok (error
);
1199 /* Parse mandatory count of named arguments (could be zero) */
1200 if (!bcheck_blob (named
, 1, data_end
, error
))
1202 num_named
= read16 (named
);
1203 namedargs
= g_new0 (gpointer
, num_named
);
1204 return_if_nok (error
);
1206 attrklass
= method
->klass
;
1208 arginfo
= g_new0 (CattrNamedArg
, num_named
);
1209 *named_arg_info
= arginfo
;
1210 *num_named_args
= num_named
;
1212 /* Parse each named arg, and add to arginfo. Each named argument could
1213 * be a field name or a property name followed by a value. */
1214 for (j
= 0; j
< num_named
; j
++) {
1216 char *name
, named_type
, data_type
;
1217 if (!bcheck_blob (named
, 1, data_end
, error
))
1219 named_type
= *named
++; /* field or property? */
1220 data_type
= *named
++; /* type of data */
1221 if (data_type
== MONO_TYPE_SZARRAY
) {
1222 if (!bcheck_blob (named
, 0, data_end
, error
))
1224 data_type
= *named
++;
1226 if (data_type
== MONO_TYPE_ENUM
) {
1229 if (!decode_blob_size_checked (named
, data_end
, &type_len
, &named
, error
))
1231 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, type_len
, data
+ len
))
1234 type_name
= (char *)g_malloc (type_len
+ 1);
1235 memcpy (type_name
, named
, type_len
);
1236 type_name
[type_len
] = 0;
1238 /* FIXME: lookup the type and check type consistency */
1241 /* named argument name: length, then name */
1242 if (!decode_blob_size_checked(named
, data_end
, &name_len
, &named
, error
))
1244 if (ADDP_IS_GREATER_OR_OVF ((const guchar
*)named
, name_len
, data
+ len
))
1246 name
= (char *)g_malloc (name_len
+ 1);
1247 memcpy (name
, named
, name_len
);
1248 name
[name_len
] = 0;
1250 if (named_type
== CATTR_TYPE_FIELD
) {
1251 /* Named arg is a field. */
1252 MonoClassField
*field
= mono_class_get_field_from_name_full (attrklass
, name
, NULL
);
1259 arginfo
[j
].type
= field
->type
;
1260 arginfo
[j
].field
= field
;
1262 namedargs
[j
] = load_cattr_value (image
, field
->type
, NULL
, named
, data_end
, &named
, error
);
1263 if (!is_ok (error
)) {
1267 } else if (named_type
== CATTR_TYPE_PROPERTY
) {
1268 /* Named arg is a property */
1269 MonoType
*prop_type
;
1270 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
1272 if (!prop
|| !prop
->set
) {
1277 prop_type
= prop
->get
? mono_method_signature_internal (prop
->get
)->ret
:
1278 mono_method_signature_internal (prop
->set
)->params
[mono_method_signature_internal (prop
->set
)->param_count
- 1];
1280 arginfo
[j
].type
= prop_type
;
1281 arginfo
[j
].prop
= prop
;
1283 namedargs
[j
] = load_cattr_value (image
, prop_type
, NULL
, named
, data_end
, &named
, error
);
1284 if (!is_ok (error
)) {
1292 *typed_args
= typedargs
;
1293 *named_args
= namedargs
;
1296 mono_error_set_generic_error (error
, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
1298 *named_arg_info
= NULL
;
1302 reflection_resolve_custom_attribute_data (MonoReflectionMethod
*ref_method
, MonoReflectionAssembly
*assembly
, gpointer data
, guint32 len
, MonoArray
**ctor_args
, MonoArray
**named_args
, MonoError
*error
)
1305 MonoArray
*typedargs
, *namedargs
;
1308 CattrNamedArg
*arginfo
= NULL
;
1319 image
= assembly
->assembly
->image
;
1320 method
= ref_method
->method
;
1321 domain
= mono_object_domain (ref_method
);
1323 if (!mono_class_init (method
->klass
)) {
1324 mono_error_set_for_class_failure (error
, method
->klass
);
1328 mono_reflection_create_custom_attr_data_args (image
, method
, (const guchar
*)data
, len
, &typedargs
, &namedargs
, &arginfo
, error
);
1329 goto_if_nok (error
, leave
);
1331 if (!typedargs
|| !namedargs
)
1334 for (i
= 0; i
< mono_method_signature_internal (method
)->param_count
; ++i
) {
1335 MonoObject
*obj
= mono_array_get (typedargs
, MonoObject
*, i
);
1336 MonoObject
*typedarg
;
1339 t
= mono_method_signature_internal (method
)->params
[i
];
1340 if (t
->type
== MONO_TYPE_OBJECT
&& obj
)
1341 t
= m_class_get_byval_arg (obj
->vtable
->klass
);
1342 typedarg
= create_cattr_typed_arg (t
, obj
, error
);
1344 goto_if_nok (error
, leave
);
1345 mono_array_setref (typedargs
, i
, typedarg
);
1348 for (i
= 0; i
< mono_array_length_internal (namedargs
); ++i
) {
1349 MonoObject
*obj
= mono_array_get (namedargs
, MonoObject
*, i
);
1350 MonoObject
*typedarg
, *namedarg
, *minfo
;
1352 if (arginfo
[i
].prop
) {
1353 minfo
= (MonoObject
*)mono_property_get_object_checked (domain
, NULL
, arginfo
[i
].prop
, error
);
1357 minfo
= (MonoObject
*)mono_field_get_object_checked (domain
, NULL
, arginfo
[i
].field
, error
);
1358 goto_if_nok (error
, leave
);
1361 typedarg
= create_cattr_typed_arg (arginfo
[i
].type
, obj
, error
);
1362 goto_if_nok (error
, leave
);
1363 namedarg
= create_cattr_named_arg (minfo
, typedarg
, error
);
1364 goto_if_nok (error
, leave
);
1366 mono_array_setref (namedargs
, i
, namedarg
);
1369 *ctor_args
= typedargs
;
1370 *named_args
= namedargs
;
1374 return mono_error_ok (error
);
1378 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod
*ref_method
, MonoReflectionAssembly
*assembly
, gpointer data
, guint32 len
, MonoArray
**ctor_args
, MonoArray
**named_args
)
1381 (void) reflection_resolve_custom_attribute_data (ref_method
, assembly
, data
, len
, ctor_args
, named_args
, error
);
1382 mono_error_set_pending_exception (error
);
1386 try_get_cattr_data_class (MonoError
* error
)
1389 MonoClass
*res
= mono_class_try_get_customattribute_data_class ();
1391 mono_error_set_execution_engine (error
, "Class System.Reflection.CustomAttributeData not found, probably removed by the linker");
1395 static MonoObjectHandle
1396 create_custom_attr_data (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoError
*error
)
1398 HANDLE_FUNCTION_ENTER ();
1400 static MonoMethod
*ctor
;
1407 g_assert (image
->assembly
);
1408 MonoObjectHandle attr
;
1410 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
1411 goto_if_nok (error
, result_null
);
1414 MonoMethod
*tmp
= mono_class_get_method_from_name_checked (cattr_data
, ".ctor", 4, 0, error
);
1415 mono_error_assert_ok (error
);
1418 mono_memory_barrier (); //safe publish!
1422 domain
= mono_domain_get ();
1424 attr
= mono_object_new_handle (domain
, cattr_data
, error
);
1425 goto_if_nok (error
, fail
);
1427 MonoReflectionMethodHandle ctor_obj
;
1428 ctor_obj
= mono_method_get_object_handle (domain
, cattr
->ctor
, NULL
, error
);
1429 goto_if_nok (error
, fail
);
1430 MonoReflectionAssemblyHandle assm
;
1431 assm
= mono_assembly_get_object_handle (domain
, image
->assembly
, error
);
1432 goto_if_nok (error
, fail
);
1433 params
[0] = MONO_HANDLE_RAW (ctor_obj
);
1434 params
[1] = MONO_HANDLE_RAW (assm
);
1435 params
[2] = &cattr
->data
;
1436 params
[3] = &cattr
->data_size
;
1438 mono_runtime_invoke_handle (ctor
, attr
, params
, error
);
1441 attr
= MONO_HANDLE_CAST (MonoObject
, mono_new_null ());
1443 HANDLE_FUNCTION_RETURN_REF (MonoObject
, attr
);
1449 create_custom_attr_data_into_array (MonoImage
*image
, MonoCustomAttrEntry
*cattr
, MonoArrayHandle result
, int index
, MonoError
*error
)
1451 // This function serves to avoid creating handles in a loop.
1452 HANDLE_FUNCTION_ENTER ();
1453 MonoObjectHandle attr
= create_custom_attr_data (image
, cattr
, error
);
1454 goto_if_nok (error
, exit
);
1455 MONO_HANDLE_ARRAY_SETREF (result
, index
, attr
);
1457 HANDLE_FUNCTION_RETURN ();
1460 static MonoArrayHandle
1461 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
, MonoError
*error
)
1463 HANDLE_FUNCTION_ENTER ();
1465 MonoArrayHandle result
;
1470 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1471 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1472 if (!centry
->ctor
) {
1473 /* The cattr type is not finished yet */
1474 /* We should include the type name but cinfo doesn't contain it */
1475 mono_error_set_type_load_name (error
, NULL
, NULL
, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1482 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1483 MonoMethod
*ctor
= cinfo
->attrs
[i
].ctor
;
1485 if (mono_class_is_assignable_from_internal (attr_klass
, ctor
->klass
))
1489 n
= cinfo
->num_attrs
;
1492 result
= mono_array_new_cached_handle (mono_domain_get (), mono_defaults
.attribute_class
, n
, error
);
1493 goto_if_nok (error
, return_null
);
1495 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1496 MonoCustomAttrEntry
*centry
= &cinfo
->attrs
[i
];
1497 if (!attr_klass
|| mono_class_is_assignable_from_internal (attr_klass
, centry
->ctor
->klass
)) {
1498 create_custom_attr_into_array (cinfo
->image
, centry
->ctor
, centry
->data
,
1499 centry
->data_size
, result
, n
, error
);
1500 goto_if_nok (error
, exit
);
1506 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
1508 HANDLE_FUNCTION_RETURN_REF (MonoArray
, result
);
1512 * mono_custom_attrs_construct:
1515 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
1517 HANDLE_FUNCTION_ENTER ();
1519 MonoArrayHandle result
= mono_custom_attrs_construct_by_type (cinfo
, NULL
, error
);
1520 mono_error_assert_ok (error
); /*FIXME proper error handling*/
1521 HANDLE_FUNCTION_RETURN_OBJ (result
);
1524 static MonoArrayHandle
1525 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
, MonoError
*error
)
1527 HANDLE_FUNCTION_ENTER ();
1529 MonoArrayHandle result
;
1530 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
1531 goto_if_nok (error
, return_null
);
1533 result
= mono_array_new_handle (mono_domain_get (), cattr_data
, cinfo
->num_attrs
, error
);
1534 goto_if_nok (error
, return_null
);
1535 for (int i
= 0; i
< cinfo
->num_attrs
; ++i
) {
1536 create_custom_attr_data_into_array (cinfo
->image
, &cinfo
->attrs
[i
], result
, i
, error
);
1537 goto_if_nok (error
, return_null
);
1541 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
1543 HANDLE_FUNCTION_RETURN_REF (MonoArray
, result
);
1547 * mono_custom_attrs_from_index:
1549 * Returns: NULL if no attributes are found or if a loading error occurs.
1552 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
1555 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1556 mono_error_cleanup (error
);
1560 * mono_custom_attrs_from_index_checked:
1561 * \returns NULL if no attributes are found. On error returns NULL and sets \p error.
1564 mono_custom_attrs_from_index_checked (MonoImage
*image
, guint32 idx
, gboolean ignore_missing
, MonoError
*error
)
1566 guint32 mtoken
, i
, len
;
1567 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
1569 MonoCustomAttrInfo
*ainfo
;
1570 GList
*tmp
, *list
= NULL
;
1572 MonoCustomAttrEntry
* attr
;
1576 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1578 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
1582 while (i
< ca
->rows
) {
1583 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
1585 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
1588 len
= g_list_length (list
);
1591 ainfo
= (MonoCustomAttrInfo
*)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * len
);
1592 ainfo
->num_attrs
= len
;
1593 ainfo
->image
= image
;
1594 for (i
= len
, tmp
= list
; i
!= 0; --i
, tmp
= tmp
->next
) {
1595 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
1596 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
1597 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
1598 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
1599 mtoken
|= MONO_TOKEN_METHOD_DEF
;
1601 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
1602 mtoken
|= MONO_TOKEN_MEMBER_REF
;
1605 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
1608 attr
= &ainfo
->attrs
[i
- 1];
1609 attr
->ctor
= mono_get_method_checked (image
, mtoken
, NULL
, NULL
, error
);
1611 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image
->name
, mtoken
, mono_error_get_message (error
));
1612 if (ignore_missing
) {
1613 mono_error_cleanup (error
);
1622 if (!mono_verifier_verify_cattr_blob (image
, cols
[MONO_CUSTOM_ATTR_VALUE
], error
)) {
1627 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
1628 attr
->data_size
= mono_metadata_decode_value (data
, &data
);
1629 attr
->data
= (guchar
*)data
;
1637 * mono_custom_attrs_from_method:
1640 mono_custom_attrs_from_method (MonoMethod
*method
)
1643 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_method_checked (method
, error
);
1644 mono_error_cleanup (error
); /* FIXME want a better API that doesn't swallow the error */
1649 mono_custom_attrs_from_method_checked (MonoMethod
*method
, MonoError
*error
)
1656 * An instantiated method has the same cattrs as the generic method definition.
1658 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1659 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1661 if (method
->is_inflated
)
1662 method
= ((MonoMethodInflated
*) method
)->declaring
;
1664 if (method_is_dynamic (method
) || image_is_dynamic (m_class_get_image (method
->klass
)))
1665 return lookup_custom_attr (m_class_get_image (method
->klass
), method
);
1668 /* Synthetic methods */
1671 idx
= mono_method_get_index (method
);
1672 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1673 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
1674 return mono_custom_attrs_from_index_checked (m_class_get_image (method
->klass
), idx
, FALSE
, error
);
1678 * mono_custom_attrs_from_class:
1681 mono_custom_attrs_from_class (MonoClass
*klass
)
1684 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_class_checked (klass
, error
);
1685 mono_error_cleanup (error
);
1690 mono_custom_attrs_from_class_checked (MonoClass
*klass
, MonoError
*error
)
1696 if (mono_class_is_ginst (klass
))
1697 klass
= mono_class_get_generic_class (klass
)->container_class
;
1699 if (image_is_dynamic (m_class_get_image (klass
)))
1700 return lookup_custom_attr (m_class_get_image (klass
), klass
);
1702 if (m_class_get_byval_arg (klass
)->type
== MONO_TYPE_VAR
|| m_class_get_byval_arg (klass
)->type
== MONO_TYPE_MVAR
) {
1703 idx
= mono_metadata_token_index (m_class_get_sizes (klass
).generic_param_token
);
1704 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1705 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
1707 idx
= mono_metadata_token_index (m_class_get_type_token (klass
));
1708 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1709 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
1711 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1715 * mono_custom_attrs_from_assembly:
1718 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
1721 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_assembly_checked (assembly
, FALSE
, error
);
1722 mono_error_cleanup (error
);
1727 mono_custom_attrs_from_assembly_checked (MonoAssembly
*assembly
, gboolean ignore_missing
, MonoError
*error
)
1733 if (image_is_dynamic (assembly
->image
))
1734 return lookup_custom_attr (assembly
->image
, assembly
);
1735 idx
= 1; /* there is only one assembly */
1736 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1737 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
1738 return mono_custom_attrs_from_index_checked (assembly
->image
, idx
, ignore_missing
, error
);
1741 static MonoCustomAttrInfo
*
1742 mono_custom_attrs_from_module (MonoImage
*image
, MonoError
*error
)
1748 if (image_is_dynamic (image
))
1749 return lookup_custom_attr (image
, image
);
1750 idx
= 1; /* there is only one module */
1751 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1752 idx
|= MONO_CUSTOM_ATTR_MODULE
;
1753 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1757 * mono_custom_attrs_from_property:
1760 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
1763 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_property_checked (klass
, property
, error
);
1764 mono_error_cleanup (error
);
1769 mono_custom_attrs_from_property_checked (MonoClass
*klass
, MonoProperty
*property
, MonoError
*error
)
1775 if (image_is_dynamic (m_class_get_image (klass
))) {
1776 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
1777 return lookup_custom_attr (m_class_get_image (klass
), property
);
1779 idx
= find_property_index (klass
, property
);
1780 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1781 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
1782 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1786 * mono_custom_attrs_from_event:
1789 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
1792 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_event_checked (klass
, event
, error
);
1793 mono_error_cleanup (error
);
1798 mono_custom_attrs_from_event_checked (MonoClass
*klass
, MonoEvent
*event
, MonoError
*error
)
1804 if (image_is_dynamic (m_class_get_image (klass
))) {
1805 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
1806 return lookup_custom_attr (m_class_get_image (klass
), event
);
1808 idx
= find_event_index (klass
, event
);
1809 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1810 idx
|= MONO_CUSTOM_ATTR_EVENT
;
1811 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1815 * mono_custom_attrs_from_field:
1818 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
1821 MonoCustomAttrInfo
* result
= mono_custom_attrs_from_field_checked (klass
, field
, error
);
1822 mono_error_cleanup (error
);
1827 mono_custom_attrs_from_field_checked (MonoClass
*klass
, MonoClassField
*field
, MonoError
*error
)
1832 if (image_is_dynamic (m_class_get_image (klass
))) {
1833 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
1834 return lookup_custom_attr (m_class_get_image (klass
), field
);
1836 idx
= find_field_index (klass
, field
);
1837 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1838 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
1839 return mono_custom_attrs_from_index_checked (m_class_get_image (klass
), idx
, FALSE
, error
);
1843 * mono_custom_attrs_from_param:
1844 * \param method handle to the method that we want to retrieve custom parameter information from
1845 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1847 * The result must be released with mono_custom_attrs_free().
1849 * \returns the custom attribute object for the specified parameter, or NULL if there are none.
1852 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
1855 MonoCustomAttrInfo
*result
= mono_custom_attrs_from_param_checked (method
, param
, error
);
1856 mono_error_cleanup (error
);
1861 * mono_custom_attrs_from_param_checked:
1862 * \param method handle to the method that we want to retrieve custom parameter information from
1863 * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
1864 * \param error set on error
1866 * The result must be released with mono_custom_attrs_free().
1868 * \returns the custom attribute object for the specified parameter, or NULL if there are none. On failure returns NULL and sets \p error.
1871 mono_custom_attrs_from_param_checked (MonoMethod
*method
, guint32 param
, MonoError
*error
)
1874 guint32 i
, idx
, method_index
;
1875 guint32 param_list
, param_last
, param_pos
, found
;
1877 MonoReflectionMethodAux
*aux
;
1882 * An instantiated method has the same cattrs as the generic method definition.
1884 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1885 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1887 if (method
->is_inflated
)
1888 method
= ((MonoMethodInflated
*) method
)->declaring
;
1890 if (image_is_dynamic (m_class_get_image (method
->klass
))) {
1891 MonoCustomAttrInfo
*res
, *ainfo
;
1894 aux
= (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)m_class_get_image (method
->klass
))->method_aux_hash
, method
);
1895 if (!aux
|| !aux
->param_cattr
)
1898 /* Need to copy since it will be freed later */
1899 ainfo
= aux
->param_cattr
[param
];
1902 size
= MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * ainfo
->num_attrs
;
1903 res
= (MonoCustomAttrInfo
*)g_malloc0 (size
);
1904 memcpy (res
, ainfo
, size
);
1908 image
= m_class_get_image (method
->klass
);
1909 method_index
= mono_method_get_index (method
);
1912 ca
= &image
->tables
[MONO_TABLE_METHOD
];
1914 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
1915 if (method_index
== ca
->rows
) {
1916 ca
= &image
->tables
[MONO_TABLE_PARAM
];
1917 param_last
= ca
->rows
+ 1;
1919 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
1920 ca
= &image
->tables
[MONO_TABLE_PARAM
];
1923 for (i
= param_list
; i
< param_last
; ++i
) {
1924 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
1925 if (param_pos
== param
) {
1933 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1934 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
1935 return mono_custom_attrs_from_index_checked (image
, idx
, FALSE
, error
);
1939 * mono_custom_attrs_has_attr:
1942 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
1945 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
1946 MonoCustomAttrEntry
*centry
= &ainfo
->attrs
[i
];
1947 if (centry
->ctor
== NULL
)
1949 MonoClass
*klass
= centry
->ctor
->klass
;
1950 if (klass
== attr_klass
|| mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE_INTERNAL (attr_klass
) && mono_class_is_assignable_from_internal (attr_klass
, klass
)))
1957 * mono_custom_attrs_get_attr:
1960 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
1963 MonoObject
*res
= mono_custom_attrs_get_attr_checked (ainfo
, attr_klass
, error
);
1964 mono_error_assert_ok (error
); /*FIXME proper error handling*/
1969 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
, MonoError
*error
)
1972 MonoCustomAttrEntry
*centry
= NULL
;
1974 g_assert (attr_klass
!= NULL
);
1978 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
1979 centry
= &ainfo
->attrs
[i
];
1980 if (centry
->ctor
== NULL
)
1982 MonoClass
*klass
= centry
->ctor
->klass
;
1983 if (attr_klass
== klass
|| mono_class_is_assignable_from_internal (attr_klass
, klass
)) {
1984 HANDLE_FUNCTION_ENTER ();
1985 MonoObjectHandle result
= create_custom_attr (ainfo
->image
, centry
->ctor
, centry
->data
, centry
->data_size
, error
);
1986 HANDLE_FUNCTION_RETURN_OBJ (result
);
1994 * mono_reflection_get_custom_attrs_info:
1995 * \param obj a reflection object handle
1997 * \returns the custom attribute info for attributes defined for the
1998 * reflection handle \p obj. The objects.
2000 * FIXME this function leaks like a sieve for SRE objects.
2003 mono_reflection_get_custom_attrs_info (MonoObject
*obj_raw
)
2005 HANDLE_FUNCTION_ENTER ();
2007 MONO_HANDLE_DCL (MonoObject
, obj
);
2008 MonoCustomAttrInfo
*result
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2009 mono_error_assert_ok (error
);
2010 HANDLE_FUNCTION_RETURN_VAL (result
);
2014 * mono_reflection_get_custom_attrs_info_checked:
2015 * \param obj a reflection object handle
2016 * \param error set on error
2018 * \returns the custom attribute info for attributes defined for the
2019 * reflection handle \p obj. The objects. On failure returns NULL and sets \p error.
2021 * FIXME this function leaks like a sieve for SRE objects.
2024 mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj
, MonoError
*error
)
2026 HANDLE_FUNCTION_ENTER ();
2028 MonoCustomAttrInfo
*cinfo
= NULL
;
2032 klass
= mono_handle_class (obj
);
2033 const char *klass_name
= m_class_get_name (klass
);
2034 if (klass
== mono_defaults
.runtimetype_class
) {
2035 MonoType
*type
= mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST(MonoReflectionType
, obj
), error
);
2036 goto_if_nok (error
, leave
);
2037 klass
= mono_class_from_mono_type_internal (type
);
2038 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
2039 cinfo
= mono_custom_attrs_from_class_checked (klass
, error
);
2040 goto_if_nok (error
, leave
);
2041 } else if (strcmp ("Assembly", klass_name
) == 0 || strcmp ("MonoAssembly", klass_name
) == 0) {
2042 MonoReflectionAssemblyHandle rassembly
= MONO_HANDLE_CAST (MonoReflectionAssembly
, obj
);
2043 cinfo
= mono_custom_attrs_from_assembly_checked (MONO_HANDLE_GETVAL (rassembly
, assembly
), FALSE
, error
);
2044 goto_if_nok (error
, leave
);
2045 } else if (strcmp ("Module", klass_name
) == 0 || strcmp ("MonoModule", klass_name
) == 0) {
2046 MonoReflectionModuleHandle module
= MONO_HANDLE_CAST (MonoReflectionModule
, obj
);
2047 cinfo
= mono_custom_attrs_from_module (MONO_HANDLE_GETVAL (module
, image
), error
);
2048 goto_if_nok (error
, leave
);
2049 } else if (strcmp ("MonoProperty", klass_name
) == 0) {
2050 MonoReflectionPropertyHandle rprop
= MONO_HANDLE_CAST (MonoReflectionProperty
, obj
);
2051 MonoProperty
*property
= MONO_HANDLE_GETVAL (rprop
, property
);
2052 cinfo
= mono_custom_attrs_from_property_checked (property
->parent
, property
, error
);
2053 goto_if_nok (error
, leave
);
2054 } else if (strcmp ("MonoEvent", klass_name
) == 0) {
2055 MonoReflectionMonoEventHandle revent
= MONO_HANDLE_CAST (MonoReflectionMonoEvent
, obj
);
2056 MonoEvent
*event
= MONO_HANDLE_GETVAL (revent
, event
);
2057 cinfo
= mono_custom_attrs_from_event_checked (event
->parent
, event
, error
);
2058 goto_if_nok (error
, leave
);
2059 } else if (strcmp ("MonoField", klass_name
) == 0) {
2060 MonoReflectionFieldHandle rfield
= MONO_HANDLE_CAST (MonoReflectionField
, obj
);
2061 MonoClassField
*field
= MONO_HANDLE_GETVAL (rfield
, field
);
2062 cinfo
= mono_custom_attrs_from_field_checked (field
->parent
, field
, error
);
2063 goto_if_nok (error
, leave
);
2064 } else if ((strcmp ("MonoMethod", klass_name
) == 0) || (strcmp ("MonoCMethod", klass_name
) == 0)) {
2065 MonoReflectionMethodHandle rmethod
= MONO_HANDLE_CAST (MonoReflectionMethod
, obj
);
2066 cinfo
= mono_custom_attrs_from_method_checked (MONO_HANDLE_GETVAL (rmethod
, method
), error
);
2067 goto_if_nok (error
, leave
);
2068 } else if (strcmp ("ParameterInfo", klass_name
) == 0 || strcmp ("MonoParameterInfo", klass_name
) == 0) {
2069 MonoReflectionParameterHandle param
= MONO_HANDLE_CAST (MonoReflectionParameter
, obj
);
2070 MonoObjectHandle member_impl
= MONO_HANDLE_NEW_GET (MonoObject
, param
, MemberImpl
);
2071 MonoClass
*member_class
= mono_handle_class (member_impl
);
2072 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
2073 MonoReflectionMethodHandle rmethod
= MONO_HANDLE_CAST (MonoReflectionMethod
, member_impl
);
2074 cinfo
= mono_custom_attrs_from_param_checked (MONO_HANDLE_GETVAL (rmethod
, method
), MONO_HANDLE_GETVAL (param
, PositionImpl
) + 1, error
);
2075 goto_if_nok (error
, leave
);
2076 } else if (mono_is_sr_mono_property (member_class
)) {
2077 MonoReflectionPropertyHandle prop
= MONO_HANDLE_CAST (MonoReflectionProperty
, member_impl
);
2078 MonoProperty
*property
= MONO_HANDLE_GETVAL (prop
, property
);
2080 if (!(method
= property
->get
))
2081 method
= property
->set
;
2084 cinfo
= mono_custom_attrs_from_param_checked (method
, MONO_HANDLE_GETVAL (param
, PositionImpl
) + 1, error
);
2085 goto_if_nok (error
, leave
);
2087 #ifndef DISABLE_REFLECTION_EMIT
2088 else if (mono_is_sre_method_on_tb_inst (member_class
)) {/*XXX This is a workaround for Compiler Context*/
2089 // FIXME: Is this still needed ?
2090 g_assert_not_reached ();
2091 } else if (mono_is_sre_ctor_on_tb_inst (member_class
)) { /*XX This is a workaround for Compiler Context*/
2092 // FIXME: Is this still needed ?
2093 g_assert_not_reached ();
2097 char *type_name
= mono_type_get_full_name (member_class
);
2098 mono_error_set_not_supported (error
,
2099 "Custom attributes on a ParamInfo with member %s are not supported",
2104 } else if (strcmp ("AssemblyBuilder", klass_name
) == 0) {
2105 MonoReflectionAssemblyBuilderHandle assemblyb
= MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder
, obj
);
2106 MonoReflectionAssemblyHandle assembly
= MONO_HANDLE_CAST (MonoReflectionAssembly
, assemblyb
);
2107 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, assemblyb
, cattrs
);
2108 MonoImage
* image
= MONO_HANDLE_GETVAL (assembly
, assembly
)->image
;
2110 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, image
, cattrs
);
2111 } else if (strcmp ("TypeBuilder", klass_name
) == 0) {
2112 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, obj
);
2113 MonoReflectionModuleBuilderHandle module
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, tb
, module
);
2114 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (module
, dynamic_image
);
2115 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, tb
, cattrs
);
2116 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2117 } else if (strcmp ("ModuleBuilder", klass_name
) == 0) {
2118 MonoReflectionModuleBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionModuleBuilder
, obj
);
2119 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (mb
, dynamic_image
);
2120 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, mb
, cattrs
);
2121 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2122 } else if (strcmp ("ConstructorBuilder", klass_name
) == 0) {
2123 MonoReflectionCtorBuilderHandle cb
= MONO_HANDLE_CAST (MonoReflectionCtorBuilder
, obj
);
2124 MonoMethod
*mhandle
= MONO_HANDLE_GETVAL (cb
, mhandle
);
2125 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, cb
, cattrs
);
2126 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, m_class_get_image (mhandle
->klass
), cattrs
);
2127 } else if (strcmp ("MethodBuilder", klass_name
) == 0) {
2128 MonoReflectionMethodBuilderHandle mb
= MONO_HANDLE_CAST (MonoReflectionMethodBuilder
, obj
);
2129 MonoMethod
*mhandle
= MONO_HANDLE_GETVAL (mb
, mhandle
);
2130 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, mb
, cattrs
);
2131 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, m_class_get_image (mhandle
->klass
), cattrs
);
2132 } else if (strcmp ("FieldBuilder", klass_name
) == 0) {
2133 MonoReflectionFieldBuilderHandle fb
= MONO_HANDLE_CAST (MonoReflectionFieldBuilder
, obj
);
2134 MonoReflectionTypeBuilderHandle tb
= MONO_HANDLE_CAST (MonoReflectionTypeBuilder
, MONO_HANDLE_NEW_GET (MonoReflectionType
, fb
, typeb
));
2135 MonoReflectionModuleBuilderHandle mb
= MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder
, tb
, module
);
2136 MonoDynamicImage
*dynamic_image
= MONO_HANDLE_GETVAL (mb
, dynamic_image
);
2137 MonoArrayHandle cattrs
= MONO_HANDLE_NEW_GET (MonoArray
, fb
, cattrs
);
2138 cinfo
= mono_custom_attrs_from_builders_handle (NULL
, &dynamic_image
->image
, cattrs
);
2139 } else if (strcmp ("MonoGenericClass", klass_name
) == 0) {
2140 MonoReflectionGenericClassHandle gclass
= MONO_HANDLE_CAST (MonoReflectionGenericClass
, obj
);
2141 MonoReflectionTypeHandle generic_type
= MONO_HANDLE_NEW_GET (MonoReflectionType
, gclass
, generic_type
);
2142 cinfo
= mono_reflection_get_custom_attrs_info_checked (MONO_HANDLE_CAST (MonoObject
, generic_type
), error
);
2143 goto_if_nok (error
, leave
);
2144 } else { /* handle other types here... */
2145 g_error ("get custom attrs not yet supported for %s", m_class_get_name (klass
));
2149 HANDLE_FUNCTION_RETURN_VAL (cinfo
);
2153 * mono_reflection_get_custom_attrs_by_type:
2154 * \param obj a reflection object handle
2155 * \returns an array with all the custom attributes defined of the
2156 * reflection handle \p obj. If \p attr_klass is non-NULL, only custom attributes
2157 * of that type are returned. The objects are fully build. Return NULL if a loading error
2161 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj_raw
, MonoClass
*attr_klass
, MonoError
*error
)
2163 HANDLE_FUNCTION_ENTER ();
2164 MONO_HANDLE_DCL (MonoObject
, obj
);
2165 MonoArrayHandle result
= mono_reflection_get_custom_attrs_by_type_handle (obj
, attr_klass
, error
);
2166 HANDLE_FUNCTION_RETURN_OBJ (result
);
2170 mono_reflection_get_custom_attrs_by_type_handle (MonoObjectHandle obj
, MonoClass
*attr_klass
, MonoError
*error
)
2172 MonoArrayHandle result
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2173 MonoCustomAttrInfo
*cinfo
;
2177 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2178 goto_if_nok (error
, leave
);
2180 MONO_HANDLE_ASSIGN (result
, mono_custom_attrs_construct_by_type (cinfo
, attr_klass
, error
));
2182 mono_custom_attrs_free (cinfo
);
2184 MONO_HANDLE_ASSIGN (result
, mono_array_new_handle (mono_domain_get (), mono_defaults
.attribute_class
, 0, error
));
2192 * mono_reflection_get_custom_attrs:
2193 * \param obj a reflection object handle
2194 * \return an array with all the custom attributes defined of the
2195 * reflection handle \p obj. The objects are fully build. Return NULL if a loading error
2199 mono_reflection_get_custom_attrs (MonoObject
*obj_raw
)
2201 HANDLE_FUNCTION_ENTER ();
2203 MONO_HANDLE_DCL (MonoObject
, obj
);
2204 MonoArrayHandle result
= mono_reflection_get_custom_attrs_by_type_handle (obj
, NULL
, error
);
2205 mono_error_cleanup (error
);
2206 HANDLE_FUNCTION_RETURN_OBJ (result
);
2210 * mono_reflection_get_custom_attrs_data:
2211 * \param obj a reflection obj handle
2212 * \returns an array of \c System.Reflection.CustomAttributeData,
2213 * which include information about attributes reflected on
2214 * types loaded using the Reflection Only methods
2217 mono_reflection_get_custom_attrs_data (MonoObject
*obj_raw
)
2219 HANDLE_FUNCTION_ENTER ();
2221 MONO_HANDLE_DCL (MonoObject
, obj
);
2222 MonoArrayHandle result
= mono_reflection_get_custom_attrs_data_checked (obj
, error
);
2223 mono_error_cleanup (error
);
2224 HANDLE_FUNCTION_RETURN_OBJ (result
);
2228 * mono_reflection_get_custom_attrs_data_checked:
2229 * @obj: a reflection obj handle
2230 * @error: set on error
2232 * Returns an array of System.Reflection.CustomAttributeData,
2233 * which include information about attributes reflected on
2234 * types loaded using the Reflection Only methods
2237 mono_reflection_get_custom_attrs_data_checked (MonoObjectHandle obj
, MonoError
*error
)
2239 MonoArrayHandle result
= MONO_HANDLE_NEW (MonoArray
, NULL
);
2240 MonoCustomAttrInfo
*cinfo
;
2244 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, error
);
2245 goto_if_nok (error
, leave
);
2247 MONO_HANDLE_ASSIGN (result
, mono_custom_attrs_data_construct (cinfo
, error
));
2249 mono_custom_attrs_free (cinfo
);
2250 goto_if_nok (error
, leave
);
2252 MonoClass
*cattr_data
= try_get_cattr_data_class (error
);
2253 goto_if_nok (error
, return_null
);
2255 MONO_HANDLE_ASSIGN (result
, mono_array_new_handle (mono_domain_get (), cattr_data
, 0, error
));
2259 result
= MONO_HANDLE_CAST (MonoArray
, mono_new_null ());
2265 custom_attr_class_name_from_methoddef (MonoImage
*image
, guint32 method_token
, const gchar
**nspace
, const gchar
**class_name
)
2267 /* mono_get_method_from_token () */
2268 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
);
2269 guint32 type_token
= mono_metadata_typedef_from_method (image
, method_token
);
2271 /* Bad method token (could not find corresponding typedef) */
2274 type_token
|= MONO_TOKEN_TYPE_DEF
;
2276 /* mono_class_create_from_typedef () */
2277 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2278 guint32 cols
[MONO_TYPEDEF_SIZE
];
2279 guint tidx
= mono_metadata_token_index (type_token
);
2281 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
2282 /* "Invalid typedef token %x", type_token */
2286 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2289 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2291 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2298 * custom_attr_class_name_from_method_token:
2299 * @image: The MonoImage
2300 * @method_token: a token for a custom attr constructor in @image
2301 * @assembly_token: out argment set to the assembly ref token of the custom attr
2302 * @nspace: out argument set to namespace (a string in the string heap of @image) of the custom attr
2303 * @class_name: out argument set to the class name of the custom attr.
2305 * Given an @image and a @method_token (which is assumed to be a
2306 * constructor), fills in the out arguments with the assembly ref (if
2307 * a methodref) and the namespace and class name of the custom
2310 * Returns: TRUE on success, FALSE otherwise.
2312 * LOCKING: does not take locks
2315 custom_attr_class_name_from_method_token (MonoImage
*image
, guint32 method_token
, guint32
*assembly_token
, const gchar
**nspace
, const gchar
**class_name
)
2317 /* This only works with method tokens constructed from a
2318 * custom attr token, which can only be methoddef or
2320 g_assert (mono_metadata_token_table (method_token
) == MONO_TABLE_METHOD
2321 || mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
);
2323 if (mono_metadata_token_table (method_token
) == MONO_TABLE_MEMBERREF
) {
2324 /* method_from_memberref () */
2326 guint32 nindex
, class_index
;
2328 int idx
= mono_metadata_token_index (method_token
);
2330 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], idx
-1, cols
, 3);
2331 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
2332 class_index
= cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
2333 if (class_index
== MONO_MEMBERREF_PARENT_TYPEREF
) {
2334 guint32 type_token
= MONO_TOKEN_TYPE_REF
| nindex
;
2335 /* mono_class_from_typeref_checked () */
2337 guint32 cols
[MONO_TYPEREF_SIZE
];
2338 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2340 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
2343 *class_name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2345 *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2347 *assembly_token
= cols
[MONO_TYPEREF_SCOPE
];
2350 } else if (class_index
== MONO_MEMBERREF_PARENT_METHODDEF
) {
2351 guint32 methoddef_token
= MONO_TOKEN_METHOD_DEF
| nindex
;
2353 *assembly_token
= 0;
2354 return custom_attr_class_name_from_methoddef (image
, methoddef_token
, nspace
, class_name
);
2356 /* Attributes can't be generic, so it won't be
2357 * a typespec, and they're always
2358 * constructors, so it won't be a moduleref */
2359 g_assert_not_reached ();
2362 /* must be MONO_TABLE_METHOD */
2364 *assembly_token
= 0;
2365 return custom_attr_class_name_from_methoddef (image
, method_token
, nspace
, class_name
);
2370 * mono_assembly_metadata_foreach_custom_attr:
2371 * \param assembly the assembly to iterate over
2372 * \param func the function to call for each custom attribute
2373 * \param user_data passed to \p func
2374 * Calls \p func for each custom attribute type on the given assembly until \p func returns TRUE.
2375 * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
2378 mono_assembly_metadata_foreach_custom_attr (MonoAssembly
*assembly
, MonoAssemblyMetadataCustomAttrIterFunc func
, gpointer user_data
)
2382 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
2387 * This might be called during assembly loading, so do everything using the low-level
2391 image
= assembly
->image
;
2392 /* Dynamic images would need to go through the AssemblyBuilder's
2393 * CustomAttributeBuilder array. Going through the tables below
2394 * definitely won't work. */
2395 g_assert (!image_is_dynamic (image
));
2396 idx
= 1; /* there is only one assembly */
2397 idx
<<= MONO_CUSTOM_ATTR_BITS
;
2398 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
2400 /* Inlined from mono_custom_attrs_from_index_checked () */
2401 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2402 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
2406 gboolean stop_iterating
= FALSE
;
2407 while (!stop_iterating
&& i
< ca
->rows
) {
2408 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
2410 mono_metadata_decode_row (ca
, i
, cols
, MONO_CUSTOM_ATTR_SIZE
);
2412 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
2413 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
2414 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
2415 mtoken
|= MONO_TOKEN_METHOD_DEF
;
2417 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
2418 mtoken
|= MONO_TOKEN_MEMBER_REF
;
2421 g_warning ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
2425 const char *nspace
= NULL
;
2426 const char *name
= NULL
;
2427 guint32 assembly_token
= 0;
2429 if (!custom_attr_class_name_from_method_token (image
, mtoken
, &assembly_token
, &nspace
, &name
))
2432 stop_iterating
= func (image
, assembly_token
, nspace
, name
, mtoken
, user_data
);
2437 init_weak_fields_inner (MonoImage
*image
, GHashTable
*indexes
)
2439 MonoTableInfo
*tdef
;
2441 MonoClass
*klass
= NULL
;
2442 guint32 memberref_index
= -1;
2443 int first_method_idx
= -1;
2444 int method_count
= -1;
2446 if (image
== mono_get_corlib ()) {
2448 klass
= mono_class_from_name_checked (image
, "System", "WeakAttribute", error
);
2449 if (!is_ok (error
)) {
2450 mono_error_cleanup (error
);
2455 first_method_idx
= mono_class_get_first_method_idx (klass
);
2456 method_count
= mono_class_get_method_count (klass
);
2458 tdef
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2459 guint32 parent
, field_idx
, col
, mtoken
, idx
;
2460 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2461 parent
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_PARENT
);
2462 if ((parent
& MONO_CUSTOM_ATTR_MASK
) != MONO_CUSTOM_ATTR_FIELDDEF
)
2465 col
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_TYPE
);
2466 mtoken
= col
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
2469 if ((col
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
2470 field_idx
= parent
>> MONO_CUSTOM_ATTR_BITS
;
2471 if (idx
>= first_method_idx
&& idx
< first_method_idx
+ method_count
)
2472 g_hash_table_insert (indexes
, GUINT_TO_POINTER (field_idx
), GUINT_TO_POINTER (1));
2476 /* Memberref pointing to a typeref */
2477 tdef
= &image
->tables
[MONO_TABLE_MEMBERREF
];
2479 /* Check whenever the assembly references the WeakAttribute type */
2480 gboolean found
= FALSE
;
2481 tdef
= &image
->tables
[MONO_TABLE_TYPEREF
];
2482 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2483 guint32 string_offset
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEREF_NAME
);
2484 const char *name
= mono_metadata_string_heap (image
, string_offset
);
2485 if (!strcmp (name
, "WeakAttribute")) {
2494 /* Find the memberref pointing to a typeref */
2495 tdef
= &image
->tables
[MONO_TABLE_MEMBERREF
];
2496 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2497 guint32 cols
[MONO_MEMBERREF_SIZE
];
2500 mono_metadata_decode_row (tdef
, i
, cols
, MONO_MEMBERREF_SIZE
);
2501 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
2502 mono_metadata_decode_blob_size (sig
, &sig
);
2504 guint32 nindex
= cols
[MONO_MEMBERREF_CLASS
] >> MONO_MEMBERREF_PARENT_BITS
;
2505 guint32 class_index
= cols
[MONO_MEMBERREF_CLASS
] & MONO_MEMBERREF_PARENT_MASK
;
2506 const char *fname
= mono_metadata_string_heap (image
, cols
[MONO_MEMBERREF_NAME
]);
2508 if (!strcmp (fname
, ".ctor") && class_index
== MONO_MEMBERREF_PARENT_TYPEREF
) {
2509 MonoTableInfo
*typeref_table
= &image
->tables
[MONO_TABLE_TYPEREF
];
2510 guint32 cols
[MONO_TYPEREF_SIZE
];
2512 mono_metadata_decode_row (typeref_table
, nindex
- 1, cols
, MONO_TYPEREF_SIZE
);
2514 const char *name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2515 const char *nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2517 if (!strcmp (nspace
, "System") && !strcmp (name
, "WeakAttribute")) {
2518 MonoClass
*klass
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| nindex
, error
);
2519 if (!is_ok (error
)) {
2520 mono_error_cleanup (error
);
2523 g_assert (!strcmp (m_class_get_name (klass
), "WeakAttribute"));
2524 /* Allow a testing dll as well since some profiles don't have WeakAttribute */
2525 if (klass
&& (m_class_get_image (klass
) == mono_get_corlib () || strstr (m_class_get_image (klass
)->name
, "Mono.Runtime.Testing"))) {
2526 /* Sanity check that it only has 1 ctor */
2527 gpointer iter
= NULL
;
2530 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2531 if (!strcmp (method
->name
, ".ctor"))
2535 memberref_index
= i
;
2541 if (memberref_index
== -1)
2544 tdef
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
2545 guint32 parent
, field_idx
, col
, mtoken
, idx
;
2546 for (int i
= 0; i
< tdef
->rows
; ++i
) {
2547 parent
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_PARENT
);
2548 if ((parent
& MONO_CUSTOM_ATTR_MASK
) != MONO_CUSTOM_ATTR_FIELDDEF
)
2551 col
= mono_metadata_decode_row_col (tdef
, i
, MONO_CUSTOM_ATTR_TYPE
);
2552 mtoken
= col
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
2555 field_idx
= parent
>> MONO_CUSTOM_ATTR_BITS
;
2556 if ((col
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_MEMBERREF
) {
2557 if (idx
== memberref_index
)
2558 g_hash_table_insert (indexes
, GUINT_TO_POINTER (field_idx
), GUINT_TO_POINTER (1));
2565 * mono_assembly_init_weak_fields:
2567 * Initialize the image->weak_field_indexes hash.
2570 mono_assembly_init_weak_fields (MonoImage
*image
)
2572 if (image
->weak_fields_inited
)
2575 GHashTable
*indexes
= NULL
;
2577 if (mono_get_runtime_callbacks ()->get_weak_field_indexes
)
2578 indexes
= mono_get_runtime_callbacks ()->get_weak_field_indexes (image
);
2580 indexes
= g_hash_table_new (NULL
, NULL
);
2583 * To avoid lookups for every field, we scan the customattr table for entries whose
2584 * parent is a field and whose type is WeakAttribute.
2586 init_weak_fields_inner (image
, indexes
);
2589 mono_image_lock (image
);
2590 if (!image
->weak_fields_inited
) {
2591 image
->weak_field_indexes
= indexes
;
2592 mono_memory_barrier ();
2593 image
->weak_fields_inited
= TRUE
;
2595 g_hash_table_destroy (indexes
);
2597 mono_image_unlock (image
);
2601 * mono_assembly_is_weak_field:
2603 * Return whenever the FIELD table entry with the 1-based index FIELD_IDX has
2604 * a [Weak] attribute.
2607 mono_assembly_is_weak_field (MonoImage
*image
, guint32 field_idx
)
2612 mono_assembly_init_weak_fields (image
);
2614 /* The hash is not mutated, no need to lock */
2615 return g_hash_table_lookup (image
->weak_field_indexes
, GINT_TO_POINTER (field_idx
)) != NULL
;